鸿蒙OS 公共事件与通知的概述
HarmonyOS 通过 CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力,通过 ANS(Advanced Notification Service,即高级通知服务)系统服务来为应用程序提供发布通知的能力。 | |
---|---|
公共事件可分为系统公共事件和自定义公共事件。
系统公共事件:系统将收集到的事件信息,根据系统策略发送给订阅该事件的用户程序
。
IntentAgent 封装了一个指定行为的 Intent,可以通过 IntentAgent 启动 Ability 和发送公共事件。
应用如果需要接收公共事件,需要订阅相应的事件。
约束与限制
公共事件的约束与限制
目前公共事件仅支持动态订阅。部分系统事件需要具有指定的权限,具体的权限见API参考。
目前公共事件订阅不支持多用户。
ThreadMode 表示线程模型,目前仅支持 HANDLER 模式,即在当前 UI 线程上执行回调函数。
deviceId 用来指定订阅本地公共事件还是远端公共事件。deviceId 为 null、空字符串或本地设备 deviceId 时,表示订阅本地公共事件,否则表示订阅远端公共事件。
通知的约束与限制
通知目前支持六种样式:普通文本、长文本、图片、社交、多行文本和媒体样式。创建通知时必须包含一种样式。
通知支持快捷回复。
目前通知订阅不支持多用户。
通知的订阅目前仅支持系统应用,不支持第三方应用。
IntentAgent 的限制
使用 IntentAgent 启动 Ability 时,Intent 必须指定 Ability 的包名和类名
鸿蒙OS 公共事件开发指导
每个应用都可以订阅自己感兴趣的公共事件,订阅成功后且公共事件发布后,系统会把其发送给应用。这些公共事件可能来自系统、其他应用和应用自身。HarmonyOS 提供了一套完整的 API,支持用户订阅、发送和接收公共事件。发送公共事件需要借助 CommonEventData 对象,接收公共事件需要继承 CommonEventSubscriber 类并实现 onReceiveEvent 回调函数。 | |
---|---|
接口说明
公共事件相关基础类包含 CommonEventData、CommonEventPublishInfo、CommonEventSubscribeInfo、CommonEventSubscriber 和 CommonEventManager。基础类之间的关系如下图所示:
有序公共事件:主要场景是多个订阅者有依赖关系或者对处理顺序有要求,例如:高优先级订阅者可修改公共事件内容或处理结果,包括终止公共事件处理;或者低优先级订阅者依赖高优先级的处理结果等。
有序公共事件的订阅者可以通过 CommonEventSubscribeInfo.setPriority() 方法指定优先级,缺省为 0,优先级范围[-1000, 1000],值越大优先级越高。
粘性公共事件:指公共事件的订阅动作是在公共事件发布之后进行,订阅者也能收到的公共事件类型。
主要场景是由公共事件服务记录某些系统状态,如蓝牙、WLAN、充电等事件和状态。不使用粘性公共事件机制时,应用可以通过直接访问系统服务获取该状态;在状态变化时,系统服务、硬件需要提供类似 observer 等方式通知应用。
发布粘性公共事件可以通过 setSticky() 方法设置, 发布粘性公共事件需要申请如下权限。
"reqPermissions": [{
"name": "ohos.permission.COMMONEVENT_STICKY",
"reason": "get right",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
}, {
...
}]
接口名 描述
CommonEventSubscribeInfo 封装公共事件订阅相关信息,比如优先级、线程模式、事件范围等。
线程模式(ThreadMode):设置订阅者的回调方法执行的线程模式。ThreadMode 有 HANDLER,POST,ASYNC,BACKGROUND 四种模式,目前只支持 HANDLER 模式。
HANDLER:在 Ability 的主线程上执行。
POST:在事件分发线程执行。
ASYNC:在一个新创建的异步线程执行。
BACKGROUND:在后台线程执行。
发布无序的公共事件:构造 CommonEventData 对象,设置 Intent,通过构造operation 对象把需要发布的公共事件信息传入 intent 对象。然后调用 CommonEventManager.publishCommonEvent(CommonEventData) 接口发布公共事件。
try {
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withAction("com.my.test")
.build();
intent.setOperation(operation);
CommonEventData eventData = new CommonEventData(intent);
CommonEventManager.publishCommonEvent(eventData);
} catch (RemoteException e) {
HiLog.info(LABEL, "publishCommonEvent occur exception.");
}
发布携带权限的公共事件:构造 CommonEventPublishInfo 对象,设置订阅者的权限。
{
"reqPermissions": [{
"name": "com.example.MyApplication.permission",
"reason": "get right",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
}, {
...
}]
}
发布带权限的公共事件示例代码如下:
Intent intent = new Intent();
Operation operation = new Intent.OperationBuilder()
.withAction("com.my.test")
.build();
intent.setOperation(operation);
CommonEventData eventData = new CommonEventData(intent);
CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
String[] permissions = {"com.example.MyApplication.permission" };
publishInfo.setSubscriberPermissions(permissions); // 设置权限
try {
CommonEventManager.publishCommonEvent(eventData, publishInfo);
} catch (RemoteException e) {
HiLog.info(LABEL, "publishCommoneEvent occur exception.");
}
发布有序的公共事件:构造 CommonEventPublishInfo 对象,通过 setOrdered(true) 指定公共事件属性为有序公共事件,也可以指定一个最后的公共事件接收者。
CommonEventSubscriber resultSubscriber = new MyCommonEventSubscriber();
CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
publishInfo.setOrdered(true); // 设置属性为有序公共事件
try {
CommonEventManager.publishCommonEvent(eventData, publishInfo, resultSubscriber); // 指定resultSubscriber为有序公
共事件最后一个接收者。
} catch (RemoteException e) {
HiLog.info(LABEL, "publishCommoneEvent occur exception.");
}
发布粘性公共事件:构造 CommonEventPublishInfo 对象,通过 setSticky(true)
指定公共事件属性为粘性公共事件。
发布者首先在 config.json 中申请发布粘性公共事件所需的权限,各字段含义详见权限申请字段说明。
{
"reqPermissions": [{
"name": "ohos.permission.COMMONEVENT_STICKY",
"reason": "get right",
"usedScene": {
"ability": [
".MainAbility"
],
"when": "inuse"
}
}, {
...
}]
}
发布粘性公共事件。
CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();
publishInfo.setSticky(true); // 设置属性为粘性公共事件
try {
CommonEventManager.publishCommonEvent(eventData, publishInfo);
} catch (RemoteException e) {
HiLog.info(LABEL, "publishCommoneEvent occur exception.");
}
订阅公共事件
创建 CommonEventSubscriber 派生类,在 onReceiveEvent() 回调函数中处理公共事件。
说明
class MyCommonEventSubscriber extends CommonEventSubscriber {
MyCommonEventSubscriber(CommonEventSubscribeInfo info) {
super(info);
}
@Override
public void onReceiveEvent(CommonEventData commonEventData) {
}
}
构造 MyCommonEventSubscriber 对象,调用 CommonEventManager.subscribeCommonEvent() 接口进行订阅。
String event = "com.my.test";
MatchingSkills matchingSkills = new MatchingSkills();
filter.addEvent(event); // 自定义事件
filter.addEvent(CommonEventSupport.COMMON_EVENT_SCREEN_ON); // 亮屏事件
CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
MyCommonEventSubscriber subscriber = new MyCommonEventSubscriber(subscribeInfo);
try {
CommonEventManager.subscribeCommonEvent(subscriber);
} catch (RemoteException e) {
HiLog.info(LABEL, "subscribeCommonEvent occur exception.");
}
如果订阅拥有指定权限应用发布的公共事件,发布者需要在 config.json 中申请权限,各字段含义详见 权限申请字段说明。
"reqPermissions": [
{
"name": "ohos.abilitydemo.permission.PROVIDER",
"reason": "get right",
"usedScene": {
"ability": ["com.huawei.hmi.ivi.systemsetting.MainAbility"],
"when": "inuse"
}
}
]
如果订阅的公共事件是有序的,可以调用 setPriority()指定优先级。
String event = "com.my.test";
MatchingSkills matchingSkills = new MatchingSkills();
matchingSkills.addEvent(event ); // 自定义事件
CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);
subscribeInfo.setPriority(100); // 设置优先级,优先级取值范围[-1000,1000],值默认为0。
MyCommonEventSubscriber subscriber = new MyCommonEventSubscriber(subscribeInfo);
try {
CommonEventManager.subscribeCommonEvent(subscriber);
} catch (RemoteException e) {
HiLog.info(LABEL, "subscribeCommonEvent occur exception.");
}
针对在 onReceiveEvent 中不能执行耗时操作的限制,可以使用 CommonEventSubscriber 的 goAsyncCommonEvent() 来实现异步操作,函数返回后仍保持该公共事件活跃,且执行完成后必须调用 AsyncCommonEventResult .finishCommonEvent() 来结束。
EventRunner runner = EventRunner.create(); //EventRunner 创建新线程,将耗时的操作放到新的线程上执行
MyEventHandler myHandler = new MyEventHandler(runner); //MyEventHandler 为 EventHandler 的派生类,在不同线程间分发和处理事件和 Runnable 任务
@Override
public void onReceiveEvent(CommonEventData commonEventData){
final AsyncCommonEventResult result = goAsyncCommonEvent();
Runnable task = new Runnable() {
@Override
public void run() {
........ // 待执行的操作,由开发者定义
result.finishCommonEvent(); // 调用finish结束异步操作
}
};
myHandler.postTask(task);
}
退订公共事件
在 Ability的onStop() 中调用 CommonEventManager.unsubscribeCommonEvent() 方法来退订公共事件。调用后,之前订阅的所有公共事件均被退订。
try {
CommonEventManager.unsubscribeCommonEvent(subscriber);
} catch (RemoteException e) {
HiLog.info(LABEL, "unsubscribeCommonEvent occur exception.");
}
鸿蒙OS 通知开发指导
HarmonyOS 提供了通知功能,即在一个应用的 UI 界面之外显示的消息,主要用来提醒用户有来自该应用中的信息。当应用向系统发出通知时,它将先以图标的形式显示在通知栏中,用户可以下拉通知栏查看通知的详细信息。常见的使用场景: | |
---|---|
显示接收到短消息、即时消息等。
显示应用的推送消息,如广告、版本更新等。
显示当前正在进行的事件,如播放音乐、导航、下载等。
接口说明
通知相关基础类包含 [ NotificationSlot ]、[ NotificationRequest ]和[ NotificationHelper ]。基础类之间的关系如下所示:
通知基础类关系图
NotificationSlot 时,当前通知会使用默认的 NotificationSlot,默认的 NotificationSlot 优先级为 LEVEL_DEFAULT 。
NotificationSlot 的级别目前支持如下几种, 由低到高:
LEVEL_NONE: 表示通知不发布。
LEVEL_MIN:表示通知可以发布,但是不显示在通知栏,不自动弹出,无提示音;该级别不适用于前台服务的场景。
LEVEL_LOW:表示通知可以发布且显示在通知栏,不自动弹出,无提示音。
LEVEL_DEFAULT:表示通知发布后可在通知栏显示,不自动弹出,触发提示音。
LEVEL_HIGH:表示通知发布后可在通知栏显示,自动弹出,触发提示。
NotificationRequest
NotificationRequest 用于设置具体的通知对象,包括设置通知的属性,如:通知的分发时间、小图标、大图标、自动删除等参数,以及设置具体的通知类型,如普通文本、长文本等。
通知发布后,通知的设置不可修改。如果下次发布通知使用相同的 id,就会更新之前发布的通知。
NotificationHelper
NotificationHelper 封装了发布、更新、订阅、删除通知等静态方法。订阅通知、退订通知和查询系统中所有处于活跃状态的通知,有权限要求需为系统应用或具有订阅者权限。
开发步骤
通知的开发指导分为创建 NotificationSlot、发布通知和取消通知等开发场景。
创建NotificationSlot
NotificationSlot 可以设置公共通知的震动,锁屏模式,重要级别等,并通过调用 NotificationHelper.addNotificationSlot() 发布 NotificationSlot 对象。
NotificationSlot slot = new NotificationSlot("slot_001","slot_default", NotificationSlot.LEVEL_MIN); // 创建notificationSlot对象
slot.setDescription("NotificationSlotDescription");
slot.setEnableVibration(true); // 设置振动提醒
slot.setLockscreenVisibleness(NotificationRequest.VISIBLENESS_TYPE_PUBLIC);//设置锁屏模式
slot.setEnableLight(true); // 设置开启呼吸灯提醒
slot.setLedLightColor(Color.RED.getValue());// 设置呼吸灯的提醒颜色
try {
NotificationHelper.addNotificationSlot(slot);
} catch (RemoteException ex) {
HiLog.warn(LABEL, "addNotificationSlot occur exception.");
}
发布通知
构建 NotificationRequest 对象,应用发布通知前,通过 NotificationRequest 的 setSlotId() 方法与 NotificationSlot 绑定,使该通知在发布后都具备该对象的特征。
int notificationId = 1;
NotificationRequest request = new NotificationRequest(notificationId);
request.setSlotId(slot.getId());
调用 setContent() 设置通知的内容。
String title = "title";
String text = "There is a normal notification content.";
NotificationNormalContent content = new NotificationNormalContent();
content.setTitle(title)
.setText(text);
NotificationContent notificationContent = new NotificationContent(content);
request.setContent(notificationContent); // 设置通知的内容
调用 publishNotification() 发送通知。
try {
NotificationHelper.publishNotification(request);
} catch (RemoteException ex) {
HiLog.warn(LABEL, "publishNotification occur exception.");
}
取消通知
取消通知分为取消指定单条通知和取消所有通知,应用只能取消自己发布的通知。
调用 cancelNotification() 取消指定的单条通知。
int notificationId = 1;
try {
NotificationHelper.cancelNotification(notificationId);
} catch (RemoteException ex) {
HiLog.warn(LABEL, "cancelNotification occur exception.");
}
调用 cancelAllNotifications() 取消所有通知。
try {
NotificationHelper.cancelAllNotifications();
} catch (RemoteException ex) {
HiLog.warn(LABEL, "cancelAllNotifications occur exception.");
}
鸿蒙OS IntentAgent开发指导
IntentAgent封装了一个指定行为的 Intent,可以通过 triggerIntentAgent 接口主动触发,也可以与通知绑定被动触发。具体的行为包括:启动 Ability 和发送公共事件。例如:收到通知后,在点击通知后跳转到一个新的 Ability,不点击则不会触发。 | |
---|---|
接口说明
IntentAgent 相关基础类包括 IntentAgentHelper、 IntentAgentInfo、 IntentAgentConstant 和 TriggerInfo,基础类之间的关系如下图所示:
IntentAgentHelper封装了获取、激发、取消IntentAgent等静态方法。
IntentAgentInfo
IntentAgentInfo 类封装了获取一个 IntentAgent 实例所需的数据。使用构造函数 IntentAgentInfo(int requestCode, OperationType operationType, List flags, List intents, IntentParams extraInfo) 获取 IntentAgentInfo 对象。 | |
---|---|
requestCode:使用者定义的一个私有值。
operationType:为 IntentAgentConstant.OperationType 枚举中的值。
flags:为 IntentAgentConstant.Flags 枚举中的值。
intents:将被执行的意图列表。operationType 的值为 START_ABILITY,START_SERVICE 和 SEND_COMMON_EVENT 时,intents 列表只允许包含一个 Intent;operationType 的值为 START_ABILITIES 时,intents 列表允许包含多个 Intent
extraInfo:表明如何启动一个有页面的 ability,可以为 null,只在operationType 的值为 START_ABILITY 和 START_ABILITIES 时有意义。
IntentAgentConstant
IntentAgentConstant 类中包含 OperationType 和 Flags 两个枚举类:
类名 枚举值
TriggerInfo
TriggerInfo 类封装了主动激发一个 IntentAgent 实例所需的数据,使用构造函数TriggerInfo( String permission, IntentParams extraInfo, Intent intent, int code) 获取 TriggerInfo 对象。
permission:IntentAgent 的接收者的权限名称,只在 operationType 的值为 SEND_COMMON_EVENT 时,该参数才有意义。
extraInfo:激发 IntentAgent 时用户自定义的额外数据。
intent:额外的 Intent。如果 IntentAgentInfo 成员变量 flags 包含CONSTANT_FLAG,则忽略该参数;如果 flags 包含 REPLACE_ELEMENT,REPLACE_ACTION,REPLACE_URI,REPLACE_ENTITIES 或 REPLACE_BUNDLE,则使用额外 Intent 的 element,action,uri,entities 或 bundleName 属性替换原始 Intent 中对应的属性。如果 intent 是空,则不替换原始 Intent 的属性。
code:提供给 IntentAgent 目标的结果码。
开发步骤
获取 IntentAgent 的代码示例如下:
// 指定要启动的Ability的BundleName和AbilityName字段
// 将Operation对象设置到Intent中
Operation operation = new Intent.OperationBuilder()
.withDeviceId("")
.withBundleName("com.huawei.testintentagent")
.withAbilityName("com.huawei.testintentagent.entry.IntentAgentAbility")
.build();
intent.setOperation(operation);
List<Intent> intentList = new ArrayList<>();
intentList.add(intent);
// 定义请求码
int requestCode = 200;
// 设置flags
List<Flags> flags = new ArrayList<>();
flags.add(Flags.UPDATE_PRESENT_FLAG);
// 指定启动一个有页面的Ability
IntentAgentInfo paramsInfo = new IntentAgentInfo(requestCode, IntentAgentConstant.OperationType.START_ABILITY, flags, intentList, null);
// 获取IntentAgent实例
IntentAgent agent = IntentAgentHelper.getIntentAgent(this, paramsInfo);
通知中添加 IntentAgent 的代码示例如下:
int notificationId = 1;
NotificationRequest request = new NotificationRequest(notificationId);
String title = "title";
String text = "There is a normal notification content.";
NotificationNormalContent content = new NotificationNormalContent();
content.setTitle(title)
.setText(text);
NotificationContent notificationContent = new NotificationContent(content);
request.setContent(notificationContent); // 设置通知的内容
request.setIntentAgent(agent); // 设置通知的 IntentAgent
主动激发 IntentAgent 的代码示例如下:
int code = 100;
IntentAgentHelper.triggerIntentAgent(this, agent, null, null, new TriggerInfo(null, null, null, code ));