鸿蒙实况窗开发:只会liveViewManager?巧用Push Kit才能告别用户投诉!
鸿蒙实况窗开发:本地与云端双保险方案 本文针对鸿蒙实况窗开发中常见的进程依赖问题,提出了本地liveViewManager与云端Push Kit协同的解决方案: 问题分析:纯本地更新方案依赖App进程存活,后台易中断导致状态不同步 方案对比: liveViewManager:适合前台高频更新(如进度条) Push Kit:保障后台关键状态更新(如订单状态变更) 最佳实践: 创建时使用liveVie
鸿蒙实况窗开发:只会liveViewManager?巧用Push Kit才能告别用户投诉!
大家好啊~我是那个在代码海洋里扑腾了10+年的老水手,目前主业是"鸿蒙应用开发+Web全栈开发"双面间谍。
这些年写过的BUG能绕地球半圈,填过的坑能养活一个施工队,当然也攒了点有用的经验(毕竟吃一堑长一智嘛)。
平时最大的爱好就是把复杂的技术掰碎了、嚼烂了,做成普通人也能看懂的小甜点分享给大家。
如果你也喜欢折腾代码、踩坑、填坑,或者想找个人唠唠技术嗑,欢迎关注我一起交流~毕竟,独乐乐不如众乐乐,一起进步才是正经事!
上周夜里两点,我被一个报警电话吵醒。运营那边炸了锅:好几个用户投诉,打车打到一半,订单状态停在"司机已接单"死活不更新了。用户看不到车到哪儿,急得直骂街。
一查日志,好家伙,问题出在实况窗上。我们的小哥图省事儿,全程只用 liveViewManager 在App本地更新实况窗。结果用户切到后台刷了会儿短视频,进程一被回收,更新链就断了。司机那边都开到目的地了,用户手机上的实况窗还停留在十分钟前。
说白了,这就是掉进了 “本地更新依赖进程存活” 的大坑。今天咱就唠唠,怎么用 liveViewManager 和 Push Kit 打好配合,把这坑填得平平的。你想想,一个负责漂亮地"开场"和前台即时响应,一个负责稳定地"续命"和后台全局调度,这不挺合理的吗?
首先,咱得把事儿掰扯明白
看了官方文档,你可能觉得有两套东西都能管实况窗:liveViewManager 和 Push Kit。有点懵,对吧?其实啊,它俩是接力赛的关系,干的是同一件事(实况窗生命周期管理)的不同阶段。
liveViewManager (Live View Kit):这是客户端SDK。它的活儿是跟你App的UI线程紧密配合,创建第一个实况窗卡片,以及在App前台活跃时进行快速的本地更新。特点是快、即时。但它有个致命前提:你的App进程得活着,最好是在前台。
Push Kit:这是云端服务。它的核心能力是穿透。不管你的App是在后台还是被杀了,Push Kit的服务器都能通过系统通道,把更新指令推送到用户设备上,进而更新实况窗。它负责的是保活和全局状态同步。
所以,一个常见的误区是二选一。正确的姿势是:本地创建 + 云端推送更新。官方也是这么推荐的,为啥?为了可靠性。



关键抉择:这活儿该派给谁干?
| 更新方式 | 进程依赖 | 适用场景 | 生命周期限制 | 推荐优先级 |
|---|---|---|---|---|
| 本地更新 (liveViewManager.updateLiveView) |
需应用进程存活 | 前台服务即时状态(如:倒计时、进度条实时刷新) | 进程退出即失效 | ★★☆ |
| 推送更新 (Push Kit) |
无进程依赖 | 跨进程/离线场景(如:订单状态变更、物流轨迹更新) | 最长8小时超时 | ★★★ |
本地 (liveViewManager) 分支:连接"用户刚下单,APP在前台"、“短时、连续的状态微调(如进度条每1%更新)”、“APP始终在前台的特殊场景(如内置导航)”。
远程 (Push Kit) 分支:连接"APP转入后台或进程可能被杀"、“关键状态节点更新(如司机已接单->已到达)”、“最终结束实况窗”、“用户长时间未操作APP”。
翻译成人话就是:
- 创建时刻,用 liveViewManager。用户点完外卖,App还亮着,这时候立刻弹出"订单已接收"的实况窗,体验最丝滑。
- 常规持续更新,优先用 Push Kit。特别是那些决定性的状态跳转,比如"商家已接单 -> 骑手已取餐 -> 已送达"。这些节点必须触达,不管App在干嘛。
- 如果你的应用场景特殊,要求极高频率、极低延迟的连续更新(比如一个秒级的锻炼计时器),并且你能保证App前台存活,那可以用 liveViewManager 本地更新。但得小心系统频控,别更太猛。
- 结束时刻,用 Push Kit。服务完成了,云端发个指令干净利落地结束它,最保险。
决策做完,咱们上代码看看具体怎么搞
实战 Part 1: 用 liveViewManager 漂亮地开场
假设我们做一个外卖取餐场景。首先,得检查用户有没有把咱们的实况窗开关给关了(设置里能找到),这是前提。
import { liveViewManager } from '@kit.LiveViewKit';
import { wantAgent } from '@kit.AbilityKit';
export class LiveViewService {
// 1. 检查开关,这步不能省
private static async checkLiveViewSwitch(): Promise<boolean> {
return await liveViewManager.isLiveViewEnabled();
}
// 2. 创建一个取餐实况窗(强调文本模板)
public async startPickUpLiveView(orderId: number, code: string, shopName: string): Promise<void> {
try {
const isEnabled = await LiveViewService.checkLiveViewSwitch();
if (!isEnabled) {
console.warn('实况窗开关被用户关闭,无法创建');
return;
}
const liveView: liveViewManager.LiveView = {
id: orderId, // 用订单ID作为实况窗唯一ID,方便后续更新关联
event: 'PICK_UP', // 场景类型,必须和申请的场景一致
liveViewData: {
primary: {
title: '餐品已备好',
content: [
{ text: '请前往 ' },
{ text: shopName, textColor: '#FF0A59F7' }, // 强调色
{ text: ' 取餐' }
],
clickAction: await this.buildWantAgent(), // 点击卡片跳回App
layoutData: {
layoutType: liveViewManager.LayoutType.LAYOUT_TYPE_PICKUP,
title: '取餐码',
content: code, // 取餐号
underlineColor: '#FF0A59F7',
descPic: 'resource://rawfile/coffee.png' // 旁边放个咖啡图
}
},
// 3. 同步创建一个胶囊(状态栏显示)
capsule: {
type: liveViewManager.CapsuleType.CAPSULE_TYPE_TEXT,
status: 1,
content: `取餐码 ${code}`,
icon: 'resource://rawfile/capsule_icon.png',
backgroundColor: '#FF0A59F7'
}
}
};
const result = await liveViewManager.startLiveView(liveView);
if (result.resultCode !== 0) {
console.error('创建实况窗失败:', result.message);
}
} catch (error) {
console.error('启动实况窗异常:', error);
}
}
private async buildWantAgent() {
// 构造点击实况窗后想要跳转的Ability信息,具体代码参考官方wantAgent文档
const wantAgentInfo = {/* ... */};
return await wantAgent.getWantAgent(wantAgentInfo);
}
}
看这段代码,几个关键点:
- id 很重要,它是后续云端推送更新的唯一依据。
- event 要和你在AGC后台申请的场景对上。
- 顺手把 capsule (胶囊) 也创建了,用户不点卡片也能在状态栏看到关键信息。
- 图片路径用 resource://rawfile/ 开头,别写错了。
好了,现在用户下单后,一个漂亮的取餐实况窗就弹出来了。但它还是个"宝宝",离不开妈妈(App进程)。接下来,我们得给它找个"云保姆"。
实战 Part 2: 用 Push Kit 当坚实的云保姆
Push Kit 的活主要在后端。流程是这样的:
- App 用 Push Kit 拿到一个设备标识 pushToken,并把它和刚才的 orderId(即实况窗 id)一起上传给你的业务服务器。
- 当订单状态在后台变化时(比如商家接单),你的业务服务器调用华为 Push Kit 的服务端API,发送一条更新消息。
- 这条消息会通过系统通道直接推送到用户设备,系统负责更新实况窗,完全不需要你的App醒来。
关键就在服务端发的这条消息。我们看看一个"更新取餐状态"的推送请求大概长啥样:
// 这是你的后台服务(比如Node.js)需要构造和发送的请求
const https = require('https');
const updateLiveViewViaPush = async (projectId, accessToken, pushToken, orderId, newStatus) => {
const data = JSON.stringify({
payload: {
activityId: orderId, // 必须和本地创建的 liveView.id 一致!
operation: 1, // 1代表更新,0创建,2结束
event: 'PICK_UP',
status: newStatus, // 新状态,如'READY_FOR_PICKUP'
version: Date.now(), // 版本号,确保更新有序,后发的要比先发的大
activityData: {
notificationData: {
type: 4, // LAYOUT_TYPE_PICKUP 在推送API中对应值,查文档确认
contentTitle: '餐品已备好', // 可以更新标题
contentText: [{ text: `取餐码已更新为 ${newCode}` }], // 更新内容
// ... 其他可以更新的字段,参考推送实况窗消息文档
}
},
token: [pushToken] // 推送给哪个设备
}
});
const options = {
hostname: 'push-api.cloud.huawei.com',
path: `/v3/${projectId}/messages:send`,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${accessToken}`,
'push-type': '7' // 固定值7,代表实况窗消息
}
};
const req = https.request(options, (res) => {
// 处理响应...
});
req.write(data);
req.end();
};
这里有几个血泪经验:
- activityId 和 id 必须是同一个东西,不然系统对不上号。
- version 要递增,防止旧消息覆盖新消息(网络延迟可能导致顺序错乱)。
- push-type: 7 这个头千万别忘了,否则会被当成普通推送处理。
- 开通权益:在AGC后台,不光要开通"实况窗服务权益",如果要用Push Kit更新,还得先开通 “推送服务权益” ,并且在项目设置里把数据处理位置设好(通常是中国)。没设对,消息根本下不去。
绕不开的坑和最佳姿势
- 别更太猛,有频控:系统怕你刷屏。打车和赛事场景,每小时最多更180次;其他场景每小时最多60次。超了的直接丢。
- 保序很重要:本地更新靠 sequence 字段,云端更新靠 version 字段。确保后发的数字比当前的大。
- 生命周期不是无限的:单个实况窗最多活8小时。超过4小时没任何更新,系统就直接帮你结束了。所以关键状态要及时推。
- 设计规范是红线:你的实况窗长得丑、乱发广告、或者用在非场景(比如当成普通促销推送),轻则审核不过,重则权益被封。老老实实按设计规范来。
- 联调测试:在AGC后台"调测设备管理"里添加上你开发板的设备信息,开通测试权限。先用测试消息 (testMessage: true) 把流程跑通,每天有额度限制。
最后,串起来的工作流
唠了这么多,咱们把整个最佳实践串成一张图,你照着做就行:
- 用户下单,App在前台。
- 调用 liveViewManager.startLiveView(…) 本地创建实况窗(含胶囊)。
- 同时,App将 { orderId, pushToken, event } 绑定,上报给业务服务器。
- (用户切到后台,甚至杀进程)
- 订单状态变化(商家接单)。
- 业务服务器调用 Push Kit 服务端API,发送 operation=1 的更新消息。
- 华为Push服务器将消息送达用户设备。
- 系统自动更新实况窗界面。
- 订单完成,业务服务器调用 Push Kit API,发送 operation=2 的结束消息。
- 系统移除实况窗。
说到底,技术选型没有银弹。liveViewManager 和 Push Kit 在鸿蒙实况窗生态里就是一对黄金搭档。一个管"出生"和"高频心跳",一个管"一生照料"和"善终"。理解它俩的分工,才能写出既体验流畅又稳定可靠的服务。
下次再设计实况窗,别光想着 liveViewManager.updateLiveView 那一行代码了。问问自己:“万一用户这会儿不在我App里,这消息还能不能准点到?” 想明白这个问题,你就知道该怎么做了。
希望这篇能帮你省下半夜接报警电话的功夫。如果有更奇葩的坑,欢迎来找我唠唠,一起填坑,比一个人折腾有意思多了。
更多推荐



所有评论(0)