一、简介

① 概念
  • HarmonyOS 通过 CES(Common Event Service,公共事件服务)为应用程序提供订阅、发布、退订公共事件的能力,通过 ANS(Advanced Notification Service,即通知增强服务)系统服务来为应用程序提供发布通知的能力。
  • 公共事件可分为系统公共事件和自定义公共事件:
    • 系统公共事件:系统将收集到的事件信息,根据系统策略发送给订阅该事件的用户程序。 公共事件包括:终端设备用户可感知的亮灭屏事件,以及系统关键服务发布的系统事件(例如:USB 插拔,网络连接,系统升级)等;
    • 自定义公共事件:应用自定义一些公共事件用来处理业务逻辑。
  • 应用如果需要接收公共事件,需要订阅相应的事件。
② 约束与限制
  • 目前公共事件仅支持动态订阅,部分系统事件需要具有指定的权限。
  • 目前公共事件订阅不支持多用户。
  • ThreadMode 表示线程模型,目前仅支持 HANDLER 模式,即在当前 UI 线程上执行回调函数。
  • deviceId 用来指定订阅本地公共事件还是远端公共事件。deviceId 为 null、空字符串或本地设备 deviceId 时,表示订阅本地公共事件,否则表示订阅远端公共事件。
③ 应用场景
  • 每个应用都可以订阅自己感兴趣的公共事件,订阅成功后且公共事件发布后,系统会把其发送给应用,这些公共事件可能来自系统、其它应用和应用自身。
  • HarmonyOS 提供了一套完整的 API,支持用户订阅、发布和接收公共事件。发布公共事件需要借助 CommonEventData 对象,接收公共事件需要继承 CommonEventSubscriber 类并实现 onReceiveEvent 回调函数。

三、公共事件的 API 说明

  • 公共事件相关基础类包含 CommonEventData、CommonEventPublishInfo、CommonEventSubscribeInfo、CommonEventSubscriber 和 CommonEventManager。基础类之间的关系如下图所示:

① CommonEventData
  • CommonEventData 封装公共事件相关信息,用于在发布、分发和接收时处理数据。
  • 在构造 CommonEventData 对象时,相关参数需要注意以下事项:
    • code 为有序公共事件的结果码,data 为有序公共事件的结果数据,仅用于有序公共事件场景。
    • intent 不允许为空,否则发布公共事件失败。
  • CommonEventData 主要 API:
接口名 描述
CommonEventData​() 创建公共事件数据
CommonEventData(Intent intent) 创建公共事件数据指定Intent
CommonEventData(Intent intent, int code, String data) 创建公共事件数据,指定Intent、code和data
getIntent() 获取公共事件Intent
setCode(int code) 设置有序公共事件的结果码
getCode() 获取有序公共事件的结果码
setData(String data) 设置有序公共事件的详细结果数据
getData() 获取有序公共事件的详细结果数据
② CommonEventPublishInfo
  • CommonEventPublishInfo 封装公共事件发布相关属性、限制等信息,包括公共事件类型(有序或粘性)、接收者权限等。
  • 有序公共事件:主要场景是多个订阅者有依赖关系或者对处理顺序有要求,例如:高优先级订阅者可修改公共事件内容或处理结果,包括终止公共事件处理;或者低优先级订阅者依赖高优先级的处理结果等。
  • 有序公共事件的订阅者可以通过 CommonEventSubscribeInfo.setPriority() 方法指定优先级,缺省为 0,优先级范围 [-1000, 1000],值越大优先级越高。
  • 粘性公共事件:指公共事件的订阅动作是在公共事件发布之后进行,订阅者也能收到的公共事件类型。主要场景是由公共事件服务记录某些系统状态,如蓝牙、WLAN、充电等事件和状态。不使用粘性公共事件机制时,应用可以通过直接访问系统服务获取该状态;在状态变化时,系统服务、硬件需要提供类似 observer 等方式通知应用。
  • 发布粘性公共事件可以通过 setSticky() 方法设置, 发布粘性公共事件需要申请如下权限:
 "reqPermissions": [{"name": "ohos.permission.COMMONEVENT_STICKY","reason": "Obtain the required permission","usedScene": {"ability": [".MainAbility"],"when": "inuse"}},{...}]
  • CommonEventPublishInfo 主要接口:
接口名 描述
CommonEventPublishInfo() 创建公共事件信息
CommonEventPublishInfo(CommonEventPublishInfo publishInfo) 拷贝一个公共事件信息
setSticky(boolean sticky) 设置公共事件的粘性属性
setOrdered(boolean ordered) 设置公共事件的有序属性
setSubscriberPermissions(String[] subscriberPermissions) 设置公共事件订阅者的权限,多参数仅第一个生效
③ CommonEventSubscribeInfo
  • CommonEventSubscribeInfo 封装公共事件订阅相关信息,比如优先级、线程模式、事件范围等。
  • 线程模式(ThreadMode):设置订阅者的回调方法执行的线程模式。ThreadMode 有HANDLER,POST,ASYNC,BACKGROUND 四种模式,目前只支持 HANDLER 模式。
    • HANDLER:在Ability的主线程上执行;
    • POST:在事件分发线程执行;
    • ASYNC:在一个新创建的异步线程执行;
    • BACKGROUND:在后台线程执行。
  • CommonEventSubscribeInfo 主要接口:
接口名 描述
CommonEventSubscribeInfo(MatchingSkills matchingSkills) 创建公共事件订阅器指定matchingSkills
CommonEventSubscribeInfo(CommonEventSubscribeInfo) 拷贝公共事件订阅器对象
setPriority(int priority) 设置优先级,用于有序公共事件
setThreadMode(ThreadMode threadMode) 指定订阅者的回调函数运行在哪个线程上
setPermission(String permission) 设置发布者必须具备的权限
setDeviceId(String deviceId) 指定订阅哪台设备的公共事件
④ CommonEventSubscriber
  • CommonEventSubscriber 封装公共事件订阅者及相关参数:
    • CommonEventSubscriber.AsyncCommonEventResult 类处理有序公共事件异步执行;
    • 目前只能通过调用 CommonEventManager 的 subscribeCommonEvent() 进行订阅。
  • CommonEventSubscriber 主要接口:
接口名 描述
CommonEventSubscriber(CommonEventSubscribeInfo subscribeInfo) 构造公共事件订阅者实例
onReceiveEvent(CommonEventData data) 由开发者实现, 在接收到公共事件时被调用
AsyncCommonEventResult goAsyncCommonEvent() 设置有序公共事件异步执行
setCodeAndData(int code, String data) 设置有序公共事件的异步结果
setData(String data) 设置有序公共事件的异步结果数据
setCode(int code) 设置有序公共事件的异步结果码
getData() 获取有序公共事件的异步结果数据
getCode() 获取有序公共事件的异步结果码
abortCommonEvent() 取消当前的公共事件,仅对有序公共事件有效,取消后,公共事件不再向下一个订阅者传递
getAbortCommonEvent() 获取当前有序公共事件是否取消的状态
clearAbortCommonEvent() 清除当前有序公共事件abort状态
isOrderedCommonEvent() 查询当前公共事件的是否为有序公共事件
isStickyCommonEvent() 查询当前公共事件是否为粘性公共事件
⑤ CommonEventManager
  • CommonEventManager 是为应用提供订阅、退订和发布公共事件的静态接口类。
  • CommonEventManager 主要接口:
方法 描述
publishCommonEvent(CommonEventData eventData) 发布公共事件
publishCommonEvent(CommonEventData event, CommonEventPublishInfo publishInfo) 发布公共事件指定发布信息
publishCommonEvent(CommonEventData event, CommonEventPublishInfo publishInfo, CommonEventSubscriber resultSubscriber) 发布有序公共事件,指定发布信息和最后一个接收者
subscribeCommonEvent(CommonEventSubscriber subscriber) 订阅公共事件
unsubscribeCommonEvent(CommonEventSubscriber subscriber) 退订公共事件

四、发布公共事件

① 发布无序的公共事件
  • 构造 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); HiLog.info(LABEL_LOG, "Publish succeeded"); } catch (RemoteException e) {HiLog.error(LABEL_LOG, "Exception occurred during publishCommonEvent invocation."); }
② 发布带权限的公共事件
  • 构造 CommonEventPublishInfo 对象,设置订阅者的权限。
  • 订阅者在 config.json 中申请所需的权限:
 "reqPermissions": [{"name": "com.example.MyApplication.permission","reason": "Obtain the required permission","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); HiLog.info(LABEL_LOG, "Publish succeeded"); } catch (RemoteException e) {HiLog.error(LABEL_LOG, "Exception occurred during publishCommonEvent invocation."); }
③ 发布有序的公共事件
  • 构造 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.error(LABEL_LOG, "Exception occurred during publishCommonEvent invocation."); }
④ 发布粘性的公共事件
  • 构造 CommonEventPublishInfo 对象,通过 setSticky(true) 指定公共事件属性为粘性公共事件。
  • 发布者首先在 config.json 中申请发布粘性公共事件所需的权限:
 {"reqPermissions": [{"name": "ohos.permission.COMMONEVENT_STICKY","reason": "Obtain the required permission","usedScene": {"ability": [".MainAbility"],"when": "inuse"}}, {...}]}
  • 发布粘性公共事件:
 CommonEventPublishInfo publishInfo = new CommonEventPublishInfo();publishInfo.setSticky(true); // 设置属性为粘性公共事件try {   CommonEventManager.publishCommonEvent(eventData, publishInfo); } catch (RemoteException e) {HiLog.error(LABEL, "Exception occurred during publishCommonEvent invocation."); }

五、订阅公共事件

  • 创建 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();matchingSkills.addEvent(event); // 自定义事件matchingSkills.addEvent(CommonEventSupport.COMMON_EVENT_SCREEN_ON); // 亮屏事件CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(matchingSkills);MyCommonEventSubscriber subscriber = new MyCommonEventSubscriber(subscribeInfo);try {CommonEventManager.subscribeCommonEvent(subscriber); } catch (RemoteException e) {HiLog.error(LABEL, "Exception occurred during subscribeCommonEvent invocation."); }
  • 如果订阅拥有指定权限应用发布的公共事件,发布者需要在 config.json 中申请权限:
 "reqPermissions": [{"name": "ohos.abilitydemo.permission.PROVIDER","reason": "Obtain the required permission","usedScene": {"ability": ["com.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.error(LABEL, "Exception occurred during subscribeCommonEvent invocation."); }
  • 针对在 onReceiveEvent 中不能执行耗时操作的限制,可以使用 CommonEventSubscriber 的 goAsyncCommonEvent() 来实现异步操作,函数返回后仍保持该公共事件活跃,且执行完成后必须调用 AsyncCommonEventResult .finishCommonEvent() 来结束。
 EventRunner runner = EventRunner.create(); // EventRunner创建新线程,将耗时的操作放到新的线程上执行MyEventHandler myHandler = new MyEventHandler(runner); // MyEventHandler为EventHandler的派生类,在不同线程间分发和处理事件和Runnable任务@Overridepublic void onReceiveEvent(CommonEventData commonEventData){final AsyncCommonEventResult result = goAsyncCommonEvent();Runnable task = new Runnable() {@Overridepublic void run() {........         // 待执行的操作,由开发者定义result.finishCommonEvent(); // 调用finish结束异步操作}};myHandler.postTask(task);}

六、退订公共事件

  • 在 Ability 的 onStop() 中调用 CommonEventManager.unsubscribeCommonEvent() 方法来退订公共事件。
  • 调用后,之前订阅的所有公共事件均被退订。
 try { CommonEventManager.unsubscribeCommonEvent(subscriber);} catch (RemoteException e) {HiLog.error(LABEL, "Exception occurred during unsubscribeCommonEvent invocation.");}

HarmonyOS之公共事件的发布、订阅与退订相关推荐

  1. Redis学习笔记---Redis的模式订阅与退订

    Redis学习笔记-Redis的模式订阅与退订 1.发布订阅简介 发布订阅是一种通信的模式,Redis提供了发布订阅功能,可以用于消息的传输 Redis的发布订阅机制包括三个部分,publisher( ...

  2. 使用java实现MQTT协议客户端的接收、发布消息和订阅、退订主题topic

    记录一下我实习的第一个任务,学习MQTT协议 首先呢得了解MQTT是什么,这里推荐一个我学习MQTT的中文文档 MQTT协议的基于TCP/IP协议的一个物联网协议,有几个概念必须要弄懂得主题(topi ...

  3. EDM备忘录:触发式邮件订阅和退订功能介绍

    一般来说,有触发式邮件订阅和退订功能是邮件模板设计中必不可少的两项功能,下面博主为大家介绍一下. 若客户在订阅后不想再收到这类邮件即可选择退订,将不再收到该IP地址的推广邮件,避免客户在继续收到这类邮 ...

  4. c#事件的发布-订阅模型_NET Core 3 WPF MVVM框架 Prism系列之事件聚合器

    本文将介绍如何在.NET Core3环境下使用MVVM框架Prism的使用事件聚合器实现模块间的通信 一.事件聚合器#  在上一篇 .NET Core 3 WPF MVVM框架 Prism系列之模块化 ...

  5. c#事件的发布-订阅模型_C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命...

    使用面向对象的思想 用c#控制台代码模拟猫抓老鼠 我们先来分析一下猫抓老鼠的过程 1.猫叫了 2.所有老鼠听到叫声,知道是哪只猫来了 3.老鼠们逃跑,边逃边喊:"xx猫来了,快跑啊!我是老鼠 ...

  6. c#事件的发布-订阅模型_C#事件订阅发布实现原理详解

    我们用一个简单的例子,来说明一下这种消息传递的机制. 有一家三口,妈妈负责做饭,爸爸和孩子负责吃...将这三个人,想象成三个类. 妈妈有一个方法,叫做"做饭".有一个事件,叫做&q ...

  7. java基础巩固-宇宙第一AiYWM:为了维持生计,Redis基础Part6(Redis的应用场景、Redis是单线程的速度还快、Redis线程模型:Reactor模式、事件、发布订阅、管道)~整起

    PART1-1:为什么Redis是单线程的 Redis单线程是指: Redis的网络IO和键值对读写是由一个线程来完成的.这也是 Redis 对外提供键值存储服务的主要流程.Redis的其他功能,比如 ...

  8. c#事件的发布-订阅模型_C#事件发布设计模式

    Windows程序最基本的原理是"以消息为基础,以事件驱动之(Message Based, Event Driven)".程序的运行是要靠外部发生的事件来驱动的,也就是说程序需要不 ...

  9. SpringBoot + Redis实现事件的发布订阅功能

    消息队列,消息的发布订阅模式貌似是只有kafka,MQ类中间件才能实现的事情,但是别出新裁的是redis也同样具有这些功能.但是这些消息并没有持久化机制,属于即发即弃模式,也就是说它们不能像MQ中的消 ...

最新文章

  1. 从外部导入django模块
  2. windows下mysql开启慢查询
  3. 这些 Shell 分析服务器日志命令集锦,收藏好
  4. SAP UI5 初学者教程之六 - 了解 SAP UI5 的模块(Module)概念试读版
  5. 用pythonturtle写名字_结婚请帖怎么写
  6. 【论文笔记】Simple and Deep Graph Convolutional Networks
  7. 小白知识摘录__环境变量
  8. OSPFv3中LSA详解(七)——Type4类LSA详解
  9. 论文笔记_S2D.08-2019-ICRA-使用非对称标注实时联合语义分割和深度估计
  10. SoapUI接口测试——关联——参数化
  11. VB程序设计教程(第四版)龚沛曾-实验8-3
  12. Linux版本怎么设置指纹,Linux上使用Thinkpad指纹识别
  13. Error: ‘list‘ object cannot be coerced to type ‘double‘
  14. 古风尚婚纱摄影--决定
  15. javascript 建模_如何用JavaScript编写3D建模应用程序
  16. Window-10 Hyper-V 安装 Windows 10
  17. 将VSCode语言环境设置为中文
  18. 发电机失磁保护的整定计算
  19. python中的方法
  20. 华为云CCE学习笔记-部署harbor(helm模板)

热门文章

  1. RobHess的SIFT代码解析之RANSAC
  2. Android Studio快捷键之代码提示
  3. PHP中被忽略的性能优化利器:生成器
  4. 51nod 1277 KMP 前缀出现次数
  5. 昨天登陆页面,无法进入后台,今天攻克了
  6. 用C#写的一个注册表操作类
  7. 常见的加密算法 (转自: http://blog.chinaunix.net/uid-8735300-id-2017079.html 本文摘自网络 ,如有雷同 请及时联系我 谢谢)...
  8. [MSDN]每个开发人员现在应该下载的十种必备工具
  9. 信息倒流php,PHP向客户端广播信息
  10. MySQL根被拒绝_[转载]phpMyAdmin 尝试连接到 MySQL 服务器,但服务器拒绝连接。...