tsx81429 发表于 2024-8-4 00:20:42

鸿蒙Harmony开辟案例教程:如何举行蓝牙设备发现、配对、取消配对功能

如何举行蓝牙毗连

场景说明

蓝牙技能是一种无线数据和语音通信开放的举世规范,它是基于低本钱的近距离无线毗连,为固定和移动设备建立通信环境的一种特殊的毗连。本示例通过@ohos.bluetoothManager接口实现蓝牙设备发现、配对、取消配对功能。
效果呈现

本示例终极效果如下:
发现设备毗连设备断开毗连 https://img-blog.csdnimg.cn/img_convert/d9056bc6a6af671f19af2a351483d6f8.png
https://img-blog.csdnimg.cn/img_convert/a37391d5a527e0ee87bd6d8d5d154392.png
https://img-blog.csdnimg.cn/img_convert/aa5e93d4560c25e049006a87b036bb01.png
 点击领取→纯血鸿蒙Next全套最新学习资料
运行环境

本例基于以下环境开辟,开辟者也可以基于其他适配的版本举行开辟。


[*]IDE:DevEco Studio 3.1.1 Release
[*]SDK:Ohos_sdk_full 4.0.8.5(API Version 10 Beta1)
实现思路

本文涉及到蓝牙的设备发现、配对、取消配对三个功能特性,实现思路如下:


[*]启动和关闭蓝牙:在Index页面中通过Toggle组件的onChange函数控制蓝牙的开关,开关打开的环境下实行initBluetooth函数,关闭的环境下实行bluetooth.disableBluetooth()方法来断开蓝牙;
[*]验证蓝牙是否处于毗连状态:蓝牙打开的时候通过bluetooth.on('stateChange')方法监听蓝牙毗连状态改变变乱,如确认已打开,实行foundDevices()函数来查找设备接口,确认已关闭则实行bluetooth.stopBluetoothDiscovery()方法制止查询接口。
[*]发现设备:在foundDevices()函数中通过bluetooth.on('bluetoothDeviceFind')方法监听设备发现变乱,通过bluetooth.getPairedDevices()方法更新已配对蓝牙地址,然后通过bluetooth.startBluetoothDiscovery()方法开启蓝牙扫描发现远端设备,并且通过bluetooth.setBluetoothScanMode()方法来被远端设备发现。
[*]蓝牙配对:通过bluetooth.on('pinRequired')方法监听远端蓝牙设备的配对请求变乱,点击配对实行bluetooth.setDevicePairingConfirmation(this.data.deviceId, true)方法,点击取消实行bluetooth.setDevicePairingConfirmation(this.data.deviceId, false)方法。
[*]取消配对:使用bluetooth.cancelPairedDevice()断开指定的远端设备毗连。
开辟步调


[*] 申请蓝牙权限。 使用蓝牙需要先申请对应的权限,在module.json5文件中添加以下配置:
"requestPermissions": [
      {
      //允许应用查看蓝牙的配置
      "name": "ohos.permission.USE_BLUETOOTH",
      "reason": "$string:grant_use_bluetooth",
      "usedScene": {
          "abilities": [
            "MainAbility"
          ],
          "when": "inuse"
      }
      },
      {
      //允许应用配置本地蓝牙,查找远端设备且与之配对连接
      "name": "ohos.permission.DISCOVER_BLUETOOTH",
      "reason": "$string:grant_discovery_bluetooth",
      "usedScene": {
          "abilities": [
            "MainAbility"
          ],
          "when": "inuse"
      }
      },
      {
      //允许应用获取设备位置信息
      "name": "ohos.permission.LOCATION",
      "reason": "$string:grant_location",
      "usedScene": {
          "abilities": [
            "MainAbility"
          ],
          "when": "inuse"
      }
      },
      {
      //允许应用获取设备模糊位置信息
      "name": "ohos.permission.APPROXIMATELY_LOCATION",
      "reason": "$string:grant_location",
      "usedScene": {
          "abilities": [
            "MainAbility"
          ],
          "when": "inuse"
      }
      },
      {
      //允许应用配对蓝牙设备,并对设备的电话簿或消息进行访问
      "name": "ohos.permission.MANAGE_BLUETOOTH",
      "reason": "$string:grant_manage_bluetooth",
      "usedScene": {
          "abilities": [
            "MainAbility"
          ],
          "when": "inuse"
      }
      }
    ]
[*] 构建UI框架,团体的UI框架分为TitleBar(页面名称),PinDialog(配对蓝牙弹框),index(主页面)三个部分。
//Common/TitleBar.ets
@Component
export struct TitleBar {
private handlerClickButton: () => void

build() {
    Row() {
      Image($r('app.media.ic_back'))
      .width(40)
      .height(30)
      .onClick(() => {
          this.handlerClickButton()
      })
      Text($r('app.string.bluetooth'))
      .fontSize(30)
      .width(150)
      .height(50)
      .margin({ left: 15 })
      .fontColor('#ffa2a3a4')
    }
    .width('100%')
    .height(60)
    .padding({ left: 20, top: 10 })
    .backgroundColor('#ff2d30cb')
    .constraintSize({ minHeight: 50 })
}
}

//Common/PinDalog.ets
...
aboutToAppear() {
    this.titleText = `"${this.data.deviceId}"要与您配对。请确认此配对码已在"${this.data.deviceId}"上直接显示,且不是手动输入的。`
    this.pinCode = JSON.stringify(this.data.pinCode)
}
build() {
    //配对弹框描述文字
    Column({ space: 10 }) {
      Text($r('app.string.match_request'))
      .fontSize(30)
      .alignSelf(ItemAlign.Start)
      Text(this.titleText)
      .alignSelf(ItemAlign.Start)
      .margin({ top: 20 })
      .fontSize(21)
      Text(this.pinCode)
      .fontSize(40)
      .fontWeight(FontWeight.Bold)
      .margin({ top: 20 })
      Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center }) {
      Checkbox({ name: 'checkbox' })
          .select(false)
          .selectedColor('#ff3d6fb8')
          .key('checkBox')
      Text($r('app.string.grant_permission'))
          .fontSize(15)
          .margin({ left: 3, top: 6 })
      }
      .alignSelf(ItemAlign.Start)
      .width('95%')
      .margin({ top: 5 })

      Row() {
      //配对选择UI,取消or配对
      this.choiceText($r('app.string.cancel'), () => {
          bluetooth.setDevicePairingConfirmation(this.data.deviceId, false)
          logger.info(TAG, `setDevicePairingConfirmation = ${bluetooth.setDevicePairingConfirmation(this.data.deviceId, false)}`)
          this.controller.close()
      })

      Divider()
          .vertical(true)
          .height(32)

      this.choiceText($r('app.string.match'), () => {
          bluetooth.setDevicePairingConfirmation(this.data.deviceId, true)
          logger.info(TAG, `setDevicePairingConfirmation = ${bluetooth.setDevicePairingConfirmation(this.data.deviceId, true)}`)
          this.controller.close()
      })
      }
      .margin({ top: 20 })
    }
    .width('100%')
    .padding(15)
}
...

//pages/index.ets
@Entry
@Component
struct Index {
build() {
    Column() {
      TitleBar({ handlerClickButton: this.handlerClickButton })
      Scroll() {
      Column() {
          Row() {
            //蓝牙开关
            Column() {
            Text($r('app.string.bluetooth'))
                .fontSize(30)
                .margin({ top: 20 })
                .alignSelf(ItemAlign.Start)
            if (true === this.isOn) {
                Text($r('app.string.discovery'))
                  .fontSize(20)
                  .alignSelf(ItemAlign.Start)
            }
            }

            Blank()

            Column() {
            Toggle({ type: ToggleType.Switch, isOn: this.isOn })
                .selectedColor('#ff2982ea')
                .onChange((isOn: boolean) => {
                  if (isOn) {
                  this.isOn = true
                  this.initBluetooth()
                  } else {
                  this.isOn = false
                  bluetooth.disableBluetooth()
                  this.deviceList = []
                  this.discoveryList = []
                  }
                })
            }
            .id('toggleBtn')
          }
          .width('90%')

          if (this.isOn) {
            Divider()
            .vertical(false)
            .strokeWidth(10)
            .color('#ffece7e7')
            .lineCap(LineCapStyle.Butt)
            .margin('1%')
            //已配对的设备
            Text($r('app.string.paired_device'))
            .fontSize(25)
            .fontColor('#ff565555')
            .margin({ left: '5%' })
            .alignSelf(ItemAlign.Start)

            ForEach(this.deviceList, (item, index) => {
            Row() {
                Text(item)
                  .fontSize(20)
            }
            .alignSelf(ItemAlign.Start)
            .width('100%')
            .height(50)
            .margin({ left: '5%', top: '1%' })
            .id(`pairedDevice${index}`)
            .onClick(() => {
                AlertDialog.show({
                  //取消配对
                  title: $r('app.string.disconnect'),
                  message: '此操作将会断开您与以下设备的连接:' + item,
                  primaryButton: {
                  value: $r('app.string.cancel'),
                  action: () => {
                  }
                  },
                  //确认取消
                  secondaryButton: {
                  value: $r('app.string.confirm'),
                  action: () => {
                      try {
                        bluetooth.cancelPairedDevice(item);
                        this.deviceList = bluetooth.getPairedDevices()
                        this.discoveryList = []
                        bluetooth.startBluetoothDiscovery()
                      } catch (err) {
                        console.error("errCode:" + err.code + ",errMessage:" + err.message);
                      }
                  }
                  }
                })
            })
            })

            Divider()
            .vertical(false)
            .strokeWidth(10)
            .color('#ffece7e7')
            .lineCap(LineCapStyle.Butt)
            .margin('1%')

            Text($r('app.string.available_device'))
            .fontSize(25)
            .fontColor('#ff565555')
            .margin({ left: '5%', bottom: '2%' })
            .alignSelf(ItemAlign.Start)
            //可用设备列表
            ForEach(this.discoveryList, (item) => {
            Row() {
                Text(item)
                  .fontSize(20)
            }
            .alignSelf(ItemAlign.Start)
            .width('100%')
            .height(50)
            .margin({ left: '5%', top: '1%' })
            //进行配对操作点击
            .onClick(() => {
                logger.info(TAG, `start bluetooth.pairDevice,item = ${item}`)
                let pairStatus = bluetooth.pairDevice(item)
                logger.info(TAG, `pairStatus = ${pairStatus}`)
            })

            Divider()
                .vertical(false)
                .color('#ffece7e7')
                .lineCap(LineCapStyle.Butt)
                .margin('1%')
            })
          }
      }
      }
      .constraintSize({ maxHeight: '85%' })
    }
}
}
[*] 蓝牙开关打开关闭利用,需要打开蓝牙开关才能举行后续利用:
initBluetooth() {
    bluetooth.on('stateChange', (data) => {
      logger.info(TAG, `enter on stateChange`)
      //判断蓝牙开关状态
      if (data === bluetooth.BluetoothState.STATE_ON) {
      logger.info(TAG, `enter BluetoothState.STATE_ON`)
      //蓝牙打开后的相关操作
      this.foundDevices()
      }
      if (data === bluetooth.BluetoothState.STATE_OFF) {
      logger.info(TAG, `enter BluetoothState.STATE_OFF`)
      bluetooth.off('bluetoothDeviceFind', (data) => {
          logger.info(TAG, `offBluetoothDeviceFindData = ${JSON.stringify(data)}`)
      })
      //关闭
      bluetooth.stopBluetoothDiscovery()
      this.discoveryList = []
      }
      logger.info(TAG, `BluetoothState = ${JSON.stringify(data)}`)
    })
    //开启蓝牙
    bluetooth.enableBluetooth()
}
[*] 设置蓝牙扫描模式并开启扫描去发现设备,并订阅蓝牙设备发现上报时间获取设备列表
foundDevices() {
    //订阅蓝牙设备发现上报事件
    bluetooth.on('bluetoothDeviceFind', (data) => {
      logger.info(TAG, `enter on bluetoothDeviceFind`)
      if (data !== null && data.length > 0) {
      if (this.discoveryList.indexOf(data) === -1 && this.deviceList.indexOf(data) === -1) {
          this.discoveryList.push(data)
      }
      logger.info(TAG, `discoveryList = ${JSON.stringify(this.discoveryList)}`)
      }
      let list = bluetooth.getPairedDevices()
      if (list !== null && list.length > 0) {
      this.deviceList = list
      logger.info(TAG, `deviceList =${JSON.stringify(this.deviceList)}`)
      }
    })
    //开启蓝牙扫描,可以发现远端设备
    bluetooth.startBluetoothDiscovery()
    //设置蓝牙扫描模式,可以被远端设备发现
    bluetooth.setBluetoothScanMode(bluetooth.ScanMode.SCAN_MODE_CONNECTABLE_GENERAL_DISCOVERABLE, TIME)
}
[*] 设置蓝牙扫描模式并开启扫描去发现设备,并订阅蓝牙设备发现上报时间获取设备列表
//配对确定和取消代码在PinDialog.ets文件中
//setDevicePairingConfirmation(device: string, accept: boolean): void
//device        string        表示远端设备地址,例如:"XX:XX:XX:XX:XX:XX
//accept        boolean        接受配对请求设置为true,否则设置为false

//订阅蓝牙配对状态改变事件,根据蓝牙状态更新设备列表
bluetooth.on('bondStateChange', (data) => {
    logger.info(TAG, `enter bondStateChange`)
    logger.info(TAG, `data = ${JSON.stringify(data)}`)
    if (data.state === bluetooth.BondState.BOND_STATE_BONDED) {
      logger.info(TAG, `BOND_STATE_BONDED`)
      let index = this.discoveryList.indexOf(data.deviceId)
      this.discoveryList.splice(index, 1)
      this.deviceList = bluetooth.getPairedDevices()
    }
    if (data.state === bluetooth.BondState.BOND_STATE_INVALID) {
      logger.info(TAG, `BOND_STATE_INVALID`)
      this.deviceList = bluetooth.getPairedDevices()
    }
    logger.info(TAG, `bondStateChange,data = ${JSON.stringify(data)}`)
})

最后

有很多小伙伴不知道学习哪些鸿蒙开辟技能?不知道需要重点掌握哪些鸿蒙应用开辟知识点?但是又不知道从那里下手,而且学习时频仍踩坑,终极浪费大量时间。以是本人整理了一些比较符合的鸿蒙(HarmonyOS NEXT)学习路径和一些资料的整理供小伙伴学习
点击领取→纯血鸿蒙Next全套最新学习资料(安全链接,放心点击)
希望这一份鸿蒙学习资料能够给大家带来资助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
      一、鸿蒙(HarmonyOS NEXT)最新学习路线
    https://img-blog.csdnimg.cn/direct/9e1bd404e54e495db25a2e65f9b1baf3.png​
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布条记整理收纳的一套体系性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开辟入门讲授视频,内容包含:(ArkTS、ArkUI开辟组件、Stage模型、多端部署、分布式应用开辟、音频、视频、WebGL、OpenHarmony多媒体技能、Napi组件、OpenHarmony内核、Harmony南向开辟、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)…等技能知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
二、HarmonyOS Next 最新全套视频教程
https://img-blog.csdnimg.cn/direct/058c674163cf4c8c9e46e6a44f0fc9e6.png​

三、《鸿蒙 (OpenHarmony)开辟底子到实战手册》
OpenHarmony北向、南向开辟环境搭建
https://img-blog.csdnimg.cn/direct/6ed0fb8a59394d4bb5fe7e3a1e6ad706.png​
《鸿蒙开辟底子》


[*]ArkTS语言
[*]安装DevEco Studio
[*]运用你的第一个ArkTS应用
[*]ArkUI声明式UI开辟
[*].……https://img-blog.csdnimg.cn/direct/ab30eba2666344d59db1e49e17d6d905.png​
《鸿蒙开辟进阶》


[*]Stage模型入门
[*]网络管理
[*]数据管理
[*]电话服务
[*]分布式应用开辟
[*]通知与窗口管理
[*]多媒体技能
[*]安全技能
[*]任务管理
[*]WebGL
[*]国际化开辟
[*]应用测试
[*]DFX面向未来设计
[*]鸿蒙体系移植和裁剪定制
[*]……
https://img-blog.csdnimg.cn/direct/d8b0d340b8344b3c97e554552db3d6b5.png​
《鸿蒙进阶实战》


[*]ArkTS实践
[*]UIAbility应用
[*]网络案例
[*]……
https://img-blog.csdnimg.cn/direct/dfcd46aebaad4913891a46e2e5389104.png​
四、大厂口试必问口试题
https://img-blog.csdnimg.cn/direct/6a8d1476de8b4606adef673206366f64.png​
五、鸿蒙南向开辟技能
https://img-blog.csdnimg.cn/direct/21bf9d9da77840fc9748768d594d232f.png​
六、鸿蒙APP开辟必备
https://img-blog.csdnimg.cn/direct/339886a24c544fe4a2291e51c0250a77.png​
七、鸿蒙生态应用开辟白皮书V2.0PDF
https://img-blog.csdnimg.cn/direct/8939d548a4e14cf79861d11af83ee11b.png​

完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年步伐员来说是一个挑衅,也是一个机会。只有积极应对变化,不停学习和提拔自己,他们才能在这个变革的时代中立于不败之地。 
                        https://img-blog.csdnimg.cn/direct/cf3c98e0497c4b6ebc314bb5484b802c.png


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 鸿蒙Harmony开辟案例教程:如何举行蓝牙设备发现、配对、取消配对功能