智能客服
你问我答,随时在线为你解决问题
如果应用已经与对端蓝牙设备建立过BLE蓝牙连接,那么如何不通过蓝牙扫描,就能够与之前已连接过的蓝牙设备快速建立连接?
方案一、方案二完整代码如下:
- import { access, ble, connection, constant } from '@kit.ConnectivityKit';
-
- @Entry
- @Component
- struct Reconnect {
- @State gattClient: ble.GattClientDevice | undefined = undefined;
-
- // 方案一
- ReconnectOne() {
- // 先查询已配对设备列表,判断需要连接的设备是否在已配对设备列表中存在。
- let devices = connection.getPairedDevices();
- for (let index = 0; index < devices.length; index++) {
- let name = connection.getRemoteDeviceName(devices[index]);
- // 需要连接的设备在已配对设备列表中存在,无需发起扫描,直接创建实例进行连接。
- if (name === 'name') {
- // 创建ble蓝牙client实例
- this.gattClient = ble.createGattClientDevice(devices[index]);
- // 连接前先创建连接状态回调监听
- this.onBLEConnectionStateChangeOne();
- // 连接ble蓝牙
- this.gattClient.connect();
- return;
- }
- }
- // 需要连接的设备在已配对设备列表中不存在,开启常规ble蓝牙连接流程。
- // 订阅BLE设备发现
- this.onBLEDeviceFindOne();
- // 过滤参数可根据实际场景进行设置
- let scanFilter: ble.ScanFilter = {
- name: 'name'
- };
- // 扫描参数可根据实际场景配置
- let scanOptions: ble.ScanOptions = {
- interval: 500,
- dutyMode: ble.ScanDuty.SCAN_MODE_LOW_POWER,
- matchMode: ble.MatchMode.MATCH_MODE_AGGRESSIVE,
- };
- ble.startBLEScan([scanFilter], scanOptions);
- }
-
- onBLEDeviceFindOne() {
- ble.on('BLEDeviceFind', (data: Array<ble.ScanResult>) => {
- // 发现设备,创建实例进行连接。
- this.gattClient = ble.createGattClientDevice(data[0].deviceId);
- // 连接前先创建连接状态回调监听
- this.onBLEConnectionStateChangeOne();
- // 连接ble蓝牙
- this.gattClient.connect();
- // 连接成后,将已连接设备加入配对列表。
- // 注意:加入配对列表时机并不固定,可根据实际场景来进行变更。
- connection.pairDevice(data[0].deviceId, () => {
- console.info('pairDevice err');
- });
- });
- }
-
- onBLEConnectionStateChangeOne() {
- this.gattClient?.on('BLEConnectionStateChange', (state: ble.BLEConnectionChangeState) => {
- if (state.state === constant.ProfileConnectionState.STATE_DISCONNECTED) {
- // 如果蓝牙意外断开了连接,可以在此处重新发起连接,以达到意外断连快速回连能力。
- // 不过需要保证此时this.gattClient实例没有被销毁。
- this.gattClient?.connect();
- }
- });
- }
-
- // 方案二
- ReconnectTwo() {
- // 先查询已固化设备列表,判断需要连接的设备是否在已固化设备列表中存在。
- let devices = access.getPersistentDeviceIds();
- for (let index = 0; index < devices.length; index++) {
- let name = connection.getRemoteDeviceName(devices[index]);
- let isValid = access.isValidRandomDeviceId(devices[index]);
- // 需要连接的设备在已固化设备列表中存在,同时该地址有效,无需发起扫描,直接创建实例进行连接。
- if (isValid && name === 'name') {
- // 创建ble蓝牙client实例
- this.gattClient = ble.createGattClientDevice(devices[index]);
- // 连接前先创建连接状态回调监听
- this.onBLEConnectionStateChangeTwo();
- // 连接ble蓝牙
- this.gattClient.connect();
- return;
- }
- }
- // 需要连接的设备在已固化设备列表中不存在,开启常规ble蓝牙连接流程。
- // 订阅BLE设备发现
- this.onBLEDeviceFindTwo();
- // 过滤参数可根据实际场景进行设置
- let scanFilter: ble.ScanFilter = {
- name: 'name'
- };
- // 扫描参数可根据实际场景配置
- let scanOptions: ble.ScanOptions = {
- interval: 500,
- dutyMode: ble.ScanDuty.SCAN_MODE_LOW_POWER,
- matchMode: ble.MatchMode.MATCH_MODE_AGGRESSIVE,
- };
- ble.startBLEScan([scanFilter], scanOptions);
- }
-
- onBLEDeviceFindTwo() {
- ble.on('BLEDeviceFind', (data: Array<ble.ScanResult>) => {
- // 发现设备,创建实例进行连接。
- this.gattClient = ble.createGattClientDevice(data[0].deviceId);
- // 连接前先创建连接状态回调监听
- this.onBLEConnectionStateChangeTwo();
- // 连接ble蓝牙
- this.gattClient.connect();
- // 连接成后,将已连接设备加入固化列表。
- // 注意:加入固化列表时机并不固定,可根据实际场景来进行变更。
- access.addPersistentDeviceId(data[0].deviceId);
- });
- }
-
- onBLEConnectionStateChangeTwo() {
- this.gattClient?.on('BLEConnectionStateChange', (state: ble.BLEConnectionChangeState) => {
- if (state.state === constant.ProfileConnectionState.STATE_DISCONNECTED) {
- // 如果蓝牙意外断开了连接,可以在此处重新发起连接,以达到意外断连快速回连能力。
- // 不过需要保证此时this.gattClient实例没有被销毁。
- this.gattClient?.connect();
- }
- });
- }
-
- build() {
- Column() {
- Button('ble蓝牙连接/支持快速回连(方案1)').onClick(() => {
- // 发起连接
- this.ReconnectOne();
- });
- Button('ble蓝牙连接/支持快速回连(方案2)').onClick(() => {
- // 发起连接
- this.ReconnectTwo();
- });
- }.height('100%')
- .width('100%')
- .justifyContent(FlexAlign.SpaceAround);
- }
- }
由于方案二需要使用受限开放的ohos.permission.PERSISTENT_BLUETOOTH_PEERS_MAC权限,一般建议使用方案一。若业务中不能包含配对场景,且可以成功申请ohos.permission.PERSISTENT_BLUETOOTH_PEERS_MAC权限,就可以采取方案二。
Q:由于担心蓝牙虚拟MAC地址变化,需要在重新连接前一直扫描,会造成资源消耗,应该如何解决?
A:可以使用addPersistentDeviceId持久化蓝牙地址,就不需要在重连前一直扫描。
Q:使用addPersistentDeviceId持久化后,是否即使蓝牙设备关机重启,只要蓝牙物理MAC地址不变,被持久化的虚拟MAC地址也不会发生改变?
A:是的,只要对端蓝牙设备真实地址保持不变,那么被addPersistentDeviceId接口持久化的虚拟MAC地址就不会发生改变。
Q:使用addPersistentDeviceId固化蓝牙虚拟MAC地址后,调用deletePersistentDeviceId删除该地址,再次查询固化列表时发现被删除的地址仍然存在,如何解决?
A:该问题出现在调试阶段,由于应用前后两次签名发生变化,系统未能识别差异,导致固化地址无法正常删除。在正式版本中不会出现此问题。若在调试阶段遇到此问题,可通过"设置>系统>重置>还原网络设置"清除相关数据解决。