OpenHarmony应用开发-进程间通讯
版本:v3.2 Beta5
进程模型
OpenHarmony的进程模型如下图所示:
- 应用中(同一包名)的所有UIAbility、ServiceExtensionAbility、DataShareExtensionAbility运行在同一个独立进程中,即图中绿色部分的“Main Process”。
- 应用中(同一包名)的同一类型ExtensionAbility(除ServiceExtensionAbility和DataShareExtensionAbility外)运行在一个独立进程中,即图中蓝色部分的“FormExtensionAbility Process”、“InputMethodExtensionAbility Process”、其他ExtensionAbility Process。
- WebView拥有独立的渲染进程,即图中黄色部分的“Render Process”。
图1进程模型示意图
在上述模型基础上,对于系统应用可以通过申请多进程权限(如下图所示),为指定HAP配置一个自定义进程名,该HAP中的UIAbility、DataShareExtensionAbility、ServiceExtensionAbility就会运行在自定义进程中。不同的HAP可以通过配置不同的进程名运行在不同进程中。
图2 多进程示意图
基于OpenHarmony的进程模型,系统中应用间和应用内都会存在多个进程的情况,因此系统提供了如下两种进程间通信机制:
- 公共事件机制:多用于一对多的通信场景,公共事件发布者可能存在多个订阅者同时接收事件。
- 后台服务机制:当前主要通过ServiceExtensionAbility的能力实现。
公共事件简介
OpenHarmony通过CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力。
公共事件从系统角度可分为:系统公共事件和自定义公共事件。
- 系统公共事件:CES内部定义的公共事件,只有系统应用和系统服务才能发布,例如HAP安装,更新,卸载等公共事件。目前支持的系统公共事件详见系统公共事件列表。
- 自定义公共事件:应用自定义一些公共事件用来实现跨进程的事件通信能力。
公共事件按发送方式可分为:无序公共事件、有序公共事件和粘性公共事件。
- 无序公共事件:CES转发公共事件时,不考虑订阅者是否接收到,且订阅者接收到的顺序与其订阅顺序无关。
- 有序公共事件:CES转发公共事件时,根据订阅者设置的优先级等级,在接收到优先级较高的一个订阅者回复后,再向下一个优先级较低的订阅者转发公共事件。具有相同优先级的订阅者将按随机顺序收到公共事件。
- 粘性公共事件:能够让订阅者收到在订阅前已经发送的公共事件就是粘性公共事件。普通的公共事件只能在订阅后发送才能收到,而粘性公共事件的特殊性就是可以先发送后订阅,同时也支持先订阅后发送。发送粘性事件必须是系统应用或系统服务,粘性事件发送后会一直存在系统中,且发送者需要申请
ohos.permission.COMMONEVENT_STICKY
权限,配置方式请参见访问控制授权申请。
每个应用都可以按需订阅公共事件,订阅成功,当公共事件发布时,系统会将其发送给对应的应用。这些公共事件可能来自系统、其他应用和应用自身。
图1 公共事件示意图
公共事件订阅概述
公共事件服务提供了动态订阅和静态订阅两种订阅方式。动态订阅与静态订阅最大的区别在于,动态订阅是应用运行时行为,而静态订阅是后台服务无需处于运行状态。
- 动态订阅:指订阅方在运行时调用公共事件订阅的API实现对公共事件的订阅,详见动态订阅公共事件。
- 静态订阅:订阅方通过配置文件声明和实现继承自StaticSubscriberExtensionAbility的类实现对公共事件的订阅,详见静态订阅公共事件。
动态订阅公共事件
场景介绍
动态订阅是指当应用在运行状态时对某个公共事件进行订阅,在运行期间如果有订阅的事件发布那么订阅了这个事件的应用将会收到该事件及其传递的参数。例如,某应用希望在其运行期间收到电量过低的事件,并根据该事件降低其运行功耗,那么该应用便可动态订阅电量过低事件,收到该事件后关闭一些非必要的任务来降低功耗。订阅部分系统公共事件需要先申请权限,订阅这些事件所需要的权限请见公共事件权限列表。
接口说明
详细接口见接口文档。
接口名 | 接口描述 |
createSubscriber(subscribeInfo: CommonEventSubscribeInfo, callback: AsyncCallback<CommonEventData>): void | 创建订阅者对象(callback) |
createSubscriber(subscribeInfo: CommonEventSubscribeInfo): Promise<CommonEventSubscriber> | 创建订阅者对象(promise) |
subscribe(subscriber: CommonEventSubscriber, callback: AsyncCallback): void | 订阅公共事件 |
开发步骤
- 导入CommonEvent模块。
import commonEvent from '@ohos.commonEventManager';
- 创建订阅者信息,详细的订阅者信息数据类型及包含的参数请见CommonEventSubscribeInfo文档介绍。
// 用于保存创建成功的订阅者对象,后续使用其完成订阅及退订的动作
let subscriber = null;
// 订阅者信息
let subscribeInfo = {
events: ["usual.event.SCREEN_OFF"], // 订阅灭屏公共事件
}
- 创建订阅者,保存返回的订阅者对象subscriber,用于执行后续的订阅、退订等操作。
// 创建订阅者回调
commonEvent.createSubscriber(subscribeInfo, (err, data) => {
if (err) {
console.error(`[CommonEvent] CreateSubscriberCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] CreateSubscriber success`);
subscriber = data;
// 订阅公共事件回调
}
})
- 创建订阅回调函数,订阅回调函数会在接收到事件时触发。订阅回调函数返回的data内包含了公共事件的名称、发布者携带的数据等信息,公共事件数据的详细参数和数据类型请见CommonEventData文档介绍。
// 订阅公共事件回调
if (subscriber !== null) {
commonEvent.subscribe(subscriber, (err, data) => {
if (err) {
console.error(`[CommonEvent] SubscribeCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] SubscribeCallBack data=${JSON.stringify(data)}`);
}
})
} else {
console.error(`[CommonEvent] Need create subscriber`);
}
静态订阅公共事件(仅对系统应用开放)
场景介绍
静态订阅者在未接收订阅的目标事件时,处于未拉起状态,当系统或应用发布了指定的公共事件后,静态订阅者将被拉起,并执行onReceiveEvent回调,开发者可通过在onReceiveEvent回调中执行业务逻辑,实现当应用接收到特定公共事件时执行业务逻辑的目的。例如,某应用希望在设备开机的时候执行一些初始化任务,那么该应用可以静态订阅开机事件,在收到开机事件后会拉起该应用,然后执行初始化任务。静态订阅是通过配置文件声明和实现继承自StaticSubscriberExtensionAbility的类实现对公共事件的订阅。需要注意的是,静态订阅公共事件对系统功耗有一定影响,建议谨慎使用。
开发步骤
- 静态订阅者声明
声明一个静态订阅者,首先需要在工程中新建一个ExtensionAbility, 该ExtensionAbility从StaticSubscriberExtensionAbility派生,其代码实现如下:
import StaticSubscriberExtensionAbility from '@ohos.application.StaticSubscriberExtensionAbility'
export default class StaticSubscriber extends StaticSubscriberExtensionAbility {
onReceiveEvent(event) {
console.log('onReceiveEvent, event:' + event.event);
}
}
开发者可以在onReceiveEvent中实现业务逻辑。
- 静态订阅者工程配置
在完成静态订阅者的代码实现后,需要将该订阅者配置到系统的module.json5中,配置形式如下:
{
"module": {
......
"extensionAbilities": [
{
"name": "StaticSubscriber",
"srcEntrance": "./ets/StaticSubscriber/StaticSubscriber.ts",
"description": "$string:StaticSubscriber_desc",
"icon": "$media:icon",
"label": "$string:StaticSubscriber_label",
"type": "staticSubscriber",
"visible": true,
"metadata": [
{
"name": "ohos.extension.staticSubscriber",
"resource": "$profile:subscribe"
}
]
}
]
......
}
}
上述json文件主要关注以下字段:
- srcEntrance : 表示ExtensionAbility的入口文件路径,即步骤2中声明的静态订阅者所在的文件路径
- type: 表示ExtensionAbility的类型,对于静态订阅者需要声明为“staticSubscriber”
- metadata: 表示ExtensionAbility的二级配置文件信息。由于不同的ExtensionAbility类型其配置信息不尽相同,因此需要使用不同的config文件表示其具体配置信息。
○ name:表示ExtensionAbility的类型名称,对于静态订阅类型,name必须声明为“ohos.extension.staticSubscriber”,否则无法识别为静态订阅者;
○ resource: 字段表示ExtensionAbility的配置信息路径,由开发者自行定义,在本例中表示路径为“resources/base/profile/subscribe.json"。
metadata指向的二级配置文件的通常形式如下:
{
"commonEvents": [
{
"name": "xxx",
"permission": "xxx",
"events":[
"xxx"
]
}
]
}
需要注意二级配置文件必须按照此形式进行声明,否则会无法正确识别。下面对字段进行介绍:
- name: 静态订阅ExtensionAbility的名称,需要和module.json5中声明的ExtensionAbility的name一致
- permission:订阅者要求的发布者需要具备的权限,对于发布了目标事件但不具备permission中声明的权限的发布者将被视为非法事件不予发布
- events: 订阅的目标事件列表
- 修改设备系统配置文件
修改设备系统配置文件/etc/static_subscriber_config.json,将静态订阅应用者的包名添加至该json文件中即可。
{
"xxx",
"ohos.extension.staticSubscriber",
"xxx"
}
相关示例
针对StaticSubscriberExtensionAbility开发,可参考如下实例:StaticSubscriber:静态订阅(ArkTS)(API9)(Full SDK)
取消动态订阅公共事件
场景介绍
动态订阅者完成业务需要时,需要主动取消订阅,订阅者通过调用unsubscribe()方法取消订阅事件。
接口说明
接口名 | 接口描述 |
unsubscribe(subscriber: CommonEventSubscriber, callback?: AsyncCallback) | 取消订阅公共事件 |
开发步骤
- 导入CommonEvent模块。
import commonEvent from '@ohos.commonEventManager';
- 根据动态订阅公共事件章节的步骤来订阅某个事件。
- 调用CommonEvent中的unsubscribe方法取消订阅某事件。
// subscriber为订阅事件时创建的订阅者对象
if (subscriber !== null) {
commonEvent.unsubscribe(subscriber, (err) => {
if (err) {
console.error(`[CommonEvent] UnsubscribeCallBack err=${JSON.stringify(err)}`)
} else {
console.info(`[CommonEvent] Unsubscribe`)
subscriber = null
}
})
}
公共事件发布
场景介绍
当需要发布某个自定义公共事件时,可以通过publish()方法发布事件。发布的公共事件可以携带数据,供订阅者解析并进行下一步处理。
须知: 已发出的粘性公共事件后来订阅者也可以接收到,其他公共事件都需要先订阅再接收,订阅参考公共事件订阅章节。
接口说明
详细接口见接口文档。
接口名 | 接口描述 |
publish(event: string, callback: AsyncCallback) | 发布公共事件。 |
publish(event: string, options: CommonEventPublishData, callback: AsyncCallback) | 指定发布信息并发布公共事件。 |
发布不携带信息的公共事件
不携带信息的公共事件,只能发布无序公共事件。
- 导入CommonEvent模块。
import commonEvent from '@ohos.commonEventManager';
- 传入需要发布的事件名称和回调函数,发布事件。
// 发布公共事件
commonEvent.publish("usual.event.SCREEN_OFF", (err) => {
if (err) {
console.error(`[CommonEvent] PublishCallBack err=${JSON.stringify(err)}`);
} else {
console.info(`[CommonEvent] Publish success`);
}
})
发布携带信息的公共事件
携带信息的公共事件,可以发布为无序公共事件、有序公共事件和粘性事件,可以通过参数CommonEventPublishData的isOrdered、isSticky的字段进行设置。
- 导入CommonEvent模块。
import commonEvent from '@ohos.commonEventManager';
ts
- 传入需要发布的事件名称和回调函数,发布事件。
// 公共事件相关信息
let options = {
code: 1, // 公共事件的初始代码
data: "initial data", // 公共事件的初始数据
}
- 传入需要发布的事件名称、需要发布的指定信息和回调函数,发布事件。
// 发布公共事件
commonEvent.publish("usual.event.SCREEN_OFF", options, (err) => {
if (err) {
console.error('[CommonEvent] PublishCallBack err=' + JSON.stringify(err));
} else {
console.info('[CommonEvent] Publish success')
}
})
后台服务
Stage模型提供了ServiceExtensionAbility来提供后台服务的能力,支持系统应用实现一个后台服务并对外提供相应的能力;系统应用A实现了一个后台服务,三方应用B可以通过连接系统应用A的后台服务与其进行进程间通信。
ServiceExtensionAbility的详细介绍请参见后台服务开发指导。