第7章 HarmonyOS 图解公共事件与通知
HarmonyOS 图解 学习系统 | 阶段二:进阶实战期
建议学习时长:1-2 周
学习目标
| 序号 | 能力 |
|---|---|
| 1 | 掌握公共事件服务(CES)的发布与订阅机制 |
| 2 | 能区分有序事件、无序事件和粘性事件 |
| 3 | 掌握通知服务(ANS)的创建和发布流程 |
| 4 | 了解通知的多种样式和渠道管理 |
内容讲解
7.1 公共事件服务 (CES)
想象一个社区:
- 公共事件 (CES) = 社区广播站------"今晚停水通知"(系统事件),或者"张三家孩子满月请吃席"(自定义事件)。所有订阅了广播的人都能收到,可以有序地排队处理(有序事件),或者谁收到谁处理(无序事件)。有些广播还会"粘"在广播站,新来的人也能听到之前的广播内容(粘性事件)。
- 通知 (ANS) = 手机收到的一条私信------"您的快递到了"。它会出现在通知栏,你可以点击查看,也可以直接划掉忽略。
HarmonyOS 通过 CES(Common Event Service)为应用提供订阅、发布、退订公共事件的能力。公共事件分为系统公共事件 和自定义公共事件。
事件类型
| 类型 | 说明 | 典型场景 |
|---|---|---|
| 无序事件 | 订阅者同时收到,无先后顺序 | 天气变化通知、自定义业务事件 |
| 有序事件 | 订阅者按优先级顺序接收处理 | 短信到达、电量变化 |
| 粘性事件 | 新订阅者也能收到之前发布的事件 | 系统启动完成、电量信息 |
发布自定义公共事件
java
// 创建 Intent 并设置 Action
Intent intent = new Intent();
intent.setAction("com.example.myapp.CUSTOM_EVENT");
intent.setParam("message", "Hello from publisher!");
intent.setParam("timestamp", System.currentTimeMillis());
// 封装为 CommonEventData 并发布
CommonEventData eventData = new CommonEventData(intent);
CommonEventManager.publishCommonEvent(eventData);
// 发布粘性事件(新订阅者也能收到)
CommonEventManager.publishCommonEvent(eventData, CommonEventPublishInfo.PUBLISH_STICKY);
订阅公共事件
java
// 创建订阅信息
CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(
"com.example.myapp.CUSTOM_EVENT");
// 设置优先级(有序事件需要)
subscribeInfo.setPriority(100);
// 创建订阅者并订阅
MySubscriber subscriber = new MySubscriber(subscribeInfo);
CommonEventManager.subscribeCommonEvent(subscriber);
事件接收处理
java
class MySubscriber extends CommonEventSubscriber {
public MySubscriber(CommonEventSubscribeInfo info) {
super(info);
}
@Override
public void onReceiveEvent(CommonEventData commonEventData) {
String msg = commonEventData.getIntent().getStringParam("message");
long timestamp = commonEventData.getIntent().getLongParam("timestamp", 0);
HiLog.info(TAG, "Received: " + msg + " at " + timestamp);
}
}
订阅系统公共事件
系统提供了大量预定义的公共事件 Action,常见的包括:
| 系统 Action | 说明 |
|---|---|
CommonEventSupport.COMMON_EVENT_SCREEN_ON |
屏幕亮起 |
CommonEventSupport.COMMON_EVENT_SCREEN_OFF |
屏幕熄灭 |
CommonEventSupport.COMMON_EVENT_BATTERY_CHANGED |
电量变化 |
CommonEventSupport.COMMON_EVENT_NETWORK_CHANGED |
网络状态变化 |
CommonEventSupport.COMMON_EVENT_PACKAGE_ADDED |
应用安装 |
CommonEventSupport.COMMON_EVENT_PACKAGE_REMOVED |
应用卸载 |
退订公共事件
java
// 退订公共事件(在 onStop 或 onDestroy 中调用)
CommonEventManager.unsubscribeCommonEvent(subscriber);
7.2 高级通知服务 (ANS)
通知是应用在 UI 界面之外显示的消息,用于提醒用户。通知支持多种样式:普通文本、长文本、图片、社交、多行文本和媒体样式。
创建通知渠道
在发布通知之前,必须先创建通知渠道:
java
// 创建通知渠道
NotificationSlot slot = new NotificationSlot("slot_id",
"默认渠道", NotificationSlot.LEVEL_DEFAULT);
slot.setDescription("应用默认通知渠道");
NotificationHelper.addNotificationSlot(slot);
通知等级说明:
| 等级 | 常量 | 说明 |
|---|---|---|
| 最低 | LEVEL_MIN |
不弹出横幅,仅在通知栏显示 |
| 低 | LEVEL_LOW |
不发出提示音 |
| 默认 | LEVEL_DEFAULT |
发出提示音和振动 |
| 高 | LEVEL_HIGH |
发出提示音、振动并横幅弹出 |
发布通知
java
// 创建通知请求
NotificationRequest request = new NotificationRequest(1001);
request.setSlotId("slot_id");
// 设置通知内容
NotificationRequest.NotificationNormalContent content =
new NotificationRequest.NotificationNormalContent();
content.setTitle("新消息");
content.setText("您收到一条新消息");
content.setAdditionalText("来自 HarmonyOS 学习系统");
// 包装内容
NotificationRequest.NotificationContent notificationContent =
new NotificationRequest.NotificationContent(content);
request.setContent(notificationContent);
// 发布通知
NotificationHelper.publishNotification(request);
取消通知
java
// 取消指定通知
NotificationHelper.cancelNotification(1001);
// 取消该应用所有通知
NotificationHelper.cancelAllNotifications();
订阅通知事件
应用可以订阅通知的发布、取消、点击等事件:
java
// 订阅通知事件
NotificationSubscribeInfo info = new NotificationSubscribeInfo();
info.setBundleName("com.example.myapp");
NotificationSubscriber subscriber = new NotificationSubscriber(info) {
@Override
public void onSubscribe(NotificationSlot notificationSlot) {
// 订阅成功
}
@Override
public void onUnsubscribe(String s) {
// 取消订阅
}
@Override
public void onUpdate(Notification notification, String s) {
// 收到通知更新
}
@Override
public void onDisturbModeChange(int disturbMode) {
// 免打扰模式变化
}
};
代码速查卡
| 操作 | API | 说明 |
|---|---|---|
| 发布事件 | CommonEventManager.publishCommonEvent() |
传入 CommonEventData |
| 订阅事件 | CommonEventManager.subscribeCommonEvent() |
传入 CommonEventSubscriber |
| 退订事件 | CommonEventManager.unsubscribeCommonEvent() |
在 onStop/onDestroy 中调用 |
| 创建通知渠道 | NotificationHelper.addNotificationSlot() |
必须先创建才能发通知 |
| 发布通知 | NotificationHelper.publishNotification() |
传入 NotificationRequest |
| 取消通知 | NotificationHelper.cancelNotification() |
指定 id 取消 |
| 取消所有通知 | NotificationHelper.cancelAllNotifications() |
清除该应用所有通知 |
| 设置通知等级 | NotificationSlot.setLevel() |
LEVEL_MIN/LOW/DEFAULT/HIGH |
与 Android/iOS 对比
| 特性 | HarmonyOS | Android | iOS |
|---|---|---|---|
| 事件总线 | CommonEventService (CES) | BroadcastReceiver | NotificationCenter |
| 有序事件 | 支持(优先级排序) | 支持(android:priority) | 不支持 |
| 粘性事件 | 支持 | 支持(已废弃) | 不支持 |
| 通知渠道 | NotificationSlot (必须创建) | NotificationChannel (Android 8+) | 不需要 |
| 通知管理 | NotificationHelper | NotificationManager | UNUserNotificationCenter |
⚠️ 踩坑回忆录
做通知功能时,我直接调用了 publishNotification(),结果通知发不出去,也没有任何报错。后来才知道 HarmonyOS 要求必须先创建通知渠道 (addNotificationSlot()),否则通知会被静默丢弃。这跟 Android 8.0+ 的 NotificationChannel 要求类似,但 HarmonyOS 的报错信息更不明显,连个日志都没有。
还有一点要注意:publishCommonEvent() 不需要权限就可以发布自定义事件,但如果你想发布系统级别的有序事件 或者粘性事件 ,可能需要额外的权限声明。订阅系统公共事件时,也要注意有些系统事件需要 ohos.permission.RECEIVER_SYS_EVENT 权限。
必做实操任务
| 序号 | 任务 | 难度 |
|---|---|---|
| 1 | 实现一个应用内组件间的自定义事件通信 | ★★☆ |
| 2 | 订阅屏幕亮/灭的系统公共事件并打印日志 | ★★☆ |
| 3 | 实现通知渠道的创建和通知的发布 | ★★☆ |
| 4 | 尝试发布不同等级的通知,观察通知栏的表现差异 | ★★☆ |
| 5 | 实现通知的点击事件处理(点击通知跳转到指定页面) | ★★★ |
学习检查清单
- 能说出 CES 和 ANS 的全称和作用
- 能区分有序事件、无序事件和粘性事件
- 能实现自定义公共事件的发布和订阅
- 能说出至少 3 个系统公共事件的 Action
- 能实现通知渠道的创建和通知的发布
- 理解通知等级的含义
- 知道退订公共事件的正确时机
进阶方向
- 学习通知的各种样式(长文本、图片、媒体等)
- 实现带进度条和操作按钮的通知
- 了解免打扰模式对通知的影响