HarmonyOS 6商城开发学习:公共事件限定指定订阅者接收——subscriberPermissions与bundleName定向发布避坑指南
原创
在HarmonyOS 6购物比价或电商类应用中,有时需要通过 CES(Common Event Service,公共事件服务) 向其他应用/进程发自定义事件——比如"订单支付成功通知插件"、"门店POS端刷新待配货列表"。但公共事件是系统级广播,默认所有经 addCommonEventSubscriber订阅同事件名的应用都能收到,存在信息泄漏与不必要的唤醒风险。
官方行业FAQ明确给出两种限制手段:① 权限约束(subscriberPermissions/ publisherPermission)② 包名定向(bundleName指定收/发方)。本文将完整说明两种方案及代码实战。
一、现象:自定义公共事件被无关应用收到
1. 问题现场
// 发送方——发布自定义公共事件
commonEventManager.publish('com.shop.ORDER_PAID', {
data: '{"orderId":"O8848"}'
});
// 接收方——任意应用订阅同名事件
const subscriber = commonEventManager.createSubscriberSync({
events: ['com.shop.ORDER_PAID']
});
commonEventManager.subscribe(subscriber, (err, data) => { /* 收到 */ });
结果:设备上其他无关App若也订阅 'com.shop.ORDER_PAID'同样能收到——不符合"仅指定应用可收"的预期。
2. 根因揭秘
HarmonyOS 公共事件默认不做应用级隔离,仅靠事件名匹配。要约束接收范围须显式声明:
|
约束方式 |
做法 |
适用场景 |
|---|---|---|
|
权限约束 |
发送方 |
同一生态内多应用共享事件、有统一自定义权限 |
|
包名定向 |
发送方 |
明确点对点(如主应用→Widget/卡片、或 POS端→中台App) |
二、方案A(推荐定向收发):bundleName 指定接收包名
最适合 主应用 → 桌面卡片/服务卡片 / 门店端App 这种明确一对一或一对少数的场景。
1. 发送方——限定接收 bundleName
// utils/OrderEventPublisher.ets
import { commonEventManager } from '@kit.BasicServicesKit';
import { BusinessError } from '@kit.BasicServicesKit';
/**
* 发布"订单支付成功"定向公共事件
* @param targetBundleName 接收方包名,如 'com.example.shopwidget'
* @param orderId 支付成功的订单ID
*/
export function publishOrderPaid(targetBundleName: string, orderId: string): void {
const publishData: commonEventManager.CommonEventPublishData = {
bundleName: targetBundleName, // ✅ 关键:仅此 bundleName 的应用可收到
data: JSON.stringify({ orderId, ts: Date.now() }),
isOrdered: false // 无序事件即可
};
commonEventManager.publish(
'com.shop.ORDER_PAID',
publishData,
(err: BusinessError) => {
if (err) {
console.error(`publish ORDER_PAID err: ${err.code} ${err.message}`);
}
}
);
}
调用示例(支付回调中):
// 支付成功后
publishOrderPaid('com.example.shopwidget', 'O8848');
2. 订阅方——普通订阅即可(包名匹配自动放行)
// widget/ServiceCard 内
import { commonEventManager } from '@kit.BasicServicesKit';
const subscribeInfo: commonEventManager.CommonEventSubscribeInfo = {
events: ['com.shop.ORDER_PAID'],
// 可选:若想反过来只收指定主应用发的事件可加
// publisherBundleName: 'com.example.shopmain'
};
const subscriber = commonEventManager.createSubscriberSync(subscribeInfo);
commonEventManager.subscribe(subscriber, (err, data) => {
if (err) return;
const payload = JSON.parse(data!.data! '{}');
console.log(`[Widget] 收到订单支付: ${payload.orderId}`);
// 触发卡片刷新...
});
若发送方
bundleName与订阅方自身 bundleName 不匹配 → CES 直接丢弃该事件,订阅回调不触发。
三、方案B(生态多应用共享):权限约束 subscriberPermissions
适合同一厂商多条产品线(主App、Lite版、商家版)均需监听同一事件,且不想逐个列 bundleName。
1. 定义自定义权限(所有相关模块统一)
module.json5(发送方 & 接收方均需声明):
{
"reqPermissions": [
{
"name": "com.shop.permission.RECEIVE_ORDER_EVENT",
"reason": "接收订单支付公共事件",
"usedScene": { "abilities": ["EntryAbility"] }
}
],
"defPermissions": [
{
"name": "com.shop.permission.RECEIVE_ORDER_EVENT",
"grantMode": "system_grant", // 或 user_grant 视安全等级
"availableScope": ["bundle"]
}
]
}
2. 发送方声明 subscriberPermissions
const publishData: commonEventManager.CommonEventPublishData = {
subscriberPermissions: ['com.shop.permission.RECEIVE_ORDER_EVENT'],
data: JSON.stringify({ orderId: 'O8848', ts: Date.now() })
};
commonEventManager.publish('com.shop.ORDER_PAID', publishData, (err)=>{ /*...*/ });
3. 订阅方(已申请该权限即可收到)
订阅方 CommonEventSubscribeInfo可不额外配置(只要应用已获该权限)——若想反向限定只接收带此权限发布的事件,可设:
const subInfo: commonEventManager.CommonEventSubscribeInfo = {
events: ['com.shop.ORDER_PAID'],
publisherPermission: 'com.shop.permission.RECEIVE_ORDER_EVENT'
};
权限方式要求所有参与应用预装同一定义权限,适合企业分发/同厂商多App;对外部三方插件推荐用
bundleName定向。
四、避坑指南
|
问题 |
原因 |
修复 |
|---|---|---|
|
设了 |
订阅方自身 |
|
|
权限约束事件收不到 |
订阅方 module.json5 未声明 |
确认 |
|
想同时限定包名+权限 |
可同时设 |
通常二选一即可 |
|
动态订阅后台收不到 |
应用进程后台默认暂停动态订阅回调;需改用静态订阅(json5配 |
卡片/ServiceExtension 内用静态订阅保活接收 |
|
hidumper 查订阅者权限 |
|
用于联调验证 |
五、总结:公共事件限定订阅者 SOP
-
明确场景选方案
-
点对点 / 主应用↔卡片 →
CommonEventPublishData.bundleName = 接收方bundleName(最简单安全) -
同厂商多应用共享 → 自定义权限
subscriberPermissions+ module.json5 声明
-
-
发送方:
publish(event, { bundleName / subscriberPermissions, data }) -
订阅方:普通
createSubscriberSync({events});如需反向限定发送方包名或权限可设publisherBundleName/publisherPermission -
校验:用
hidumper -s 3299 -a -e确认 subscriber 属性生效
核心法则:HarmonyOS 6 中公共事件限制接收者 = "定向用 bundleName,群体用自定义权限 subscriberPermissions",默认不约束则系统内所有同名订阅者均可收到。
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任。
更多推荐


所有评论(0)