【鸿蒙实战开发】基于短距离通信的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(`catch err->${JSON.stringify(err)}`); 
  } 
}

配置文件

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" 
    } 
  }, 
]

场景二: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: 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%') 
  } 
}

经典蓝牙扫描: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%') 
  } 
}

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

效果图

方案:

相关接口能力:

⦁    开启蓝牙:access.enableBluetooth。

⦁    关闭蓝牙:access.disableBluetooth。

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

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

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

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

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

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

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

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

核心代码

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; 

    } catch (err) { 
      hilog.info(0x00000, TAG, 'errCode: ' + (err as BusinessError).code + ', errMessage: ' + (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); 
    } 
  }) 
}

鸿蒙全栈开发全新学习指南

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以要有一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

本路线共分为四个阶段

第一阶段:鸿蒙初中级开发必备技能

在这里插入图片描述

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值