一. 蓝牙应用的种类
openvela 支持两种蓝牙应用开发模式:基于 Native C API 接口开发和基于快应用 JS API 接口开发。前者可以调用所有蓝牙相关能力,但跨平台移植较困难;后者仅需一次开发,跨平台复用性高,但目前仅提供有限的蓝牙能力调用。
1.基于快应用的开发
快应用蓝牙接口基于 QuickJS 引擎,通过 C++ 封装为第三方应用提供高层 API 接口。蓝牙接口请参考 QuickApp Bluetooth API 文档(https://doc.quickapp.cn/features/system/bluetooth.html)。
目前支持的蓝牙能力包括:打开和关闭蓝牙、查询和监听蓝牙状态、开始和停止蓝牙扫描、查询和监听扫描结果、连接和断开蓝牙、查询已连接的蓝牙设备、查询 BLE 设备的 Services、读写 BLE 设备的特征值(Characteristic)。
2.基于 Native NDK 的开发
另一种是基于 NDK(Native Development Kit)接口直接调用蓝牙系统的全部能力,使用 C 语言进行 Native 应用开发。所有可用的 API 声明位于目录 framework/connectivity/bluetooth/framework/include 中,如下表所示。
| 头文件 | 接口描述 |
|---|---|
| bluetooth.h | 实例管理:蓝牙 instance 的创建,通过同步或异步方式对蓝牙 Service 执行远程函数调用(RPC),以及向蓝牙 Service 注册 callback |
| bt_adapter.h | 本地适配器管理:包含蓝牙服务对本地 Bluetooth Adapter 的所有 RPC 调用 |
| bt_device.h | 远端设备管理:包含蓝牙服务对 Remote Device 的所有 RPC 调用 |
| bt_a2dp_sink.h | 包含蓝牙 Service 对 A2DP Sink 服务的所有 RPC 调用 |
| bt_a2dp_source.h | 包含蓝牙 Service 对 A2DP Source 服务的所有 RPC 调用 |
| bt_avrcp_control.h | 包含蓝牙 Service 对 AVRCP Control 服务的所有 RPC 调用 |
| bt_avrcp_target.h | 包含蓝牙 Service 对 AVRCP Target 服务的所有 RPC 调用 |
| bt_hfp_ag.h | 包含蓝牙 Service 对 HFP AG 服务的所有 RPC 调用 |
| bt_hfp_hf.h | 包含蓝牙 Service 对 HFP HF 服务的所有 RPC 调用 |
| bt_hid_device.h | 包含蓝牙 Service 对 HID Device 服务的所有 RPC 调用 |
| bt_spp.h | 包含蓝牙 Service 对 SPP 服务的所有 RPC 调用 |
| euv_pipe.h | 包含蓝牙 Service 对 SPP 数据文件节点的读写操作 |
| bt_l2cap.h | 包含蓝牙 Service 对 LE L2CAP CoC 服务的所有 RPC 调用 |
| bt_le_advertiser.h | 包含蓝牙 Service 对 LE Advertising 服务的所有 RPC 调用 |
| bt_le_scan.h | 包含蓝牙 Service 对 LE Scan 服务的所有 RPC 调用 |
| bt_gattc.h | 包含蓝牙 Service 对 GATT Client 服务的所有 RPC 调用 |
| bt_gatts.h | 包含蓝牙 Service 对 GATT Server 服务的所有 RPC 调用 |
二. 蓝牙原生应用开发
- 运行时模型
以下是一个典型的蓝牙应用工作流:
(1)获取蓝牙实例(Instance)
开发者需根据业务场景对实时性的要求,选择创建同步或异步实例。
同步实例通过 bluetooth_create_instance() 获取。该实例用于发送同步命令,调用后会阻塞应用当前线程,直到蓝牙服务执行完毕并返回才继续运行,如下图所示。

异步实例通过 bluetooth_create_async_instance() 获取,调用时需要传入 uv_loop_t 事件循环以及连接和断开的回调函数。该实例用于发送异步命令,调用后不会阻塞应用当前线程,蓝牙服务执行完毕后通过回调通知应用,如下图所示。

(2)注册服务回调(Register Callbacks)
获取实例后,需要根据业务需求向 Bluetooth Service 注册对应模块的回调函数,以便接收服务端的状态更新或数据上报。主要注册接口如下:
基础管理:本地适配器/远程设备使用 bt_adapter_register_callback()。
经典蓝牙音频与通话:A2DP Sink 使用 bt_a2dp_sink_register_callbacks(),A2DP Source 使用 bt_a2dp_source_register_callbacks(),AVRCP Control 使用 bt_avrcp_control_register_callbacks(),AVRCP Target 使用 bt_avrcp_target_register_callbacks(),HFP AG 使用 bt_hfp_ag_register_callbacks(),HFP HF 使用 bt_hfp_hf_register_callbacks()。
低功耗蓝牙(BLE):LE Advertising 在启动时传入回调(bt_le_start_advertising()),LE Scan 在启动时传入回调(bt_le_start_scan()),GATT Client 在连接时传入回调(bt_gattc_create_connect()),GATT Server 在注册服务时传入回调(bt_gatts_register_service()),L2CAP CoC 使用 bt_l2cap_register_callbacks()。
其他协议:HID Device 使用 bt_hid_device_register_callbacks(),SPP 使用 bt_spp_register_app()。
(3)执行远程调用 (RPC)
根据业务需要,向蓝牙 Framework/Service 不同服务发送命令,执行远程函数调用。
(4)回调处理(Callback)
在回调函数中处理蓝牙服务返回的状态变更和数据上报。
2.开发实例
以打开蓝牙为例,介绍蓝牙应用编写的一般思路。更多完整的代码实例,请参考 openvela 官方仓库:https://github.com/open-vela/frameworks_bluetooth/tree/dev/sample_code。
(1)创建蓝牙实例
首先,创建一个同步的蓝牙实例句柄。
/* 创建蓝牙 instance */
static bt_instance_t* g_bt_ins = bluetooth_create_instance();
if (g_bt_ins == NULL) {
LOGE("create instance error");
goto error;
}
(2)声明并注册回调
定义适配器状态变更的回调函数,并将其注册到系统中。
/* 声明 Callback */
const static adapter_callbacks_t app_gap_cbs = {
.on_adapter_state_changed = gap_adapter_state_changed_callback,
};
/* 注册 Callback */
static void* adapter_callback = bt_adapter_register_callback(g_bt_ins, &app_gap_cbs);
if (adapter_callback == NULL) {
LOGE("register callback error.");
goto error;
}
(3)发送命令,远程执行调用
调用 bt_adapter_enable 接口开启蓝牙。由于使用的是同步实例,该函数返回时表示命令已下发(但状态变更可能稍后通过回调上报)。
/* 发送命令 */
if (bt_adapter_enable(g_bt_ins) != BT_STATUS_SUCCESS) {
LOGE("enable adapter error.");
goto error;
}
(4)回调处理(Callback)
/* Callback处理 */
static void gap_adapter_state_changed_callback(void* cookie, bt_adapter_state_t state)
{
LOGE("Bluetooth Adapter State = %d", state);
}