OpenHarmony开发者论坛
标题:
OpenHarmony公共事件基本原理解
[打印本页]
作者:
Laval社区小助手
时间:
2024-1-8 11:25
标题:
OpenHarmony公共事件基本原理解
[md]## 简介
**OpenHarmony通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。**
**公共事件根据发送方不同可分为系统公共事件和自定义公共事件。**
* **系统公共事件:系统将收集到的事件信息,根据系统策略发送给订阅该事件的用户程序。 例如:系统关键服务发布的系统事件(例如:hap安装,更新,卸载等)。**
* **自定义公共事件:应用自定义一些公共事件用来实现跨应用的事件通信能力。**
**每个应用都可以按需订阅公共事件,订阅成功且公共事件发布,系统会把其发送给应用。这些公共事件可能来自系统、其他应用和应用自身。**
![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony%E5%85%AC%E5%85%B1%E4%BA%8B%E4%BB%B6%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86/img/ces.png?lastModify=1686127308)
![](
https://devpress.csdnimg.cn/620403828bdd46628db2389a7efdabe6.png
)
**commonEvent接口的方法如下:**
![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony%E5%85%AC%E5%85%B1%E4%BA%8B%E4%BB%B6%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86/img/commonEventUsage.png?lastModify=1686127308)
![](
https://devpress.csdnimg.cn/90e33e7056e9450393049667499447ff.png
)
## 名词解释
### 订阅者信息(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)
> **用于作为订阅公共事件的载体,订阅公共事件并获取公共事件传递而来的参数。详细信息请参考**[CommonEvent文档/CommonEventSubscriber](
https://gitee.com/openharmony/do ... ber?login=from_csdn
)
| **方法名称** | **描述** |
| ------------------------------- | ------------------------------------------------------------------------------------------ |
| **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}** | **否** | **表示公共事件的附加信息。** |
#### **有序公共事件:**
> **当一个无序公共事件发布时,该公共事件的所有订阅者会同时收到发布信息。**
>
> **当一个有序公共事件发布时,该公共事件的所有订阅者会根据优先级高低依次收到发布信息。**
#### **粘性公共事件:**
> **非粘性公共事件: 公共事件的订阅动作必须在公共事件发布之前进行。**
>
> **必须订阅者先订阅,然后公共事件发布,订阅者才可以接收到公共事件发布的信息。**
>
> **粘性公共事件: 公共事件的订阅动作可以在公共事件发布之后进行。**
>
> **可以先发布公共事件,然后订阅者再订阅,依然可以收到公共事件发布的信息。**
## 公共事件开发指导:
### 订阅、退订公共事件
> 1. **设置订阅信息(公共事件名称、订阅者优先级等)**
> 2. **使用订阅信息创建订阅者**
> 3. **使用订阅者订阅、退订**
**系统公共事件名称请参考**[CommonEvent文档/公共事件列表](
https://gitee.com/openharmony/do ... %A8?login=from_csdn
)
```
//步骤一: 导入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订阅公共事件。**
### 时序图如下:
![](
https://devpress.csdnimg.cn/21978e81137f4d76a5717ddee5356122.png
)
![](file:///C:/Users/kuangansheng/Desktop/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E8%AF%BE%E7%A8%8B%E6%A1%88%E4%BE%8BFAQ/%E5%85%AC%E5%BC%80%E8%AF%BE%E7%A8%8B/OpenHarmony%E5%85%AC%E5%85%B1%E4%BA%8B%E4%BB%B6%E7%9A%84%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86/img/demo1.png?lastModify=1686127308)
### 应用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
}
})
})
}
}
}
}
```
### 操作流程:
> 1. **A应用创建订阅者、订阅**
> 2. **B应用创建订阅者、订阅**
> 3. **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公共事件.**[
https://gitee.com/openharmony/do ... apis-commonEvent.md
](
https://gitee.com/openharmony/do ... .md?login=from_csdn
)
[/md]
欢迎光临 OpenHarmony开发者论坛 (https://forums.openharmony.cn/)
Powered by Discuz! X3.5