跳转至

消息中心开发指南

本文档介绍 HiDiTing V100 MsgCenter(消息中心)的业务定位、消息分发模型和系统业务扩展方法。MsgCenter 是板侧常驻的系统消息路由服务,负责接收手机侧协议消息、按命令号分发给 Native 系统业务,并提供板侧向手机侧发送响应或主动上报的通路。对于板侧 Native 事件,它还连接 OpenHarmony 轻量级广播服务的发布、订阅、通知和优先级处理机制。

本文面向修改产品系统服务的 Native/C++ 集成开发者,不是普通 Native Slice 或 JS 应用的公共 API 指南。JS 应用不直接调用 MsgCenter;需要拉起 JS 应用或向 JS 转发数据时,由 Native 系统适配层完成协议解析和桥接。本文以 SDK 中已有的闹钟 Topic、手机消息和 HC 消息演示模块为参考,说明如何发布或订阅 Native 事件、注册手机命令、按子类型分发、发送响应、拉起 JS 应用以及管理 UI 通知资源。手机侧协议封装和解析请结合穿戴类产品对外交互协议阅读。

消息中心背景知识

MsgCenter 的职责和消息路径

手机侧 APP 不能把任意二进制数据直接当作 MsgCenter 消息发送。下行数据必须按穿戴对外交互协议封装,板侧 MsgCenter 解析命令帧和 TLV 数据后,按命令号、子类型分发给注册的业务处理函数;上行数据则由板侧业务调用 MsgCenter 发送接口,再由手机侧 SDK 解析。

消息中心职责与消息路径图

上图的命令号是一级路由键,例如 MSGCENTER_CMD_PHONE_MSGMSGCENTER_CMD_NAVIGATION;业务模块通常还会用 type 做二级分发。协议帧格式、长度与 TLV 编码规则由 msg_center_protocol.h 定义,手机侧与板侧必须保持一致。

板侧 Native 事件不经过手机协议帧,而是由广播 Pub/Sub 服务在设备内部传递:发布者以 TopicRequest 发布事件,MsgCenter 订阅 Topic 后查找通知处理表,并根据事件优先级决定是否显示或更新通知 UI。两条消息路径可以并存,分别适合设备内部事件和手机与设备间的交互。

Native、JS 与手机侧 SDK 的分工

参与方 主要职责 关键约束
手机侧 SDK 封装下行协议帧、解析上行协议帧 必须使用穿戴对外交互协议约定的命令号、类型和数据格式。
MsgCenter 校验帧基本长度,按命令号找到业务处理函数 只负责路由,业务模块自行校验 payload 的业务含义。
Native 系统业务 发布或处理闹钟、蓝牙、健康等 C/C++ 系统事件;处理通知、设备信息、OTA 等手机消息 组件位于产品系统服务层;内部事件使用 Topic 发布/订阅,手机消息注册命令回调并按子类型分发。普通 Native 应用不直接修改 MsgCenter 的路由表。
JS 应用 处理由 Native 适配层拉起或转发的应用消息 JS 不直接调用 MsgCenter;需要启用 JS_ENABLE,并由 Native 适配层定义 bundle、事件和数据协议。当前 samples/js_samples 没有直接调用 MsgCenter 的示例。
NotificationManager 显示通知 UI 并回收页面资源 页面退出时注册清理函数,避免通知资源泄漏。

下图说明手机、板侧 Native/JS 应用和 MsgCenter 的关系:

MsgCenter 交互图

整体架构示意图

核心对象和代码组织

代码位置 作用
/src/application/wearable/service/msg_center/include/msg_center_protocol.h 命令号、TLV 结构、收发接口和 TLV 辅助函数。
/src/application/wearable/service/msg_center/include/msg_center_cmd.h 命令注册和注销接口。
/src/application/wearable/service/msg_center/src/msg_center_cmd.cpp 注册表、一级命令分发和入站协议帧处理。
/src/application/wearable/service/msg_center/src/msg_center_customer.cpp Native Topic 的订阅列表、通知处理表和事件优先级表。
/src/application/wearable/service/remote_msg/remote_msg.cpp 手机消息业务的二级分发参考实现。
/src/application/wearable/service/msg_center/include/notify/notification_manager.h 通知显示、停止和资源回收接口。
/src/application/wearable/service/msg_center/src/notify/alarm_notification.cpp 通知清理函数注册的参考实现。
/src/application/wearable/service/hc_demo_msg/hc_demo_msg.cpp 通用 HC 命令注册和二级分发参考实现。
/src/application/wearable/service/hc_demo_msg/msg_center_hc_demo.cpp 从 TLV 读取 bundle 名称、返回 ACK、拉起 JS 应用的参考实现。
/src/ohos/foundation/systemabilitymgr/samgr_lite/interfaces/kits/communication/broadcast/broadcast_interface.h 广播服务的公开 TopicSubscriberPubSubInterface 接口定义。
/src/ohos/foundation/systemabilitymgr/samgr_lite/communication/broadcast/source/pub_sub_feature.h Topic 枚举及广播服务的公共类型。
/src/ohos/foundation/systemabilitymgr/samgr_lite/communication/broadcast/source/pub_sub_implement.c Topic 到目标核的映射表和发布实现。
/src/application/wearable/service/msg_center/diting-community/libmsg_center.a 社区目标使用的 MsgCenter 基础服务库。

当前 msg_center 的 CMake 配置会将 msg_center_cmd.cppmsg_center_customer.cpp 和消息适配代码纳入 msg_center_adapt 组件;与 JS 相关的通知和适配代码受 JS_ENABLE 条件控制。新增业务前,应先确认目标产品配置确实启用了对应组件和依赖。

MsgCenter 的扩展边界如下:普通 Native 或 JS 应用不直接依赖该系统服务;只有需要修改产品固件消息协议、系统通知或 Native 系统业务时,才在现有服务之上扩展 Topic、手机协议和 Native 适配组件。应用页面、业务状态和普通应用内事件仍应使用对应的应用框架接口,不应为了应用内通信修改 MsgCenter 路由表。

快速跑通 Native Topic 事件 Demo

本节以 SDK 的闹钟响铃事件 TOPIC_EVENT_ALARM_RING 为例,说明设备内部 Native 事件如何从发布者进入 MsgCenter,再显示通知 UI。该场景对应“发布事件 → 订阅事件 → 通知分发 → 资源回收”的完整路径,可作为新增业务 Topic 的参考。

说明: 本文示例命令以一站式 CLI 为主。实际开发可从以下三种环境中选择,推荐使用一站式 CLI。

开发环境 适用场景 使用指南
一站式 CLI(推荐) 快速完成目标选择、构建、烧录和串口监视 一站式 CLI 开发环境使用指南
HiSpark Studio for VS Code 图形化编辑、编译、烧录和调试 HiSpark Studio for VS Code 开发环境使用指南
WSL 与 Docker 在 Windows 上使用一致的 Linux 容器构建环境 WSL 与 Docker 环境使用指南

准备工作:按一站式 CLI 开发环境使用指南准备环境、构建和烧录;构建前必须确保 fbb doctor 成功。本文不展开构建和烧录命令。

场景设计

原生主题事件流程

接口与代码参考

功能 接口或对象
定义 Topic TopicNumTOPIC_EVENT_*
配置 Topic 所属核 topicToCoreArray
广播公开接口 PubSubInterface::SubscribeTopic()UnsubscribeTopic()PublishTopic()
发布 Topic PubSubInterface::PublishTopic()、调用示例 AlarmTimerEventPublish()
订阅 Topic MsgCenterSubscribeTopic()
选择通知处理函数 MsgCenterNotifyProc()g_msgCenterNotifyTable
注册/停止通知 RegisterNotifyCleanupFunction()StopNotify()

实现流程与核心代码走读

broadcast_interface.h 定义了广播服务的公开契约:Topicuint16 类型;Request 携带 msgIdlendata 等消息字段;PubSubInterface 提供订阅、取消订阅、查询订阅位图和发布 Topic 的能力。需要由 MsgCenter 显示通知的事件,应走本节的 MsgCenterSubscribeTopic() 和通知表配置;独立组件自行订阅 Topic 时,才直接创建 Subscriber 并调用 PubSubInterface::SubscribeTopic()

定义 Topic 并配置目标核

TopicNum 位于 pub_sub_feature.h,现有 Topic 从 TOPIC_START_NUM 开始,到 TOPIC_END_NUM 结束。新增 Topic 时在该枚举中定义唯一值,并在 pub_sub_implement.ctopicToCoreArray 中增加同一个 Topic 的目标核映射。映射表中的 Topic 不可重复,并应保持有序;缺少映射时,广播服务无法将该 Topic 正确纳入可用 Topic 表。

由业务模块发布事件

AlarmTimerEventPublish() 是当前闹钟业务的发布参考。它先复制业务数据,构造 Request,再获取广播服务的 PubSubInterface 并调用 PublishTopic();发布完成后释放临时数据。自己的发布函数也必须检查内存申请、接口获取和数据复制结果,不能向异步处理路径传递已失效的缓冲区。

Request request = {
    .msgId = topic,
    .len = sizeof(AlarmClockEventData),
    .data = publishData,
    .msgValue = 0,
};
api = SAMGR_GetInstance()->GetFeatureApi(BROADCAST_SERVICE, PUB_SUB_FEATURE);
ret = api->QueryInterface(api, DEFAULT_VERSION, (void **)&broadcastApi);
broadcastApi->PublishTopic((IUnknown *)broadcastApi, &request);
broadcastApi->Release((IUnknown *)broadcastApi);

AlarmClockTimerConfig.cpp 在闹钟回调中调用 AlarmTimerEventPublish(TOPIC_EVENT_ALARM_RING, ...)。新业务应先用一个固定、可验证的数据结构跑通发布和订阅,再逐步增加业务字段与版本信息。

在 MsgCenter 中订阅事件

msg_center_customer.cppMsgCenterSubscribe() 集中列出 MsgCenter 要订阅的 Topic。新增 Topic 后,在此函数中增加一条 MsgCenterSubscribeTopic(TOPIC_EVENT_XXX);否则发布成功也不会进入 MsgCenter 的通知逻辑。

Native Topic 订阅代码示意图

配置事件通知逻辑与优先级

g_msgCenterNotifyTable 将 Topic 映射到通知处理函数。收到已订阅的事件后,MsgCenterNotifyProc() 遍历此表并调用匹配处理函数,例如 MsgCenterNotifyAlarmProc()。需要展示通知时,处理函数应先根据业务状态检查参数,再调用 NotificationManager::ShowNotify()

Native Topic 通知代码示意图

PRI_MAPPER 为各 Topic 设置通知优先级,CheckPriority() 会结合当前 Native 页面和当前通知的优先级决定是否允许显示。为新 Topic 增加通知逻辑时,应同步评估其优先级,避免低优先级事件覆盖通话、告警等高优先级界面。

Native Topic 优先级代码示意图

注册 UI 资源清理函数

通知 UI 创建页面、定时器或监听器后,要调用 RegisterNotifyCleanupFunction() 注册对应释放函数。StopNotify() 会执行该回调;alarm_notification.cpp 中的 FreeAlarmViewFreeAlarmCloseViewFreeAlarmRingView 是可直接参考的资源生命周期实现。

验证与预期结果

触发闹钟事件后,应依次看到发布日志、MsgCenter 通知处理、优先级判断和通知 UI。主动关闭通知或触发超时关闭后,已注册的 UI、定时器和监听器必须被清理。新 Topic 至少应验证正常数据、空数据、重复发布、通知被高优先级事件抢占和主动关闭等路径。

快速跑通手机消息分发 Demo

场景前置条件

准备一端能按穿戴对外交互协议发送 MSGCENTER_CMD_PHONE_MSG 的手机侧 APP 或调测工具,并确认板侧已包含 msg_centerremote_msg 组件。下行 payload 应在接收处理函数中按长度和类型校验;不要直接信任来自手机侧的数据。

场景设计

以当前 SDK 的手机消息模块为例,手机侧发送 MSGCENTER_CMD_PHONE_MSG 后,MsgCenter 找到 msg_center_phone_msg_type_dispatch();该函数再根据 type 将短信、电话、第三方消息、联系人更新或联系人查询分发给对应业务函数。业务处理完成后,可使用 msg_center_send_data() 返回 ACK、查询结果或主动上报。

手机消息分发流程

接口列表

功能 接口
注册一级命令 msg_center_register_cmd()
注销一级命令 msg_center_unregister_cmd()
接收并分发协议帧 msg_center_pkt_proc()
向手机侧发送数据 msg_center_send_data()
获取 TLV 负载 msg_center_get_tlv_payload()
注册通知清理函数 NotificationManager::RegisterNotifyCleanupFunction()
停止通知并回收资源 NotificationManager::StopNotify()

实现流程与核心代码走读

定义命令号和子类型

一级命令号定义在 msg_center_protocol.hmsg_center_cmd_id_t,例如 MSGCENTER_CMD_PHONE_MSG。一个命令下可再定义多个业务 type;手机侧和板侧必须同步发布该映射,不能只在任一侧新增枚举。

注册一级命令处理函数

现有 remote_msg.cpp 在初始化函数中注册 MSGCENTER_CMD_PHONE_MSG。初始化宏会让模块在系统启动阶段完成注册,之后才能接收来自手机侧的消息。

void phone_msg_init(void)
{
    msg_center_register_cmd(MSGCENTER_CMD_PHONE_MSG,
        msg_center_phone_msg_type_dispatch);
}

APP_FEATURE_INIT_PRI(phone_msg_init, LAYER_INIT_LEVEL_4);

注册函数将命令号和回调写入 g_msg_center_cmds 链表。当前实现未在注册时去重,因此同一个命令不应重复注册;模块卸载或可重入初始化场景应调用 msg_center_unregister_cmd() 清理。

在 MsgCenter 中解析并执行一级分发

msg_center_pkt_proc() 校验 data、帧头长度和 TLV 最小长度,随后提取 cmd_idtype 与用户数据,交给 msg_center_pkt_dispatch()。后者遍历已注册命令并调用匹配的业务回调。

uint8_t type = ((msg_center_pkt_tlv_t *)usr_data)->type &
    TLV_NO_CHILD_ONE_BYTE_LEN_MAX;
return msg_center_pkt_dispatch(req->cmd_id, type, usr_data, size);

业务回调收到的 usr_data 仍是 TLV 数据。需要读取业务 payload 时应使用 msg_center_get_tlv_payload(),并结合 usr_len、TLV 长度字段和业务结构长度校验边界,不能只做指针转换。

按子类型分发并发送响应

msg_center_phone_msg_type_dispatch() 遍历 g_msg_center_phone_msg_tbl,按 type 调用短信、电话、联系人等对应处理函数。业务函数需要响应时,调用 msg_center_send_data(cmd_id, type, usr_data, usr_len) 发送结果;cmd_id、响应 type 和 payload 格式必须与手机侧 SDK 协议一致。

if ((item->type == type) && (item->handler != NULL)) {
    item->handler(cmd_id, type, usr_data, usr_len);
    return ERRCODE_SUCC;
}
return ERRCODE_NOT_SUPPORT;

处理函数应尽快返回。耗时的文件、网络或 UI 操作应通过业务任务继续执行,避免阻塞 MsgCenter 的分发路径。

显示通知时管理资源生命周期

Native 消息若创建通知 UI,应在创建页面后通过 RegisterNotifyCleanupFunction() 注册释放函数。StopNotify() 停止当前通知时会执行清理逻辑;alarm_notification.cppcalendar_notification.cppphone_msg_notification.cpp 都提供了实际用法。

NotificationManager::GetInstance()->RegisterNotifyCleanupFunction(
    FreePhoneMsgView);

这一步不能省略:只关闭界面而未释放关联对象、定时器或监听器,会造成重复消息后内存泄漏或无效回调。

验证与预期结果

使用手机侧 SDK 发送已注册命令和子类型后,应能在板侧日志看到 msg_center_pkt_proc 打印的 module、cmd、type 信息,并进入目标业务处理函数。对于需要 ACK 的业务,手机侧应收到正确命令号、类型和长度的响应;对于通知类业务,重复发送、主动关闭和超时关闭后均不应残留 UI 或定时器资源。

快速跑通 JS 应用消息 Demo

本节以 SDK 的 HC 消息演示模块为例,说明手机侧如何请求拉起板侧 JS 应用。该场景使用穿戴对外交互协议,而不是内部 Topic;手机侧必须封装协议帧,板侧 Native 适配层负责确认请求、解析 bundle 名称、返回 ACK 并启动 JS 应用。需要向 JS 传递业务数据时,应用可在适配层校验 payload 后调用公开的 DmsLiteSendMsgToJS() 接口。

JS 应用交互图

场景设计

JS应用消息流程

接口与代码参考

功能 接口或对象
注册 HC 命令 msg_center_register_cmd()
命令/类型定义 MSGCENTER_CMD_HCMSGCENTER_TYPE_ID_HC_START_JS
启动 JS 应用 StartJsApp()
向 JS 应用发送数据 DmsLiteSendMsgToJS()
HC 业务适配 msg_center_hc_start_js()

实现流程与核心代码走读

hc_demo_msg.cppMSGCENTER_CMD_HC 注册一级命令处理函数,并使用 MSGCENTER_TYPE_ID_HC_START_JStype 区分卡片流转、传输状态、启动 JS、日历同步和表盘传输等业务。APP_FEATURE_INIT_PRI 保证服务初始化后完成注册;该演示模块受 SUPPORT_HC_DEMO 控制,使用前需在产品配置中启用该功能宏。

static const msg_center_cmd_map_t g_msg_center_hc_demo_tbl[] = {
#ifdef SUPPORT_HC_DEMO
    {MSGCENTER_CMD_HC, MSGCENTER_TYPE_ID_HC_START_JS,
        msg_center_hc_start_js},
#endif
};

void hc_demo_init(void)
{
    msg_center_register_cmd(MSGCENTER_CMD_HC,
        msg_center_hc_demo_type_dispatch);
}

JS 命令注册代码示意图

msg_center_hc_start_js() 从 TLV payload 中读取 bundle 名称,先通过 msg_center_send_data() 返回 ACK,再在 JS_ENABLE 条件下调用 StartJsApp(bundle_name)。自定义 JS 业务应在计算 usr_len - tl_len 前先确认 usr_data 非空且 usr_len >= tl_len,再进行内存申请和字符串/二进制数据转换。若还需把数据传给已启动的 JS 应用,可在完成同样的校验后调用 DmsLiteSendMsgToJS()

验证与预期结果

手机侧先发送启动 JS 类型,应看到目标 JS 应用被拉起并收到 ACK;再发送业务数据时,应确认 Native 适配层和 JS 应用按约定处理。需要同时验证 JS 未安装、应用未启动、未知 type、TLV 长度不足和重复数据的处理路径。

JS 应用交付边界

当前 SDK 提供 hc_demo_msg 的 Native 适配参考,但不提供可直接复用的完整 JS 应用工程。因而,本文档可指导开发 Native 协议适配层,不能替代 JS 应用 SDK。

要开发可运行的完整 JS 应用,除本文档的 Native 适配代码外,还需要从产品或应用提供方获得以下交付物:

  1. JS 应用包、安装方式以及固定的 bundle 名称;StartJsApp() 使用的名称必须与该 bundle 一致。
  2. JS 侧接收 DmsLiteSendMsgToJS() 数据的 API、事件名和回调线程约束。
  3. 手机侧、Native 适配层和 JS 侧共同使用的 payload 格式(JSON 或二进制)、版本字段、错误码和 ACK 约定。
  4. 启用 JS_ENABLE 及相关产品组件后的目标构建配置。

扩展系统消息业务

参考现有系统服务组件

MsgCenter 属于产品系统服务,不在 samples/native_samples 下建立普通应用 Demo。需要扩展手机协议或系统消息时,应参考 SDK 已有的 /src/application/wearable/service/hc_demo_msg 系统服务组件:

src/application/wearable/service/hc_demo_msg/
├── CMakeLists.txt
├── hc_demo_msg.cpp
├── msg_center_hc_demo.cpp
└── msg_center_hc_demo.h

各文件职责如下:

文件 作用
CMakeLists.txt 定义 hc_demo_msg 系统服务组件及 MsgCenter、Native Ability、JS 桥接等依赖头文件。
hc_demo_msg.cpp 定义 cmd_id + type 二级分发表,注册 MSGCENTER_CMD_HC 一级命令。
msg_center_hc_demo.cpp 校验 TLV 数据、返回 ACK,并按业务类型处理卡片流转、JS 应用启动、日历同步和表盘传输。
msg_center_hc_demo.h 定义 HC 业务的子类型和状态值。

系统业务组件由 /src/application/wearable/service/CMakeLists.txt 接入产品构建,并由目标配置中的 msg_center_service 组件集合统一启用。注册命令时使用 APP_FEATURE_INIT_PRI,保证 MsgCenter 服务初始化后完成业务注册。普通 Native 应用不应复制该组件、分配新的系统命令号或修改产品协议;只有负责产品固件和手机协议联调的系统集成开发者才需要扩展这一层。

扩展系统消息业务时,先明确下面的边界:

  1. 手机与开发板之间的 cmd_idtype、TLV 和 ACK 由产品协议共同定义,不能只修改板侧代码。
  2. 新组件放在产品系统服务层,并加入对应产品的组件集合;不要把它包装成普通 Native 示例应用。
  3. 处理函数必须先校验 usr_data、TLV 头长度和 payload 实际长度,再执行业务逻辑。
  4. 需要启动或通知 JS 应用时,由 Native 适配层完成 bundle 校验和数据桥接,JS 应用不直接注册 MsgCenter 命令。
  5. 通知 UI、定时器和监听器必须有明确的停止和资源回收路径。

新增或删除 Native Topic

  1. /src/ohos/foundation/systemabilitymgr/samgr_lite/communication/broadcast/source/pub_sub_feature.h 中增加唯一的 TopicNum 枚举值。
  2. /src/ohos/foundation/systemabilitymgr/samgr_lite/communication/broadcast/source/pub_sub_implement.ctopicToCoreArray 中添加该 Topic 的目标核映射。
  3. 在发布业务中构造 Request 并调用 PublishTopic();发布数据必须在调用期间有效,且发布后由业务侧释放临时内存。
  4. /src/application/wearable/service/msg_center/src/msg_center_customer.cppMsgCenterSubscribe()PRI_MAPPERg_msgCenterNotifyTable 中补齐订阅、优先级与通知回调。
  5. 如果通知 UI 分配了页面、定时器或监听器,注册 RegisterNotifyCleanupFunction() 并验证 StopNotify() 的释放路径。
  6. 删除 Topic 时,先移除发布者和 MsgCenter 的订阅/优先级/通知表项;确认没有其他消费者后,再删除 Topic 定义和目标核映射。仅取消通知回调而保留发布者会造成无消费的事件。

只修改展示或处理方式而不改变 Topic 数据格式时,修改对应通知处理函数即可,例如 MsgCenterNotifyAlarmProc()。如果同时修改 Request::data 的结构,应同步修改所有发布者和消费者,并增加版本或长度校验,不能只改通知处理函数。

新增手机侧 Native 命令

新增手机协议业务时,可参考 remote_msgdevice_msgauto_ota_msg

  1. msg_center_protocol.h 规划唯一的一级命令号,或在已有命令下规划唯一的 type,并同步更新手机侧协议实现。
  2. 新建命令/子类型映射表和分发函数,逐层校验 TLV 长度、版本和业务字段。
  3. 使用 APP_FEATURE_INIT_PRI 调用 msg_center_register_cmd();可重入或卸载场景使用 msg_center_unregister_cmd() 清理。
  4. 需要响应时使用 msg_center_send_data() 返回明确的成功或错误状态;需要展示 UI 时注册资源清理函数。
  5. 依次验证正常消息、未知 type、长度不足、重复消息、手机侧重传和 UI 主动关闭。

新增 JS 应用协议

新增 JS 业务时,除完成上述命令号和 type 设计外,还要在目标产品配置中启用 JS_ENABLE,确认 JS 包已安装并定义稳定的 bundle 名称。Native 适配层负责协议解析、ACK、应用启动和数据转发;JS 应用负责业务展示与业务处理。不要把未经长度校验的手机侧 payload 直接传给 JS。

开发前自检

开发者或 AI 在生成代码前,按下表确认输入条件;任一项不明确时,不应假设协议值、bundle 名称或 JS 运行时行为。

检查项 Native Topic 手机侧 Native 命令 JS 应用协议
唯一标识 TopicNumtopicToCoreArray 均已添加,且不与现有 Topic 重复。 cmd_idtype 与手机侧协议同步定义。 在手机协议命令/类型基础上,明确 JS 事件名或 payload 类型。
编译配置 系统业务组件已加入 application/wearable/service 的产品构建,目标包含 msg_center_service 同左。 同左,且启用 JS_ENABLE
数据边界 Request::data 的结构、长度和所有消费者一致。 处理函数校验 TLV 最小长度、实际长度和业务版本。 Native 与 JS 两端约定数据编码、版本、大小上限和 ACK。
生命周期 通知 UI、定时器和监听器均有 StopNotify() 清理路径。 注册和注销时机明确,手机重传不会产生不可控副作用。 bundle 可启动、JS 回调可接收数据,异常时不会阻塞 MsgCenter。
验证 发布、订阅、优先级抢占、关闭和重复发布均已验证。 正常、未知类型、长度不足、重复和重传均已验证。 JS 未安装、启动失败、数据格式错误和重复数据均已验证。

调试方法

观察点 方法与预期
Native Topic 发布 在发布函数和 AlarmTimerEventPublish() 参考路径打印 Topic、Request::len 和接口返回值。
Topic 通知分发 观察 MsgCenterNotifyProc 的日志,并确认 Topic 在订阅列表、优先级表和通知表中均有对应项。
手机协议分发 观察 msg_center_pkt_proc 打印的 module、cmd、type,并确认进入目标二级分发函数。
上行响应 手机侧同时记录发送的命令/type 和收到的 ACK 或返回数据,核对长度及协议约定。
JS 转发 记录 JS 应用是否启动、DmsLiteSendMsgToJS() 的调用结果和 JS 侧接收日志。
UI 资源释放 反复触发、关闭和抢占通知,确认 StopNotify() 后页面、定时器和监听器均被释放。

注意事项

  • MsgCenter 是协议边界。所有手机侧输入必须校验命令、type、TLV 长度、版本和业务字段;未知消息不能按已知结构访问内存。
  • 同一个手机命令不要重复注册;同一个 Native Topic 也不要在 topicToCoreArray 中重复定义。
  • Topic 优先级应按产品体验整体设计,不能仅因新业务需要展示就设置为最高优先级。
  • 对涉及联系人、通知、语音等用户数据的消息,遵循数据最小化原则,不在日志中输出敏感完整内容。
  • 修改 Topic 或手机协议的数据结构后,应进行版本兼容设计,避免新旧手机应用或新旧固件组合时发生解析错误。

常见编译错误

现象 原因与处理
TopicRequestPUB_SUB_FEATURE 未定义 缺少广播服务头文件或组件依赖。检查 pub_sub_feature.hbroadcast_service.h 的包含关系,以及新增组件的 CMake 依赖。
链接阶段找不到 msg_center_register_cmdNotificationManager 符号 新组件未链接 MsgCenter 相关组件,或目标配置未纳入对应服务。参照 /src/application/wearable/service/msg_center/CMakeLists.txt 检查组件配置。
JS 命令代码未编译或 JS 消息无响应 JS_ENABLE 未启用,导致 JS 相关源文件或注册表项未加入构建。检查 /src/build/config/target_config/3322/config.py 与产品目标配置。
板侧没有进入业务回调 核对手机协议帧长度、命令号、TLV 类型;确认模块初始化后已注册命令,或 Native Topic 已同时完成定义、映射和订阅。
返回 ERRCODE_NOT_SUPPORT 一级命令或二级 type 未注册,或注册表与手机侧枚举不一致。
收到消息但 payload 解析异常 检查 TLV 长度、版本、字节序和业务结构体大小;不要绕过长度校验。
通知关闭后仍有回调或资源泄漏 为页面、定时器和监听器注册 RegisterNotifyCleanupFunction(),并验证 StopNotify() 路径。