HarmonyOS 鸿蒙Next基于短距离通信的BLE蓝牙扫描

发布于 1周前 作者 bupafengyu 来自 鸿蒙OS

HarmonyOS 鸿蒙Next基于短距离通信的BLE蓝牙扫描

场景描述

蓝牙是一种短距的无线通讯技术,可实现固定设备、移动设备之间的数据交换。一般将蓝牙3.0之前的BR/EDR蓝牙称为传统蓝牙,而将蓝牙4.0规范下的BLE蓝牙称为低功耗蓝牙。BLE模块提供了对蓝牙操作和管理的方法。

场景一:申请蓝牙权限

方案:

ACCESS_BLUETOOTH 权限是很多蓝牙接口需要申请的,比如:ble.getConnectedBLEDevices(获取和当前设备连接的BLE设备)、ble.startBLEScan(发起BLE扫描流程)。这个权限是需要用户授权的,可以通过调用requestPermissionsFromUser()方法来实现。

不鼓励频繁弹窗打扰用户,如果用户拒绝授权,将无法再次拉起弹窗。需要应用引导用户在系统应用“设置”的界面中手动授予权限,参考文档:向用户申请授权

核心代码

requestPermissionsFromUser() {
let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();
try {
let context = getContext(this);
atManager.requestPermissionsFromUser(context, [‘ohos.permission.ACCESS_BLUETOOTH’], (err: BusinessError, data: PermissionRequestResult) => {
console.info(‘data:’ + JSON.stringify(data));
console.info(‘data permissions:’ + data.permissions);
console.info(‘data authResults:’ + data.authResults);
});
} catch (err) {
console.log(<span class="hljs-keyword"><span class="hljs-keyword">catch</span></span> err-&gt;${<span class="hljs-built_in"><span class="hljs-built_in">JSON</span></span>.stringify(err)});
}
}<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

配置文件

module.json文件中申请相关权限,相关权限说明可参考文档:对所有应用开放

“requestPermissions”:[
{
“name” : “ohos.permission.ACCESS_BLUETOOTH”,
“reason”: “$string:module_desc”,
“usedScene”: {
“abilities”: [
“FormAbility”
],
“when”:“always”
}
},
{
“name” : “ohos.permission.DISCOVER_BLUETOOTH”,
“usedScene”: {
“abilities”: [
“FormAbility”
],
“when”:“always”
}
},
{
“name” : “ohos.permission.USE_BLUETOOTH”,
“usedScene”: {
“abilities”: [
“bluetouth”
],
“when”:“always”
}
},
]<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

场景二:BLE蓝牙扫描和系统设置蓝牙扫描

BLE为低功耗蓝牙,只能扫描到低功耗的蓝牙设备。

connection是经典蓝牙,如果想扫描到系统设置中的所有设备,可以调用此接口。

方案:

ble扫描的是低功耗蓝牙,相比于connection扫描结果偏少,如果想要扫描到系统设置中的所有设备,需要去调用@ohos.bluetooth.connection模块中的connection.startbluetoothdiscovery。

核心代码

低功耗蓝牙扫描:ble.startBLEScan

import { BusinessError } from ‘@kit.BasicServicesKit’;
import { ble } from ‘@kit.ConnectivityKit’;

@Entry @Component struct Index { @State onReceiveEventData: string = ‘’ @State isScan: boolean = false // …

build() { Row() { Column() { // 蓝牙扫描 Button(“startBLEScan”) .onClick(() => { this.isScan = !this.isScan let onReceiveEvent = (data: Array<ble.ScanResult>) => { console.info('BLE scan device find result = ’ + JSON.stringify(data)); let dataString = JSON.stringify(data) this.onReceiveEventData = dataString } try { ble.on(“BLEDeviceFind”, onReceiveEvent); let scanFilter: ble.ScanFilter = { // deviceId:“xxxx”, // name:“test”, // serviceUuid:“xxxx” }; console.info(‘scanFilter’ + JSON.stringify(scanFilter)) let scanOptions: ble.ScanOptions = { interval: 50, dutyMode: ble.ScanDuty.SCAN_MODE_LOW_POWER, matchMode: ble.MatchMode.MATCH_MODE_AGGRESSIVE, } ble.startBLEScan(null, scanOptions); } catch (err) { console.error('errCode: ’ + (err as BusinessError).code + ', errMessage: ’ + (err as BusinessError).message); }

      }) 
      .type(ButtonType.Capsule) 
      .margin({ top: <span class="hljs-number"><span class="hljs-number">4</span></span> }) 
      .backgroundColor(<span class="hljs-string"><span class="hljs-string">'#ff1198ee'</span></span>) 
      .width(<span class="hljs-string"><span class="hljs-string">'67%'</span></span>) 
      .height(<span class="hljs-string"><span class="hljs-string">'4%'</span></span>) 
    <span class="hljs-comment"><span class="hljs-comment">// ... </span></span>
    Text(<span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.isScan ? <span class="hljs-keyword"><span class="hljs-keyword">this</span></span>.onReceiveEventData : <span class="hljs-string"><span class="hljs-string">'蓝牙未开启扫描'</span></span>) 
      .textAlign(TextAlign.Center) 
      .fontSize(<span class="hljs-number"><span class="hljs-number">12</span></span>) 
      .border({ width: <span class="hljs-number"><span class="hljs-number">1</span></span> }) 
      .padding(<span class="hljs-number"><span class="hljs-number">10</span></span>) 
      .margin(<span class="hljs-number"><span class="hljs-number">10</span></span>) 
      .width(<span class="hljs-string"><span class="hljs-string">'80%'</span></span>) 
      .height(<span class="hljs-number"><span class="hljs-number">200</span></span>) 
  } 
  .width(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>) 
} 
.height(<span class="hljs-string"><span class="hljs-string">'100%'</span></span>) 

} }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

经典蓝牙扫描:connection.startBluetoothDiscovery。

import { BusinessError } from ‘@kit.BasicServicesKit’;
import connection from ‘@ohos.bluetooth.connection’;

@Entry @Component struct Index { @State onReceiveEventData: string = ‘’ @State isScan: boolean = false // …

build() { Row() { Column() { // 蓝牙扫描 Button(“startBluetoothDiscovery”) .onClick(() => { this.isScan = !this.isScan let onReceiveEvent = (data: Array<string>) => { console.log(‘data length’ + JSON.stringify(data)); let dataString = JSON.stringify(data) this.onReceiveEventData = dataString } try { connection.on(‘bluetoothDeviceFind’, onReceiveEvent); connection.startBluetoothDiscovery(); } catch (err) { console.error(‘errCode: ’ + (err as BusinessError).code + ‘, errMessage: ’ + (err as BusinessError).message); } }) .type(ButtonType.Capsule) .margin({ top: 4 }) .backgroundColor(’#ff1198ee’) .width(‘67%’) .height(‘4%’) Text(this.isScan ? this.onReceiveEventData : ‘蓝牙未开启扫描’) .textAlign(TextAlign.Center) .fontSize(12) .border({ width: 1 }) .padding(10) .margin(10) .width(‘80%’) .height(200) } .width(‘100%’) } .height(‘100%’) } }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

场景三:蓝牙模块能力展示

效果图

image10.png

方案:

相关接口能力:

⦁    开启蓝牙:access.enableBluetooth。

⦁    关闭蓝牙:access.disableBluetooth。

⦁    获取蓝牙配对列表:connection.getPairedDevices。

⦁    获取蓝牙配对状态:connection.getPairState。

⦁    订阅蓝牙设备发现上报事件:connection.on(‘bluetoothDeviceFind’)。

⦁    取消订阅蓝牙设备发现上报事件:connection.off(‘bluetoothDeviceFind’)。

⦁    开启蓝牙扫描,可以发现远端设备:connection.startBluetoothDiscovery。

⦁    关闭蓝牙扫描:connection.stopBluetoothDiscovery。

⦁    发起蓝牙配对:connection.pairDevice。

⦁    创建一个服务端监听Socket:socket.sppListen。

相关接口参考文档:@ohos.bluetooth.access (蓝牙access模块)@ohos.bluetooth.connection (蓝牙connection模块)@ohos.bluetooth.socket (蓝牙socket模块)

核心代码

GridItem(){
Button(‘打开权限’).onClick(() => {
hilog.info(0x00000, TAG, ‘打开权限’);
this.requestPermissionsFromUser();
})
}
.columnStart(0)
.columnEnd(1)
.rowStart(0)
.rowEnd(0)

GridItem() { Button(‘蓝牙-开启’).onClick(() => { hilog.info(0x00000, TAG, ‘蓝牙-开启’); try { access.enableBluetooth(); } catch (err) { hilog.info(0x00000, TAG, 'errCode: ’ + (err as BusinessError).code + ', errMessage: ’ + (err as BusinessError).message); } }) }

GridItem() { Button(‘蓝牙-关闭’).onClick(() => { hilog.info(0x00000, TAG, ‘蓝牙-关闭’); try { access.disableBluetooth(); } catch (err) { hilog.info(0x00000, TAG, 'errCode: ’ + (err as BusinessError).code + ', errMessage: ’ + (err as BusinessError).message); } }) }

GridItem() { Button(‘获取蓝牙配对列表&状态’).onClick(() => { hilog.info(0x00000, TAG, ‘获取蓝牙配对列表’); try { let result: Array<string> = connection.getPairedDevices(); let index = 1; result.forEach(s => { let state = connection.getPairState(s) hilog.info(0x00000, TAG, ‘第%{public}s台设备,id-> %{public}s,状态为->%{public}s’, index++, s, bluetoothBondStateMap.get(state)); }) } catch (err) { hilog.info(0x00000, TAG, 'errCode: ’ + (err as BusinessError).code + ', errMessage: ’ + (err as BusinessError).message); } }) } .columnStart(0) .columnEnd(1) .rowStart(1) .rowEnd(1)

GridItem() { Button(‘订阅蓝牙设备发现上报事件’).onClick(() => { hilog.info(0x00000, TAG, ‘订阅蓝牙设备发现上报事件。’); try { connection.on(‘bluetoothDeviceFind’, onReceiveEvent); } catch (err) { hilog.info(0x00000, TAG, 'errCode: ’ + (err as BusinessError).code + ', errMessage: ’ + (err as BusinessError).message); } }) } .columnStart(0) .columnEnd(1) .rowStart(2) .rowEnd(2) GridItem() { Button(‘取消订阅设备发现上报事件’).onClick(() => { hilog.info(0x00000, TAG, ‘取消订阅设备发现上报事件’); try { hilog.info(0x00000, TAG, ‘共发现了设备数量为-1#’ + deviceSet.size); connection.off(‘bluetoothDeviceFind’, onReceiveEvent); index = 1;

} <span class="hljs-keyword"><span class="hljs-keyword">catch</span></span> (err) { 
  hilog.info(<span class="hljs-number"><span class="hljs-number">0x00000</span></span>, TAG, <span class="hljs-string"><span class="hljs-string">'errCode: '</span></span> + (err as BusinessError).code + <span class="hljs-string"><span class="hljs-string">', errMessage: '</span></span> + (err as BusinessError).message); 
} 

}) } .columnStart(0) .columnEnd(1) .rowStart(3) .rowEnd(3)

GridItem() { Button(‘蓝牙-开启扫描’).onClick(() => { hilog.info(0x00000, TAG, ‘蓝牙-开启扫描’); try { connection.startBluetoothDiscovery() } catch (err) { hilog.info(0x00000, TAG, 'errCode: ’ + (err as BusinessError).code + ', errMessage: ’ + (err as BusinessError).message); } }) }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

11 回复
demo连接在哪里

您好,当前技术文章配套的demo工程正在外发中,后续会发布至gitee上,敬请关注!

问下预计什么时间段上传

希望HarmonyOS能加强与其他品牌设备的兼容性,让更多人受益。

你好,近两周内会陆续上传,上传后我这边会第一时间同步回复您的!

前排 等待发布
当前鸿蒙蓝牙ble模块 支持车机交互嘛 蓝牙扫描得到的deviceId与车机蓝牙mac地址不一致 怎么解决
client端向低功耗蓝牙设备写入数据是用的writeDescriptorValue方法吧,我是用这个方法的时候,需要传入BLEDescriptor,这个对象里面有个descriptorUuid字段是必填项,这个descriptorUuid我从哪里获取,目前调用这个接口是报401错误
你好,请问一下我已经配置了系统功能,
{
"devices": {
"general": [
"phone",
"tablet"
]
},
"development": {
"addedSysCaps": [
"SystemCapability.Communication.Bluetooth.Core"
]
}
}

但是每次运行还是给我

 'connection' can't support crossplatform application.

有大佬知道为啥么?

插眼,等demo

HarmonyOS(鸿蒙)Next版本若支持基于短距离通信的BLE(蓝牙低功耗)扫描功能,通常需要在你的应用或设备中集成相应的蓝牙API。确保你的鸿蒙应用具有蓝牙权限,并在代码中正确调用蓝牙扫描API。检查API文档,了解如何启动扫描、处理扫描结果及停止扫描。同时,确认设备硬件支持BLE功能,并且操作系统版本与API兼容。如果问题依旧没法解决请加我微信,我的微信是itying888。

回到顶部