OpenHarmony公共事件基本原理解
简介
OpenHarmony通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。
公共事件根据发送方不同可分为系统公共事件和自定义公共事件。
-
系统公共事件:系统将收集到的事件信息,根据系统策略发送给订阅该事件的用户程序。 例如:系统关键服务发布的系统事件(例如:hap安装,更新,卸载等)。
-
每个应用都可以按需订阅公共事件,订阅成功且公共事件发布,系统会把其发送给应用。这些公共事件可能来自系统、其他应用和应用自身。


commonEvent接口的方法如下:


名词解释
订阅者信息(CommonEventSubscribeInfo)
用于设置订阅的一些基本信息,在创建订阅者时使用。
| 名称 | 读写属性 | 类型 | 必填 | 描述 |
|---|---|---|---|---|
| events | 只读 | Array<string> | 是 | 表示订阅的公共事件,一个订阅者可以订阅多个公共事件。 |
| publisherPermission | 只读 | string | 否 | 表示发布者的权限。发布者必须具有该权限才可以发布公共事件给该订阅者,该订阅者只接收具有该权限的发布者发布的公共事件。 |
| publisherDeviceId | 只读 | string | 否 | 表示设备ID,该值必须是同一ohos网络上的现有设备ID。 |
| userId | 只读 | number | 否 | 表示用户ID。此参数是可选的,默认值当前用户的ID。如果指定了此参数,则该值必须是系统中现有的用户ID。 |
| priority | 只读 | number | 否 | 表示订阅者的优先级,值的范围是-100到1000。数值越大,订阅者的优先级别越高,在有序公共事件发布时越先接收到发布信息。 |
写法示例:
let subscribeInfo: any = { events: ["event1","event2"], userId: 100, priority: 200, }
订阅者(Subscriber)
用于作为订阅公共事件的载体,订阅公共事件并获取公共事件传递而来的参数。详细信息请参考
| 方法名称 | 描述 |
|---|---|
| getCode | 获取公共事件的结果代码 |
| setCode | 设置公共事件的结果代码 |
| getData | 获取公共事件的结果数据 |
| setData | 设置公共事件的结果数据 |
| setCodeAndData | 设置公共事件的结果代码和结果数据 |
| isOrderedCommonEvent | 查询当前公共事件的是否为有序公共事件 |
| isStickyCommonEvent | 检查当前公共事件是否为一个粘性事件 |
| abortCommonEvent | 取消当前的公共事件,仅对有序公共事件有效,取消后,公共事件不再向下一个订阅者传递 |
| clearAbortCommonEvent | 清除当前公共事件的取消状态,仅对有序公共事件有效 |
| getAbortCommonEvent | 获取当前有序公共事件是否取消的状态 |
| getSubscribeInfo | 获取订阅者的订阅信息 |
| finishCommonEvent | 结束当前有序公共事件 |
公共事件数据(CommonEventData)
通过订阅者成功订阅公共事件之后,返回的订阅的公共事件的一些基本信息。
| 名称 | 读写属性 | 类型 | 必填 | 描述 |
|---|---|---|---|---|
| event | 只读 | string | 是 | 表示当前接收的公共事件名称。 |
| bundleName | 只读 | string | 否 | 表示包名称。 |
| code | 只读 | number | 否 | 表示公共事件的结果代码,用于传递int类型的数据,默认为0。 |
| data | 只读 | string | 否 | 表示公共事件的自定义结果数据,用于传递string类型的数据。 |
| parameters | 只读 | {[key: string]: any} | 否 | 表示公共事件的附加信息。 |
公共事件发布信息(CommonEventPublishData)
在发布公共事件时使用,用于设置发布的公共事件的一些基本信息。
| 名称 | 类型 | 必填 | 描述 |
|---|---|---|---|
| bundleName | string | 否 | 表示包名称。 |
| code | number | 否 | 表示公共事件的结果代码。 |
| data | string | 否 | 表示公共事件的自定义结果数据。 |
| subscriberPermissions | Array<string> | 否 | 表示订阅者的权限。 |
| isOrdered | boolean | 否 | 表示是否是有序事件。 |
| isSticky | boolean | 否 | 表示是否是粘性事件。 |
| parameters | {[key: string]: any} | 否 | 表示公共事件的附加信息。 |
有序公共事件:
当一个无序公共事件发布时,该公共事件的所有订阅者会同时收到发布信息。
当一个有序公共事件发布时,该公共事件的所有订阅者会根据优先级高低依次收到发布信息。
粘性公共事件:
非粘性公共事件: 公共事件的订阅动作必须在公共事件发布之前进行。
必须订阅者先订阅,然后公共事件发布,订阅者才可以接收到公共事件发布的信息。
粘性公共事件: 公共事件的订阅动作可以在公共事件发布之后进行。
可以先发布公共事件,然后订阅者再订阅,依然可以收到公共事件发布的信息。
公共事件开发指导:
订阅、退订公共事件
设置订阅信息(公共事件名称、订阅者优先级等)
使用订阅信息创建订阅者
使用订阅者订阅、退订
系统公共事件名称请参考
//步骤一: 导入commonEvent模块 import commonEvent from "@ohos.commonEvent"; //步骤二: 创建订阅信息,订阅者信息的数据类型及包含的参数请参考名词解释 let subscribeInfo : any = { events : ["testEvent"], //要订阅的公共事件 userId : 100, //用户Id priority : 1, //该订阅者的优先级 } let subscriberA = undefined //步骤三:创建订阅者 commonEvent.createSubscriber(subscribeInfo, (err, subscriber) => { if (err?.code) { console.log("[CommonEvent] CreateSubscriber CallBack err=" + JSON.stringify(err)) } else { console.log("[CommonEvent] CreateSubscriber") this.subscriberA = subscriber //将创建订阅者回调生成的订阅者赋给subscriberA } }) //步骤四: 订阅公共事件 commonEvent.subscribe(subscriberA, (err, data) => { if (err?.code) { console.log("[CommonEvent] SubscribeCallBack err=" + JSON.stringify(err)) } else { console.log("[CommonEvent] SubscribeCallBack data=" + JSON.stringify(data)) } }) //退订公共事件 commonEvent.unsubscribe(subscriberA, err=>{ if(err?.code){ console.log("[CommonEvent] unSubscribeCallBack err=" + JSON.stringify(err)) }else{ console.log("[CommonEvent] unSubscribeCallBack succeed") } })
发布公共事件
开发者可以发布四种公共事件:无序的公共事件、有序的公共事件、带权限的公共事件、粘性的公共事件。
import commonEvent from "@ohos.commonEvent"; //步骤一:设置公共事件发布信息,具体参数信息请参考名词解释 let commonEventPublishData = { data : "test data", isOrdered: true, //设置为有序公共事件 code : 13178, isSticky : true, //设置为粘性公共事件 parameters : { //公共事件发布时,携带的参数 a : "aa", b : 'bb', c : 'cc' } } //步骤二:发布公共事件testEvent commonEvent.publish("testEvent", commonEventPublishData,(err) => { if (err?.code) { Logger.info("[CommonEvent] Publish CallBack err=" + JSON.stringify(err)) } else { Logger.info("[CommonEvent] Publish testEvent succeed ") } })
开发示例
此处以应用间的公共事件发布、订阅为例,应用A发布公共事件,应用B订阅公共事件。
时序图如下:


应用A中代码如下:
三个操作: 创建订阅者、订阅、发布公共事件testEvent
import commonEvent from '@ohos.commonEvent'; @Entry @Component struct TestA { @State publishCount: number = 0 @State createSubscriberCount: number = 0 @State SubscribetestEventCount: number = 0 subscriberOftestEvent : any = undefined build() { Row() { Column() { //步骤一:创建订阅者 Button('Create Subscriber Of testEvent: '+ this.createSubscriberCount).type(ButtonType.Capsule).fontSize(30).margin({bottom: 15}) .onClick(()=>{ this.createSubscriberCount+=1 let subscribeInfo: any= { events: ["testEvent"] } commonEvent.createSubscriber(subscribeInfo, (err, subscriber) => { if (err.code) { console.log("[CommonEvent]CreateSubscriberCallBack err=" + JSON.stringify(err)) } else { console.log("[CommonEvent]CreateSubscriber") this.subscriberOftestEvent = subscriber } }) }) //步骤二:订阅公共事件testEvent Button('Subscribe testEvent: '+ this.SubscribetestEventCount).type(ButtonType.Capsule).fontSize(30).margin({bottom: 30}) .onClick(()=>{ console.log("come in !!!") this.SubscribetestEventCount+=1 console.log(`this.subscriberOftestEvent : ${JSON.stringify(this.subscriberOftestEvent)}`) commonEvent.subscribe(this.subscriberOftestEvent, (err, data) => { if (err?.code) { console.log("[CommonEvent] SubscribeCallBack err=" + JSON.stringify(err)) } else { this.SubscribetestEventCount+=1 console.log("[CommonEvent] SubscribeCallBack data=" + JSON.stringify(data)) } }) }) //步骤三:发布公共事件testEvent Button('Publish testEvent : ' + this.publishCount).fontSize(30).margin({bottom: 15}) .onClick(()=>{ this.publishCount+=1 commonEvent.publish("testEvent", (err) => { console.log(`err${JSON.stringify(err)}`) if (err?.code) { console.log("[CommonEvent] PublishCallBack err=" + JSON.stringify(err)) } else { console.log("[CommonEvent] Publish Succeed ") } }) }) } .width('100%') } .height('100%') } }
应用B中代码如下:
只订阅应用A发布的公共事件testEvent
import commonEvent from '@ohos.commonEvent'; @Component @Entry struct TestB{ @State dCount : number = 0 @State result : string = "待订阅" @State createSubscriberInfo : string = "待创建" subscriber : any = undefined subscribeInfo: any= { events: ["testEvent"], } build(){ Column(){ Column(){ //步骤一:创建订阅者 Button('创建订阅者: '+ this.createSubscriberInfo).type(ButtonType.Capsule).fontSize(40) .onClick(()=>{ //创建订阅者回调 commonEvent.createSubscriber(this.subscribeInfo, (err, subscriber) => { if (err?.code) { console.log("[CommonEvent] CreateSubscriberCallBack err=" + JSON.stringify(err)) } else { console.log("[CommonEvent] CreateSubscriber") this.subscriber = subscriber this.createSubscriberInfo = "Create subscriber succeed" } }) }) //步骤二:订阅 Button('订阅公共事件testEvent: '+ this.dCount+this.result).type(ButtonType.Capsule).fontSize(40) .onClick(()=>{ commonEvent.subscribe(this.subscriber, (err, data) => { if (err?.code) { console.log("[CommonEvent]SubscribeCallBack err=" + JSON.stringify(err)) } else { this.dCount+=1 console.log("[CommonEvent]SubscribeCallBack data=" + JSON.stringify(data)) this.result = "receive, event = " + data.event + ", data = " + data.data + ", code = " + data.code } }) }) } } } }
操作流程:
A应用创建订阅者、订阅
B应用创建订阅者、订阅
A应用发布公共事件testEvent
(顺序不能乱,因为这里发布的不是粘性公共事件)
公共事件调试助手cem
公共事件与通知提供了供开发者查看公共事件信息及通知信息、发布公共事件等一些调试功能的工具。
这些工具已经随系统集成,开发者进入shell环境,可以直接调用相关命令。
publish发布公共事件
参数如下表所示
| 参数 | 参数说明 |
|---|---|
| -e/--event | 必选参数,发布事件名称 |
| -s/--sticky | 可选参数,发布粘性事件,默认发布非粘性事件 |
| -o/--ordered | 可选参数,发布有序事件,默认发布无序事件 |
| -c/--code | 可选参数,公共事件结果码 |
| -d/--data | 可选参数,公共事件携带数据 |
| -h/--help | 帮助信息 |
用法示例:
# 发布名称为testevent的公共事件 cem publish --event "testevent" # 发布名称为testevent的粘性有序公共事件,该事件的结果码为100,携带数据内容为“this is data” cem publish -e "testevent" -s -o -c 100 -d "this is data"
dump打印公共事件相关信息
参数如下表所示
| 参数 | 参数说明 |
|---|---|
| -a/--all | 打印开机以来所有已发送的公共事件及其具体信息 |
| -e/--event | 查询特定名称事件的具体信息 |
| -h/--help | 帮助信息 |
用法示例:
# 打印公共事件名称为testevent的具体信息 cem dump -e "testevent"
打印出来的信息如下:
Subscribers: No information Sticky Events: No information Pending Events: No information History Events: Total 1 information NO 1 Time: 20170805 10:12 AM PID: 2099 UID: 20010037 USERID: ALL_USER BundleName: com.ohos.dtest RequiredPermission: # 发布者所要求的权限 IsSticky: false # 发布的事件是否是粘性事件 IsOrdered: false # 发布的事件是否是有序事件 IsSystemApp: false # 发布者是否是系统应用 IsSystemEvent: false # 发布的事件是否是系统事件 Want: Action: testevent # 发布的事件名称 Entity: Scheme: Uri: Flags: 0 Type: BundleName: AbilityName: DevicedID: Code: 0 # 有序事件的结果码,仅在有序事件下有效 Data: # 事件携带的数据 HasLastSubscriber: false # 是否有最终订阅者,仅在有序事件下有效 EventState: RECEIVED # 事件发送状态 ReceiverTime: 0 DispatchTime: 0 ResultAbort: false # 事件是否被终止,仅在有序事件下有效 Subscribers: Total 1 subscribers # 所有可以接收该事件的订阅者信息 NO 1 Time: 20170805 10:11 AM BundleName: com.ohos.dtest # 事件订阅者的包名 Priority: 0 # 订阅者的优先级,仅在订阅有序 USERID: ALL_USER # 作为子系统订阅者,没有指定用户ID的情况下,默认订阅所有的用户; # 如果是三方应用,则只能订阅这个包对应的用户ID,且不允许订阅其他的用户。 Permission: # 订阅者所要求的权限 DevicedID: IsFreeze: false # 订阅者是否被冻结,被冻结的订阅者将无法收到事件 FreezeTime: - EventState: DELIVERED # 订阅者接收状态
-
发布者EventState有三种状态:
-
IDLE表示没有订阅者或者有序事件正在等待处理下一个订阅者;
-
RECEIVEING表示该订阅者们仍然在处理该事件;
-
RECEIVED表示所有订阅已经处理完成,事件发送完成。
-
-
订阅者EventState有四种状态:
-
PENDING表示订阅者仍在等待处理事件;
-
DELIVERED表示订阅者已经完成接收;
-
SKIPPED表示该订阅者不能接收该事件,常见于权限不匹配或者订阅者被冻结的情况下;
-
TIMEOUT仅出现在有序事件下,表示该订阅者处理事件超时。
-
参考文献
[1]OpenHarmony公共事件.
更多推荐

所有评论(0)