UX开发指南
本文档面向 HiDiTing 穿戴音频方案的应用开发者,说明如何使用 UX 完成蓝牙连接管理、SPP 数传、BLE 数传及蓝牙音频控制,并以“BLE 数传回显”给出从代码改动、编译、烧录、验证的一条完整路径。文中的接口均可跳转到 /src/application/ux/interfaces/ 下的公开头文件。
UX 不是底层蓝牙协议栈的替代品,而是其上层的应用开发框架:它封装蓝牙、媒体和平台能力,预注册协议栈回调,并以统一状态与消息机制降低应用与底层模块的耦合。本指南基于当前 SDK 源码编写;本文档标注的版本对应关系为 UX 1.0.0 / HiDiTing。
适用范围:本文所列
ux_api_*接口位于 SDK UX 模块;它们目前没有独立的 API Reference 页面,故接口表均链接到 src/application/ux/interfaces/ 中对应声明所在的头文件与行号。底层bs_*接口的链接仅用于定位和调试,业务代码应优先调用 UX API。
UX 模块背景知识
模块定位
UX 位于 native app 与蓝牙/媒体/平台服务之间。应用调用 ux_api_* 接口发起使能、发现、连接或数据收发;UX 负责把底层协议栈回调转换为内部事件和应用侧可消费的状态。以蓝牙为例,协议栈成功返回只表示“请求受理”或“底层调用成功”,最终状态须以 UX 的异步消息或状态查询为准。
| 层次 | 当前 SDK 中的代表位置 | 职责 |
|---|---|---|
| Native 应用 | src/application/wearable/nativeapp/nativeui/ | 设置页、UI Service、播放器等业务与 UI |
| UX 对外接口 | src/application/ux/interfaces/solution/bg/ | ux_api_bt.h、ux_api_ble.h、音频控制头文件 |
| UX 连接与服务实现 | src/application/ux/watch/bg/gap/、src/application/ux/solution/bg/ | 协议栈管理、连接管理、BLE GATT 与 SPP 数传服务 |
| 适配与事件框架 | src/application/ux/adapter/、src/application/ux/framework/ | 将协议栈回调转换为 UX/应用消息 |
| 蓝牙协议栈服务 | bs_*、bts_* |
BR、BLE、GATT、SPP 等底层能力 |
基于当前代码的架构说明
两条重要事件链路
协议栈使能链路:ux_api_bt_enable() 调用 ux_bt_ble_init() 或 ux_bt_br_init();协议栈随后经回调报告 enabled;BLE 在 process_ble_enable_result() 中启动广播并在启用 CONFIG_SUPPORT_UX_GATT 时初始化 BLE 数传服务,BR 在 process_br_enable_result() 中初始化 SPP 服务。本文档中的 BT_GAP_ENABLE_SUCC 再由 UX Adapter 转交 native app。
BLE 数据链路:手机写入 GATT 特征值后,ux_ble_data_received_callback() 复制数据并投递 UX_EVENT_TYPE_BLE_HOST;process_ble_service_msg() 再调用由 ux_api_ble_service_register_msg_handler() 注册的业务回调。业务回调使用 ux_api_ble_service_send_data() 通过当前服务声明的 Notify 路径回传数据。
快速跑通 BLE 数传回显 Demo
本章以 BLE 数传回显为例,将连接管理、数传接口、关键配置、编码、构建、验证与调试串成一条可直接执行的路径。
开发指导
连接管理
| 场景 | 正确顺序 | 关键点 |
|---|---|---|
| 打开协议栈 | ux_api_bt_enable(BR/BLE) → 等待异步成功状态 |
返回成功不等于协议栈已可用;不要立即假定广播/扫描成功。重复启用同一协议会报错。 |
| 关闭协议栈 | 停止业务 →ux_api_bt_disable(BR/BLE) |
关闭会终止该协议的全部连接;未启用时关闭会报错。 |
| 外围设备(被手机连接) | 协议栈就绪 →ux_api_bt_start_discovery(PERIPHERAL, protocol) → 等待中心设备连接 |
在 UX 中 PERIPHERAL 对应可被发现/广播。当前 BLE 与 BR 初始化成功后均会由 SDK 自动启动外围发现,业务层不要重复启动。 |
| 中心设备(扫描并连接耳机等) | 协议栈就绪 →ux_api_bt_start_discovery(CENTRAL, protocol) → 获得设备地址 → 配对或连接 |
CENTRAL 表示主动扫描。扫描结束必须调用 stop;停止不存在的发现流程会报错。 |
| 新设备配对 | 按协议调用 ux_api_bt_pair_device() |
配对结果异步上报;BLE 对端须处于可连接状态;BR 配对前先停止扫描。 |
| 已配对设备回连 | ux_api_bt_connect(profile, addr) |
先连 BR/BLE 基础链路;A2DP、HFP 等扩展 profile 通常要分别连接。 |
| 断连或删除 | ux_api_bt_disconnect(profile, addr) / ux_api_bt_remove_device(addr, protocol) |
disconnect 保留配对记录;remove 删除配对记录。对未连接或不存在对象操作会报错。 |
SPP 数传
- 先使能 BR,并等待协议栈及 SPP 服务初始化完成。
- 调用
ux_api_spp_service_register_msg_handler()注册接收函数。 - 在回调中快速校验/转存数据;通过
ux_api_spp_service_send_data()向对端发送。
BLE 数传
- 先使能 BLE,并等待
process_ble_enable_result()完成 GATT 服务初始化和广播启动。 - 调用
ux_api_ble_service_register_msg_handler()注册接收函数。 - 收到数据后用
ux_api_ble_service_send_data()发送响应或业务数据。
通用使用规则
ux_api_bt_config()的len必须与目标配置项的数据类型大小完全一致;名称最大 32 Byte(含\\0),且为 UTF-8 字符串。- 使用
ux_api_bt_get_profile_state()判断连接中、已连接、断开中、已断开等状态,不能只依据发起接口的返回值。 - 蓝牙音频流开始前,目标设备须已连接且支持该 profile;未启动流时调用停止接口会报错。
- AVRCP 绝对音量范围为
0x00~0x7F,HFP 音量范围为0~15;静音会覆盖当前音量状态。 - 播放控制仅对可控制的对端状态有效;拨号请求必须以
param和param_len传入电话号码。
接口与关键配置
本示例涉及的接口
UX API 目前未在 api-reference 下生成独立接口页面,以下接口名可直接跳转到公开头文件中的声明行。errcode_t 的通用说明可参见 errcode API 参考。若当前文档查看器不支持 #L 行号片段,链接仍会打开对应头文件。
头文件快速入口
- 蓝牙连接与 SPP:ux_api_bt.h
- BLE 数传与广播配置:ux_api_ble.h
- 蓝牙音频:ux_api_bt_audio.h
- 通话、音量与播放控制:ux_api_bt_control.h
| 接口声明 | 用途 |
|---|---|
| ux_api_bt_enable / ux_api_bt_disable | 启用或关闭 BR/BLE 协议栈;完成状态异步上报 |
| ux_api_bt_start_discovery / ux_api_bt_stop_discovery | 按中心/外围角色启动或停止扫描、广播 |
| ux_api_bt_pair_device / ux_api_bt_connect | 配对新设备,或连接已配对设备的指定 profile |
| ux_api_bt_disconnect / ux_api_bt_remove_device | 断开链路或删除 BR/BLE 配对信息 |
| ux_api_bt_get_profile_state | 查询连接中、已连接、断开中、已断开等状态 |
| ux_api_bt_get_name / ux_api_bt_config | 读取或配置本机名称、地址、广播扩展数据、连接参数等 |
| ux_api_bt_get_device_info / ux_api_bt_get_device_info_by_id | 查询当前设备信息 |
| ux_api_spp_service_register_msg_handler / ux_api_spp_service_send_data | 注册 SPP 接收回调、发送 SPP 数据 |
| ux_api_ble_service_register_msg_handler / ux_api_ble_service_send_data | 注册 BLE 接收回调、通过 GATT Notify 发送数据 |
| ux_api_bt_audio_get_info / ux_api_bt_audio_start / ux_api_bt_audio_stop | 查询、启动或停止 A2DP/SCO 音频流 |
| ux_api_bt_control_volume / ux_api_bt_control_play / ux_api_bt_control_call | 音量、播放与通话控制 |
关键配置与源码事实
| 配置/条件 | 作用 | 当前 diting-community 配置 |
|---|---|---|
DEMO_WATCH |
选择手表 UX 与 native UI 路径 | 已启用 |
CONFIG_SUPPORT_BLE |
编入 BLE 协议栈与 ux_api_bt_enable(BLE) 实现 |
已启用 |
CONFIG_SUPPORT_UX_GATT |
使能后由 BLE 成功回调初始化 UX GATT 数传服务 | 已启用 |
CONFIG_SUPPORT_BR |
编入 BR 协议栈 | 已启用 |
CONFIG_SUPPORT_UX_SPP |
使能后由 BR 成功回调初始化 UX SPP 服务 | 已启用 |
CONFIG_SUPPORT_UX_TEST_AT |
编入 UX AT 测试入口 | 已启用 |
上述默认项位于 /src/build/config/target_config/3322/config.py。若更改定义,使用 fbb menuconfig diting-community 或维护相同目标的配置文件后,必须完整重新编译。
示例目标与设计
本示例复用当前手表 native UI 的蓝牙初始化:SettingBluetoothModel::Init() 已依次使能 BLE、BR。我们只增加 BLE 接收处理函数,并在 BLE 使能前完成回调注册;手机向 SDK 已创建的 UX GATT 特征写入任意数据时,设备立即通过 Notify 回传完全相同的数据。
这样做不重复调用 ux_api_bt_enable(),可避免与现有设置模块竞争协议栈生命周期,也能直接验证“注册回调 → 收到数据 → 调用 UX API 发送”的完整数传路径。
功能说明
- 使用 SDK 已有的 BLE 广播、GATT 服务与特征,不新增服务定义,也不额外调用
ux_api_bt_start_discovery()。 - 业务回调只打印长度并回显收到的字节;真实产品可在此处解析 TLV/私有协议,再将耗时工作投递到自己的任务或队列。
- 当前 GATT 服务定义在
ux_ble_service.c:服务 UUID 字节序列为{0xAA, 0x00},特征 UUID 字节序列为{0xFF, 0x01},属性为 Read / Write No Response / Notify。不同手机工具对 16 位 UUID 的显示字节序可能不同,以实际扫描到的值为准。
准备工作
- 使用 HiDiTing 开发板、可用的烧录串口及日志串口。
- 手机安装 BLE 调试工具,例如 nRF Connect;手机蓝牙权限已授予。
- 检查上节的
DEMO_WATCH、CONFIG_SUPPORT_BLE、CONFIG_SUPPORT_UX_GATT均已启用。 - 使用工作区根目录下的
src/作为 SDK 根目录执行构建命令。 - 确认系统没有在其他自定义模块中重复启用/关闭 BLE;当前 SDK 的所有权在
SettingBluetoothModel::Init()。 - 本示例放在
SettingBluetoothModel.cpp中时,已有同目录的ux_api_bt.h引用,ux_api_ble.h与其位于同一个公开头文件目录,通常无需改动 CMake。若迁移到独立组件,则在该组件的私有 include 路径中加入${ROOT_DIR}/application/ux/interfaces/solution/bg。
详细编码
步骤 1:添加 BLE 接口头文件
编辑 /src/application/wearable/nativeapp/nativeui/settings/src/model/SettingBluetoothModel.cpp,在已有 /src/application/ux/interfaces/solution/bg/ux_api_bt.h 引用后增加 /src/application/ux/interfaces/solution/bg/ux_api_ble.h:
步骤 2:实现接收并回显的业务回调
在 namespace OHOS 内、SettingBluetoothModel::Init() 之前添加以下函数。日志宏沿用该文件已有的 WEARABLE_LOG* 风格;如项目版本未暴露此宏,可改为项目统一日志接口。
static errcode_t BleEchoHandler(uint8_t *data, uint16_t dataLen)
{
if (data == nullptr || dataLen == 0) {
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BLE echo: invalid data");
return ERRCODE_INVALID_PARAM;
}
WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP,
"BLE echo: receive %u byte(s), first=0x%02x",
static_cast<unsigned int>(dataLen), static_cast<unsigned int>(data[0]));
// 当前 UX BLE 实现按最近一次写入的内部设备 ID 选路;公开 API 的 dev_id 参数不参与选路。
errcode_t ret = ux_api_ble_service_send_data(0, data, dataLen);
if (ret != ERRCODE_SUCC) {
WEARABLE_LOGE(WEARABLE_LOG_MODULE_APP, "BLE echo: send failed, ret=0x%x", ret);
}
return ret;
}
步骤 3:在使能 BLE 前注册回调
在同文件的 SettingBluetoothModel::Init() 中,紧跟 InitBluetoothInfo() 后、首次 ux_api_bt_enable 之前增加注册。该接口在当前实现中仅保存函数指针,不依赖 GATT 服务已建立;提前注册可覆盖协议栈异步初始化期间的窗口期,真正的数据服务仍会在 BLE 成功回调中建立。
void SettingBluetoothModel::Init()
{
#ifndef SUPPORT_AUTO_OTA
InitBluetoothInfo();
ux_api_ble_service_register_msg_handler(0, BleEchoHandler);
WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "BLE echo handler registered");
errcode_t ret = ux_api_bt_enable(UX_API_BT_PROTOCOL_BLE);
WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "ux_api_bt_enable ble ret = %u", ret);
ret = ux_api_bt_enable(UX_API_BT_PROTOCOL_BR);
WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "ux_api_bt_enable br ret = %u", ret);
ClearScansDevicesList();
#endif
}
说明:回调中传入的
data由 UX 事件处理流程持有。示例只在回调期间使用它;若需异步处理,必须自行复制数据。不要在回调中执行长时阻塞、文件 I/O 或等待连接状态的操作。
编译、烧录、运行与调试
编译
说明:本文示例命令以一站式 CLI 为主。实际开发可从以下三种环境中选择,推荐使用一站式 CLI。
| 开发环境 | 适用场景 | 使用指南 |
|---|---|---|
| 一站式 CLI(推荐) | 快速完成目标选择、构建、烧录和串口监视 | 一站式 CLI 开发环境使用指南 |
| HiSpark Studio for VS Code | 图形化编辑、编译、烧录和调试 | HiSpark Studio for VS Code 开发环境使用指南 |
| WSL 与 Docker | 在 Windows 上使用一致的 Linux 容器构建环境 | WSL 与 Docker 环境使用指南 |
完成一站式 CLI 环境配置后执行:
构建成功后,固件包为 <FBB_SDK_DIR>/output/3322/fwpkg/diting-community.fwpkg。
烧录与启动
使用一站式 CLI 烧录。以下为 Windows USB DFU 示例;将 COM3 替换为实际日志串口,其他平台和串口烧写参数参见一站式 CLI 开发环境使用指南:
fbb flash -f "$env:FBB_SDK_DIR\output\3322\fwpkg\diting-community.fwpkg" --chip 3322 -d --timeout 180
fbb monitor --port COM3 --baud 750000
烧录完成后复位开发板,打开日志串口,等待 native UI 和蓝牙初始化完成。若使用两根串口线,烧录口和日志口可不同;不要让多个工具同时占用同一个串口。
手机侧验证步骤与预期结果
- 在日志中确认 BLE 使能成功,重点关注
process_ble_enable_result、ble enable success或自行新增的ux_api_bt_enable ble ret日志。 - 用 nRF Connect 扫描并连接开发板广播的 BLE 设备。
- 在 GATT 服务列表中定位 UX 数据服务及具备 Write / Write No Response / Notify 属性的特征;先订阅 Notify。
- 向该特征写入一组易识别字节,例如
48 69 44 69 54 69 6E 67(ASCII:HiDiTing)。 - 预期日志出现
BLE echo: receive 8 byte(s);手机端收到同样的 8 字节 Notify 数据。
如果手机能写入但收不到通知,优先确认已订阅 Notify、当前连接没有断开,以及数据服务已在 BLE 异步使能成功后完成初始化。
调试方法
建议按“配置 → 协议栈 → 服务 → 业务回调 → 手机端”的顺序定位,避免只盯应用回调。
| 检查层 | 观察点 | 对应源码 |
|---|---|---|
| 编译配置 | CONFIG_SUPPORT_BLE、CONFIG_SUPPORT_UX_GATT 是否进入目标定义 |
/src/build/config/target_config/3322/config.py |
| 协议栈启动 | ux_api_bt_enable(BLE) 返回值及 BLE enabled 回调日志 |
/src/application/ux/watch/bg/gap/ux_bt.c、/src/application/ux/watch/bg/gap/ux_bt_ble.c |
| 广播与服务 | process_ble_enable_result() 是否执行到启动广播、ux_bs_ble_service_init() 是否成功 |
/src/application/ux/watch/bg/gap/ux_bt_ble.c、/src/application/ux/solution/bg/ble/ux_ble_service.c |
| 接收路径 | ux_ble_data_received_callback() 是否有数据、是否成功投递 BLE_HOST 消息 |
/src/application/ux/solution/bg/ble/ux_ble_service.c |
| 业务回调 | 是否在 BLE 使能前完成注册、是否被其他模块覆盖、回调是否快速返回 | /src/application/ux/interfaces/solution/bg/ux_api_ble.h、/src/application/ux/solution/bg/ble/ux_ble_service.c |
| 发送路径 | ux_api_ble_service_send_data() 的返回码及手机是否订阅 Notify | /src/application/ux/solution/bg/ble/ux_ble_service.c |
可临时增加以下最小日志:
WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "BLE echo handler registered");
WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "BLE echo rx len=%u", static_cast<unsigned int>(dataLen));
同时保持日志不过度打印完整长报文;产品代码只记录长度、消息类型与必要的截断字段,避免泄露用户数据或拖慢 UX 事件处理。
文件结构与代码走读
文件结构
src/application/
├── ux/
│ ├── interfaces/solution/bg/ # UX 公开头文件
│ ├── watch/bg/gap/ # BLE、BR 协议栈生命周期
│ └── solution/bg/ble/ # BLE GATT 数传服务
└── wearable/nativeapp/nativeui/
├── settings/src/model/ # 公版蓝牙初始化与示例接入点
├── include/ # native UI 组件头文件
└── uxbleecho/src/ # 按第 4 章新建的业务 Demo
各文件职责
| 文件 | 职责 |
|---|---|
| /src/application/ux/interfaces/solution/bg/ux_api_bt.h | BR/BLE 使能、发现、配对、连接、SPP 数传等公开接口。 |
| /src/application/ux/interfaces/solution/bg/ux_api_ble.h | BLE 数传回调注册、Notify 发送和 BLE 广播配置接口。 |
| /src/application/ux/watch/bg/gap/ux_bt_ble.c | BLE 使能成功后配置名称、地址、安全参数、启动广播并初始化 UX GATT 服务。 |
| /src/application/ux/solution/bg/ble/ux_ble_service.c | 定义 GATT 服务与特征,将写入数据投递至 UX 事件框架,并调用业务 handler。 |
| /src/application/wearable/nativeapp/nativeui/settings/src/model/SettingBluetoothModel.cpp | 公版 native UI 的蓝牙初始化入口,也是本章最小修改示例的接入位置。 |
代码走读
BLE 服务启动与数据分发
SettingBluetoothModel::Init()调用ux_api_bt_enable(UX_API_BT_PROTOCOL_BLE)。- BLE 协议栈回调进入
process_ble_enable_result(),启动外围广播;启用CONFIG_SUPPORT_UX_GATT后调用ux_bs_ble_service_init()。 - 手机向数据特征写入时,
ux_ble_data_received_callback()复制报文并投递UX_EVENT_TYPE_BLE_HOST。 process_ble_service_msg()调用由ux_api_ble_service_register_msg_handler()保存的业务回调;回调再通过ux_api_ble_service_send_data()发送 Notify。
示例实现对应关系
| 示例步骤 | 复用的 SDK 实现 | 说明 |
|---|---|---|
| 注册业务回调 | ux_api_ble_service_register_msg_handler() | 当前实现只保存一个函数指针;在 BLE 使能前注册可避免初始化窗口期。 |
| BLE 使能 | SettingBluetoothModel::Init() | 当前设置模块调用 ux_api_bt_enable(BLE)。 |
| BLE 就绪后建服务 | process_ble_enable_result() | 启动外围发现;启用 CONFIG_SUPPORT_UX_GATT 时创建 BLE 数传服务。 |
| 手机数据进入 UX | ux_ble_data_received_callback() | 从 GATT 写回调复制数据并投递 UX_EVENT_TYPE_BLE_HOST。 |
| 分发到业务回调 | process_ble_service_msg() | 调用已注册的 ux_api_ble_msg_handler。 |
| 回显数据 | ux_api_ble_service_send_data() | 经当前 GATT 特征支持的 Notify 回传。 |
相关源码索引
| 主题 | 文件 |
|---|---|
| UX 接口说明 | 本文各接口章节 |
| UX 全部公开头文件入口 | /src/application/ux/interfaces/ |
| UX 蓝牙与 SPP 公开接口 | /src/application/ux/interfaces/solution/bg/ux_api_bt.h |
| UX BLE 公开接口 | /src/application/ux/interfaces/solution/bg/ux_api_ble.h |
| UX 音频与控制公开接口 | /src/application/ux/interfaces/solution/bg/ux_api_bt_audio.h、/src/application/ux/interfaces/solution/bg/ux_api_bt_control.h |
| BLE 数传服务实现 | /src/application/ux/solution/bg/ble/ux_ble_service.c |
| SPP 数传服务实现 | /src/application/ux/solution/bg/spp/ux_spp_service.c |
| BLE 协议栈与数传服务启动 | /src/application/ux/watch/bg/gap/ux_bt_ble.c |
| BR/SPP 服务启动 | /src/application/ux/watch/bg/gap/ux_bt_br.c |
| UX 连接 API 实现 | /src/application/ux/watch/bg/gap/ux_bt.c |
| 现有 BLE/SPP AT 发送测试 | /src/application/ux/cli/at/test/ux_at_ble_test.c、/src/application/ux/cli/at/test/ux_at_spp_test.c |
| 当前 native UI 蓝牙初始化 | /src/application/wearable/nativeapp/nativeui/settings/src/model/SettingBluetoothModel.cpp |
| 构建与烧录环境 | 一站式 CLI 开发环境使用指南 |
基于 BLE 数传回显 Demo 开发自己的应用
当业务不适合放在设置模块时,可将回显逻辑拆分为独立的 native UI 组件,同时仍由 SettingBluetoothModel::Init() 负责协议栈生命周期。当前 native app 的 /src/application/wearable/nativeapp/CMakeLists.txt 会递归收集 nativeui/ 下的 .cpp 文件,并已导出 nativeui/include;按下列结构新建文件时不需要额外登记源文件。
文件结构
src/application/wearable/nativeapp/nativeui/
├── include/uxbleecho/
│ └── UxBleEchoDemo.h
└── uxbleecho/src/
└── UxBleEchoDemo.cpp
代码清单
创建 nativeui/include/uxbleecho/UxBleEchoDemo.h:
#ifndef UX_BLE_ECHO_DEMO_H
#define UX_BLE_ECHO_DEMO_H
namespace OHOS {
void RegisterUxBleEchoDemo(void);
}
#endif
创建 nativeui/uxbleecho/src/UxBleEchoDemo.cpp:
#include <stdint.h>
#include "wearable_log.h"
#include "ux_api_ble.h"
#include "uxbleecho/UxBleEchoDemo.h"
namespace OHOS {
namespace {
errcode_t UxBleEchoHandler(uint8_t *data, uint16_t dataLen)
{
if (data == nullptr || dataLen == 0) {
return ERRCODE_INVALID_PARAM;
}
WEARABLE_LOGI(WEARABLE_LOG_MODULE_APP, "UX BLE echo rx len=%u",
static_cast<unsigned int>(dataLen));
return ux_api_ble_service_send_data(0, data, dataLen);
}
} // namespace
void RegisterUxBleEchoDemo(void)
{
ux_api_ble_service_register_msg_handler(0, UxBleEchoHandler);
}
} // namespace OHOS
CMakeLists.txt 修改示例
现有 native app 已使用 file(GLOB_RECURSE SOURCES "${NativeApp}/nativeui/*.cpp") 自动收集上述 .cpp 文件,通常无需修改 CMake。若改为独立组件,在该组件的私有 include 路径中加入:
接入初始化
- 在 /src/application/wearable/nativeapp/nativeui/settings/src/model/SettingBluetoothModel.cpp 中包含
uxbleecho/UxBleEchoDemo.h。 -
将下列调用放在
InitBluetoothInfo()后、ux_api_bt_enable(UX_API_BT_PROTOCOL_BLE)前。 -
一个 UX BLE 数传服务仅保存一个 handler;新增 Demo 前确认没有其他模块调用
ux_api_ble_service_register_msg_handler(),避免后注册的回调覆盖前者。
测试验证
编译、烧录并使用手机写入数据。预期日志为 UX BLE echo rx len=<长度>,手机在订阅 Notify 后收到同一字节序列。若要改造成 SPP 回显,将注册/发送接口替换为 ux_api_spp_service_register_msg_handler 和 ux_api_spp_service_send_data,并启用 CONFIG_SUPPORT_BR、CONFIG_SUPPORT_UX_SPP。
注意事项
协议栈与连接注意事项:
- 公版 native UI 已在
SettingBluetoothModel::Init()中使能 BLE、BR;业务 Demo 只注册数据回调,不重复调用ux_api_bt_enable()、ux_api_bt_disable()或手动启动广播。 - 接口返回成功只表示请求已受理。广播、GATT 服务、连接、配对和音频流状态必须通过 UX 消息、日志或状态查询确认。
- BR 配对前先停止扫描;已配对设备回连前通过
ux_api_bt_get_profile_state()查询基础链路和目标 profile 状态。
BLE 数传注意事项:
data仅在回调期间有效;异步处理前自行复制。回调中避免阻塞、文件 I/O、配对、连接和断连操作。- UX GATT 数据特征不支持 Indicate;手机须先订阅 Notify。当前实现还会忽略公开发送 API 的
dev_id,多连接产品必须在服务层补齐按连接句柄发送的能力。 ux_api_ble_service_register_msg_handler()只保存一个 handler;应在 BLE 使能前注册,且避免被后续注册覆盖。
配置与音频注意事项:
ux_api_bt_config()的长度与数据类型必须一致;本机名称最大 32 Byte(含\0),使用 UTF-8 字符串。- 音频流开始前确认对端已连接且支持目标 profile;AVRCP 绝对音量范围为
0x00~0x7F,HFP 音量范围为0~15。
常见编译错误
| 错误现象 | 原因 | 解决方法 |
|---|---|---|
fatal error: ux_api_ble.h: No such file or directory |
独立组件未添加 UX solution/bg 的头文件路径 | 在组件 CMake 的 PRIVATE_HEADER 中加入 ${ROOT_DIR}/application/ux/interfaces/solution/bg。 |
undefined reference to ux_api_ble_service_send_data |
未启用或未编入 UX GATT 服务实现 | 检查 CONFIG_SUPPORT_BLE、CONFIG_SUPPORT_UX_GATT,修改后完整重新编译。 |
errcode_t、ERRCODE_INVALID_PARAM 未定义 |
源文件未包含 ux_api_ble.h 或调用代码放在错误的编译单元 |
在业务 .cpp 中包含 ux_api_ble.h,并确认该文件位于 native app 的源码收集范围。 |
multiple definition of RegisterUxBleEchoDemo |
同名业务源码被重复加入多个组件或目录 | 保留唯一实现文件;native app 已递归收集 nativeui/ 下的 .cpp,不要重复在其他组件添加。 |