鸿蒙 蓝牙开发之配对与连接(三)

本文同步发表于微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、功能

  1. 主动配对设备 - 与目标蓝牙设备建立配对关系

  2. 连接设备profile能力 - 连接已配对设备支持的服务能力

前置条件

  • 蓝牙状态:必须确保蓝牙已开启(STATE_ONSTATE_BLE_ON状态)

  • 权限要求:需要申请ohos.permission.ACCESS_BLUETOOTH权限

  • 设备状态:目标设备必须处于可被发现状态

二、开发准备

2.1 权限申请

必需权限ohos.permission.ACCESS_BLUETOOTH

  • 申请步骤

    1. 在配置文件中声明权限

    2. 运行时向用户申请授权

2.2 API模块导入

需要导入多个相关模块以支持完整的配对与连接功能:

import { connection, a2dp, hfp, hid, baseProfile, constant, common } from '@kit.ConnectivityKit';
import { BusinessError } from '@kit.BasicServicesKit';

各模块作用

  • connection:蓝牙连接相关API

  • a2dp:高级音频分发协议支持

  • hfp:免提通话协议支持

  • hid:人机接口设备协议支持

  • baseProfile:基础profile状态管理

  • constant:常量定义(如profile UUID)

  • common:通用类型定义

  • BusinessError:错误处理

三、蓝牙配对功能

3.1 配对状态管理

3.1.1 配对状态类型
  • BOND_STATE_INVALID:未配对或配对无效

  • BOND_STATE_BONDED:已成功配对(目标状态)

  • BOND_STATE_BONDING:正在配对(中间状态)

3.1.2 订阅配对状态变化事件

目的:实时获取配对过程的状态变化

实现代码

// 定义配对状态变化回调函数
function onReceiveEvent(data: connection.BondStateParam) {
    console.info('pair result: ' + JSON.stringify(data));
}

try {
    // 发起订阅配对状态变化事件
    connection.on('bondStateChange', onReceiveEvent);
} catch (err) {
    console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' + (err as BusinessError).message);
}

触发场景

  1. 应用主动发起配对其他设备

  2. 其他设备主动配对本机设备

3.2 发起配对操作

3.2.1 配对前提条件
  • 目标设备状态:必须处于BOND_STATE_INVALID状态

3.2.2 用户交互流程

配对过程中,系统会弹出配对请求对话框,不同配对类型对话框样式可能不同:

  • 确认配对密钥(Confirm Passkey)模式:需要用户确认配对密钥

  • 用户授权:必须用户同意授权才能配对成功

3.2.3 地址类型说明

MAC地址处理机制

  • 实际MAC地址:属于用户隐私信息

  • 虚拟MAC地址:蓝牙子系统为每个蓝牙外设分配的地址

  • 映射关系:系统保存虚拟MAC地址与实际MAC地址的映射关系

3.2.4 API版本适配

API Version 20及以前(推荐)
特点:不需要关注目标设备的MAC地址类型

// 通过发现设备流程获取目标设备地址
let device = '66:66:66:66:66:66';

try {
    // 发起配对
    connection.pairDevice(device).then(() => {
        console.info('pairDevice');
    }, (error: BusinessError) => {
        console.error('pairDevice: errCode:' + error.code + ', errMessage:' + error.message);
    });
} catch (err) {
    console.error('startPair: errCode:' + err.code + ', errMessage:' + err.message);
}

API Version 21开始(需要指定地址类型)
特点:需要同时指定目标设备的MAC地址和地址类型

let btAddr: common.BluetoothAddress = {
    "address": '66:66:66:66:66:66',  // 目标设备的实际MAC地址或虚拟MAC地址
    "addressType": common.BluetoothAddressType.REAL,  // 相应的地址类型
}

try {
    // 发起配对
    connection.pairDevice(btAddr).then(() => {
        console.info('pairDevice');
    }, (error: BusinessError) => {
        console.error('pairDevice: errCode:' + error.code + ', errMessage:' + error.message);
    });
} catch (err) {
    console.error('startPair: errCode:' + err.code + ', errMessage:' + err.message);
}

四、连接设备profile能力

4.1 连接时机与条件

4.1.1 连接前提
  1. 设备已配对:目标设备必须已成功配对(BOND_STATE_BONDED

  2. profile支持:设备必须支持相关profile能力

4.1.2 可连接profile类型

connectAllowedProfiles方法支持连接的profile包括:

  1. A2DP:高级音频分发协议(高质量音频传输)

  2. HFP:免提通话协议(语音通话)

  3. HID:人机接口设备协议(键盘、鼠标等)

4.2 设备profile能力查询

4.2.1 能力获取机制
  • 配对过程中:蓝牙子系统会自动查询和保存目标设备支持的所有profile能力

  • 配对完成后:应用可以主动查询目标设备的profile能力

4.2.2 查询方法
// 查询设备支持的profile UUID列表
let uuids = await connection.getRemoteProfileUuids(device);
4.2.3 连接时间窗口
  • 最佳时机:配对完成后30秒内发起连接

  • 原因:确保设备处于可连接状态

4.3 连接实现流程

4.3.1 创建profile实例
// 创建各profile实例
let a2dpSrc = a2dp.createA2dpSrcProfile();    // A2DP源设备(音频发送端)
let hfpAg = hfp.createHfpAgProfile();         // HFP音频网关(手机端)
let hidHost = hid.createHidHostProfile();     // HID主机设备(接收端)
4.3.2 订阅连接状态变化
// 定义A2DP连接状态变化回调函数
function onA2dpConnectStateChange(data: baseProfile.StateChangeParam) {
    console.info(`A2DP State: ${JSON.stringify(data)}`);
}

// 定义HFP连接状态变化回调函数
function onHfpConnectStateChange(data: baseProfile.StateChangeParam) {
    console.info(`HFP State: ${JSON.stringify(data)}`);
}

// 定义HID连接状态变化回调函数
function onHidConnectStateChange(data: baseProfile.StateChangeParam) {
    console.info(`HID State: ${JSON.stringify(data)}`);
}

try {
    // 订阅各profile连接状态变化事件
    a2dpSrc.on('connectionStateChange', onA2dpConnectStateChange);
    hfpAg.on('connectionStateChange', onHfpConnectStateChange);
    hidHost.on('connectionStateChange', onHidConnectStateChange);
} catch (err) {
    console.error('订阅连接状态失败');
}
4.3.3 发起连接
// 发起连接目标设备支持的profile
connection.connectAllowedProfiles(device).then(() => {
    console.info('connectAllowedProfiles');
}, (error: BusinessError) => {
    console.error('errCode:' + error.code + ',errMessage' + error.message);
});

五、注意事项

5.1 权限与状态管理

  1. 权限验证:确保已获得蓝牙访问权限

  2. 蓝牙状态:使用功能前检查蓝牙是否已开启

  3. 配对状态:发起连接前确认设备已成功配对

5.2 用户交互

  1. 配对确认:配对过程需要用户明确授权

  2. 连接时机:配对完成后尽快发起连接

  3. 错误提示:提供友好的错误提示和恢复建议

5.3 API版本兼容

  1. 配对方式选择:根据API版本选择合适的配对方法

  2. 地址类型处理:API 21+需要指定设备地址类型

  3. 虚拟地址映射:了解系统对MAC地址的处理机制

5.4 错误处理策略

  1. 网络异常:处理设备不可达或连接超时

  2. 用户拒绝:处理用户拒绝配对授权的情况

  3. 设备不支持:处理设备不支持特定profile的情况

  4. 状态异常:处理配对或连接过程中的异常状态

5.5 核心流程

  1. 准备阶段:申请权限、导入模块、检查蓝牙状态

  2. 配对阶段:订阅配对状态、发起配对请求、处理用户授权

  3. 连接阶段:查询profile能力、订阅连接状态、发起连接

5.6 资源管理

  1. 事件监听:及时注册和注销事件监听器

  2. 实例管理:合理管理profile实例生命周期

  3. 内存释放:使用完毕后及时释放资源

<think> 我们正在讨论鸿蒙系统(HarmonyOS)中的蓝牙开发,特别是关于先配对连接的实现步骤。在鸿蒙中,蓝牙操作主要涉及以下几个关键类: - `BluetoothHost`:代表本地蓝牙设备。 - `BluetoothRemoteDevice`:代表远程蓝牙设备。 - `BluetoothDevice`:用于设备操作,如配对、取消配对、获取设备信息等。 根据鸿蒙开发文档,配对连接是两个不同的操作: 1. **配对(Pair)**:是指两个蓝牙设备之间建立信任关系的过程,通常需要输入或确认配对码。 2. **连接(Connect)**:是指在配对成功后,建立用于数据传输的通道(例如RFCOMM通道)。 ### 先配对连接的步骤 在鸿蒙系统中,实现先配对连接的基本步骤如下: #### 1. 初始化蓝牙 首先,需要获取`BluetoothHost`实例,并检查蓝牙状态,开启蓝牙(如果未开启)。 ```java // 获取BluetoothHost实例 BluetoothHost bluetoothHost = BluetoothHost.getDefaultHost(context); // 检查蓝牙是否开启,如果没有则开启 if (!bluetoothHost.isBluetoothEnabled()) { bluetoothHost.enableBluetooth(); } ``` #### 2. 发现设备并配对 在开始发现设备后,当发现目标设备时,进行配对操作。 ```java // 启动发现 bluetoothHost.startBluetoothDiscovery(); // 注册发现设备的回调 BluetoothHost.IDiscoveryCallback discoveryCallback = new BluetoothHost.IDiscoveryCallback() { @Override public void onDiscoveryStarted() { // 发现开始 } @Override public void onDiscoveryFinished() { // 发现结束 } @Override public void onDeviceFound(BluetoothRemoteDevice device) { // 发现设备 // 检查设备是否为需要配对的设备(例如通过设备名称或地址) if ("目标设备名称".equals(device.getName()) || "目标设备地址".equals(device.getDeviceAddr())) { // 停止发现 bluetoothHost.stopBluetoothDiscovery(); // 进行配对 device.startPair(); } } @Override public void onPairStatusUpdated(BluetoothRemoteDevice device, int status) { // 配对状态更新 if (status == BluetoothDevice.PAIRING_STATE_PAIRED) { // 配对成功,可以尝试连接 } else if (status == BluetoothDevice.PAIRING_STATE_FAILED) { // 配对失败 } } }; // 注册发现回调 bluetoothHost.registerDiscoveryCallback(discoveryCallback); ``` 注意:配对操作会触发一个系统级的配对请求对话框,用户需要确认配对码(如果需要)。配对状态的变化会通过`onPairStatusUpdated`回调。 #### 3. 建立连接 配对成功后,我们可以使用`BluetoothRemoteDevice`的方法来建立连接连接的类型取决于你要使用的蓝牙协议(例如RFCOMM用于串行通信,或GATT用于低功耗蓝牙)。 ##### 经典蓝牙(RFCOMM)连接 对于经典蓝牙,通常使用RFCOMM套接字进行数据传输。 ```java // 配对成功后,在onPairStatusUpdated回调中 if (status == BluetoothDevice.PAIRING_STATE_PAIRED) { // 创建RFCOMM连接 try { BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID.fromString("你的服务UUID")); socket.connect(); // 连接 // 连接成功后,可以通过socket获取输入输出流进行数据传输 } catch (IOException e) { e.printStackTrace(); } } ``` ##### 低功耗蓝牙(BLE)连接 对于BLE设备,连接过程涉及GATT操作。 ```java // 配对成功后,在onPairStatusUpdated回调中 if (status == BluetoothDevice.PAIRING_STATE_PAIRED) { // 创建Gatt连接 device.connectGatt(context, true, new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothGatt.STATE_CONNECTED) { // 连接成功,可以开始发现服务 gatt.discoverServices(); } else if (newState == BluetoothGatt.STATE_DISCONNECTED) { // 连接断开 } } // ... 其他回调方法(如onServicesDiscovered等) }); } ``` ### 注意事项 - 权限:在`config.json`中需要声明蓝牙权限,并且在运行时动态申请位置权限(因为蓝牙发现需要位置权限)。 - 配对状态监听:需要监听配对状态的变化,以确保在配对成功后再进行连接操作。 - 连接管理:连接成功后,需要管理连接的生命周期,并在不需要时及时断开连接以节省资源。 ### 总结 在鸿蒙开发中实现蓝牙配对连接的步骤概括为: 1. 初始化蓝牙,确保蓝牙开启。 2. 发现目标设备,并调用`startPair()`方法发起配对。 3. 监听配对状态,当状态变为已配对(`PAIRING_STATE_PAIRED`)时,发起连接(RFCOMM或GATT)。 4. 连接建立后,进行数据传输。 以上步骤基于HarmonyOS 3.0 API 8或以上版本,具体实现时请参考官方文档和实际使用的版本。 §§相关问题§§ 1. 在鸿蒙蓝牙开发中,如何处理配对请求的确认(比如配对码)? 2. 鸿蒙系统中,如何取消蓝牙配对? 3. 在鸿蒙中,如何实现蓝牙设备的重连机制? 4. 鸿蒙蓝牙连接过程中有哪些常见的错误码,如何解决? </think> 在鸿蒙HarmonyOS开发中,实现蓝牙配对连接的流程需要遵循以下核心步骤,基于HarmonyOS 3.0+的蓝牙API设计: --- ### **一、实现步骤** #### 1. **初始化蓝牙适配器** ```java // 获取蓝牙适配器实例 BluetoothHost bluetoothHost = BluetoothHost.getDefaultHost(context); // 检查并开启蓝牙 if (!bluetoothHost.isBluetoothEnabled()) { bluetoothHost.enableBluetooth(); // 触发系统弹窗请求用户授权 } ``` #### 2. **设备扫描配对** ```java // 注册设备扫描回调 bluetoothHost.registerDiscoveryCallback(new IDiscoveryCallback() { @Override public void onDeviceFound(BluetoothRemoteDevice device) { if (targetDevice.equals(device.getDeviceName())) { // 发起配对请求(触发系统级配对弹窗) device.startPair(); } } }); // 监听配对状态 bluetoothHost.registerPairCallback(new IPairCallback() { @Override public void onPairRequested(BluetoothRemoteDevice device) { // 系统自动处理配对码验证(用户可见弹窗) } @Override public void onPairConfirmed(BluetoothRemoteDevice device, int reqType) { // 配对成功回调 connectToDevice(device); // 进入连接流程 } }); // 开始扫描设备 bluetoothHost.startBluetoothDiscovery(); ``` #### 3. **建立蓝牙连接** ```java private void connectToDevice(BluetoothRemoteDevice device) { // 创建GATT连接(BLE设备) BluetoothGattClient gattClient = device.connectGatt(context, true, new BluetoothGattClientCallback() { @Override public void onConnectionStateChange(BluetoothGattClient client, int status, int newState) { if (newState == BluetoothGatt.STATE_CONNECTED) { // 连接成功,可进行服务发现和数据传输 client.discoverServices(); } } }); } ``` #### 4. **权限声明(config.json)** ```json "reqPermissions": [ { "name": "ohos.permission.USE_BLUETOOTH", "reason": "蓝牙操作必需" }, { "name": "ohos.permission.DISCOVER_BLUETOOTH", "reason": "设备扫描必需" }, { "name": "ohos.permission.MANAGE_BLUETOOTH", "reason": "配对管理必需" } ] ``` --- ### **二、关键机制说明** 1. **配对连接分离** - 配对(`startPair()`)是信任建立,由系统弹窗处理PIN码验证[^1]。 - 连接(`connectGatt()`)是物理链路建立,需在配对成功后调用。 2. **配对状态监听** 通过`IPairCallback`监听: - `onPairRequested()`:配对请求事件 - `onPairConfirmed()`:配对成功事件 - `onPairFailed()`:配对失败事件 3. **经典蓝牙BLE统一** - 配对流程相同(均用`startPair()`)。 - 连接区分: - **BLE**:`connectGatt()` - **经典蓝牙**:`createRfcommSocket()`(需指定UUID) --- ### **、注意事项** 1. **权限时序** 必须在`onStart()`阶段动态申请`MANAGE_BLUETOOTH`权限,否则配对操作会失败。 2. **配对超时处理** 建议添加超时机制(例如30秒后取消配对): ```java new Handler(Looper.getMainLooper()).postDelayed(() -> { if (!isPaired) device.cancelPair(); }, 30000); ``` 3. **重连机制** 已配对设备可通过`BluetoothHost.getPairedDevices()`直接获取,无需重新扫描。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值