HarmonyOS中蓝牙扫描、连接相关示例

76 阅读3分钟

1、封装蓝牙相关管理类

import { Permissions } from '@kit.AbilityKit'
import { permissionManager } from './PermissionManager'
import { promptAction } from '@kit.ArkUI'

/**
 * 蓝牙管理类
 */
export class BluetoothManager {

  // 检查并开启蓝牙权限
  static async checkAndOpenBluetooth() {
    let result = false
    const permission: Permissions[] = ["ohos.permission.ACCESS_BLUETOOTH", "ohos.permission.DISCOVER_BLUETOOTH"]
    // 检查蓝牙是否打开
    if (!permissionManager.checkPermissions(permission)) {
      try {
        result = await permissionManager.requestPermissions(permission)
      } catch (e) {
        promptAction.showDialog({
          title: '温馨提示',
          message: '蓝牙连接需要打开蓝牙权限',
          alignment: DialogAlignment.Center,
          buttons: [
            { text: '取消', color: '#89939C' },
            { text: '立即开启', color: '#0A59F7' }
          ]
        }).then((result) => {
          if (result.index === 1) {
            permissionManager.openPermissionSettingsPage()
          }
        })
      }
    } else {
      result = true
    }

    return result
  }

}

2、调用侧页面

import { BluetoothManager } from '@xfh/helper'
import { a2dp, access, ble } from '@kit.ConnectivityKit'
import { BusinessError } from '@kit.BasicServicesKit'
import { promptAction } from '@kit.ArkUI'
import connection from '@ohos.bluetooth.connection'

export interface DevicesInfo {
  name: string;
  mac: string;
}

@Entry
@Component
struct BluetoothPage {
  @State devicesMac: Array<string> = [] // 配对列表
  @State remoteDeviceName: Array<string> = [] // 配对列表名称
  @State nearbyDevicesMac: Array<string> = [] // 搜索到的蓝牙设备
  @State nearbyDevicesName: Array<string> = [] // 搜索到的蓝牙设备名称
  @State nearbyDevicesInfo: DevicesInfo[] = [] // 搜索到的未配对的蓝牙设备信息
  @State bondState: string = '' // 蓝牙配对状态
  @State devicesIndex: number = 0 // 配对列表索引

  build() {
    Navigation() {
      Scroll() {
        Column({ space: 10 }) {
          Button('检查并开启蓝牙权限')
            .onClick(async () => {
              let result = await BluetoothManager.checkAndOpenBluetooth()
              if (result) {
                promptAction.showToast({ message: '蓝牙权限已打开' })
              } else {
                promptAction.showToast({ message: '蓝牙权限未打开' })
              }
            })

          Row({ space: 30 }) {
            Button('打开蓝牙')
              .onClick(() => {
                try {
                  access.enableBluetooth()
                } catch (err) {
                  console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                  (err as BusinessError).message)
                  if (access.getState() === 2) {
                    promptAction.showToast({ message: '蓝牙已打开' })
                  } else {
                    promptAction.showToast({ message: '蓝牙打开失败' })
                  }
                }
              })

            Button('关闭蓝牙')
              .onClick(() => {
                try {
                  access.disableBluetooth()
                } catch (err) {
                  console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                  (err as BusinessError).message)
                }
              })
          }

          Button('获取蓝牙配对列表')
            .onClick(() => {
              try {
                this.devicesMac = connection.getPairedDevices()
                if (this.devicesMac.length > 0) {
                  AlertDialog.show({ message: JSON.stringify(this.devicesMac, null, 2) })
                } else {
                  promptAction.showToast({ message: '没有蓝牙配对列表' })
                }
              } catch (err) {
                console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                (err as BusinessError).message);
              }
            })

          Button('获取已配对的蓝牙设名称')
            .onClick(() => {
              for (const devices of this.devicesMac) {
                try {
                  let remoteDeviceName: string = connection.getRemoteDeviceName(devices)
                  // 判断是否为空和已经存在
                  if (remoteDeviceName !== '' &&
                    !this.remoteDeviceName.includes(remoteDeviceName)) {
                    this.remoteDeviceName.push(remoteDeviceName)
                  }
                } catch (e) {
                  console.error('errCode: ' + (e as BusinessError).code + ', errMessage: ' +
                  (e as BusinessError).message)
                }
              }
              // 显示
              if (this.remoteDeviceName.length > 0) {
                AlertDialog.show({ message: JSON.stringify(this.remoteDeviceName, null, 2) })
              } else {
                promptAction.showToast({ message: '没有对端蓝牙设备的名称' })
              }
            })

          Button('搜索(扫描)附近蓝牙设备名称')
            .onClick(() => {
              this.nearbyDevicesInfo = [] // 清空数组
              // 停止上一次的扫描
              try {
                connection.stopBluetoothDiscovery()
              } catch (err) {
                console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                (err as BusinessError).message)
              }
              try {
                connection.on('bluetoothDeviceFind', (data: Array<string>) => {
                  if (data.length > 0) {
                    for (const devicesMac of data) {
                      try {
                        let nearbyDevicesName: string = connection.getRemoteDeviceName(devicesMac)
                        // 把数据以键值对形式添加到数组中
                        if (nearbyDevicesName !== '' && !this.remoteDeviceName.includes(nearbyDevicesName)) {
                          // 判断数值中是否已经存在key为nearbyDevicesName的数据
                          if (!this.nearbyDevicesInfo.some(item => item.name === nearbyDevicesName)) {
                            this.nearbyDevicesInfo.push({
                              name: nearbyDevicesName,
                              mac: devicesMac
                            } as DevicesInfo)
                          }
                        }
                      } catch (e) {
                        console.error('errCode: ' + (e as BusinessError).code + ', errMessage: ' +
                        (e as BusinessError).message)
                      }
                    }
                  }
                })
                connection.startBluetoothDiscovery()
              } catch (err) {
                console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                (err as BusinessError).message);
              }
            })

          Button('连接XFH')
            .enabled(false)
            .onClick(() => {
              // 在nearbyDevicesInfo中找到XFH的地址
              for (const device of this.nearbyDevicesInfo) {
                if (device.name === 'XFH') {
                  try {
                    // 实际的地址可由扫描流程获取
                    connection.pairDevice(device.mac)
                  } catch (err) {
                    console.error('配对失败:errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                    (err as BusinessError).message)
                    promptAction.showToast({ message: '配对失败' })
                  }
                }
              }
            })

          Button('搜索(扫描)附近蓝牙设备')
            .enabled(false)
            .onClick(() => {
              try {
                connection.on('bluetoothDeviceFind', (data: Array<string>) => {
                  if (data.length > 0) {
                    for (const element of data) {
                      if (!this.nearbyDevicesMac.includes(element)) {
                        this.nearbyDevicesMac.push(element)
                      }
                    }
                  }
                })
                connection.startBluetoothDiscovery()
              } catch (err) {
                console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                (err as BusinessError).message);
              }
              AlertDialog.show({ message: JSON.stringify(this.nearbyDevicesMac, null, 2) })
            })

          Button('获取附近蓝牙设备名称')
            .enabled(false)
            .onClick(() => {
              for (const devices of this.nearbyDevicesMac) {
                try {
                  let nearbyDevicesName: string = connection.getRemoteDeviceName(devices)
                  // 判断是否为空和已经存在
                  if (nearbyDevicesName !== '' &&
                    !this.nearbyDevicesName.includes(nearbyDevicesName)) {
                    this.nearbyDevicesName.push(nearbyDevicesName)
                  }
                } catch (e) {
                  console.error('errCode: ' + (e as BusinessError).code + ', errMessage: ' +
                  (e as BusinessError).message)
                }
              }
              if (this.nearbyDevicesName.length > 0) {
                AlertDialog.show({ message: JSON.stringify(this.nearbyDevicesName, null, 2) })
              } else {
                promptAction.showToast({ message: '没有对端蓝牙设备的名称' })
              }
            })


          Column() {
            Text('点击发起配对:' + this.nearbyDevicesInfo.length)
            List({ space: 5 }) {
              ForEach(this.nearbyDevicesInfo, (devices: DevicesInfo, index) => {
                ListItem() {
                  Row() {
                    Text(devices.name)
                    if (this.devicesIndex === index && this.bondState !== '已配对') {
                      Text(this.bondState)
                    }
                  }.width('100%').justifyContent(FlexAlign.SpaceBetween).backgroundColor('#fff').padding(5)
                }.onClick(async () => {
                  this.devicesIndex = index
                  // 订阅配对状态
                  try {
                    connection.on('bondStateChange', (data: connection.BondStateParam) => {
                      switch (data.state) {
                        case 0:
                          this.bondState = '无效的配对'
                          break
                        case 1:
                          this.bondState = '配对中...'
                          break
                        case 2:
                          this.bondState = '已配对'
                        // 配对成功的从数组1中删除 在数组2中添加
                          this.nearbyDevicesInfo =
                            this.nearbyDevicesInfo.filter(element => element.name !== devices.name)
                          this.devicesMac.push(devices.mac)

                          promptAction.showToast({ message: `与${devices.name}配对成功` })

                          break
                        default:
                          this.bondState = '配对失败'
                      }
                    })
                  } catch (err) {
                    console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                    (err as BusinessError).message);
                  }

                  // promptAction.showToast({ message: devices.name + '的Mac:' + devices.mac })

                  try {
                    // 实际的地址可由扫描流程获取
                    await connection.pairDevice(devices.mac)
                    // promptAction.showToast({ message: `result: ${result}` })
                  } catch (err) {
                    console.error('配对失败:errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                    (err as BusinessError).message)
                    promptAction.showToast({ message: '配对失败' })
                  }
                })
              }, (item: DevicesInfo) => item.mac)
            }.width('100%').height('100%')
          }.width('100%').padding(10).height(180).backgroundColor('#ccc')

          Button('关闭搜索(扫描)附近蓝牙设备')
            .onClick(() => {
              try {
                connection.stopBluetoothDiscovery()
              } catch (err) {
                console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                (err as BusinessError).message);
                if (access.getState() === 0) {
                  promptAction.showToast({ message: '蓝牙搜索已关闭' })
                } else {
                  promptAction.showToast({ message: '蓝牙搜索关闭失败' })
                }
              }
            })

          Button('查看蓝牙是否连接')
            .onClick(() => {
              try {
                let result: Array<string> = ble.getConnectedBLEDevices()
                if (result.length > 0) {
                  AlertDialog.show({ message: JSON.stringify(result, null, 2) })
                } else {
                  promptAction.showToast({ message: '没有蓝牙连接' })
                }
              } catch (err) {
                console.error('errCode: ' + (err as BusinessError).code + ', errMessage: ' +
                (err as BusinessError).message)
              }
            })

          Button('获取已连接设备列表')
            .onClick(() => {
              try {
                let a2dpSrc = a2dp.createA2dpSrcProfile()
                let retArray = a2dpSrc.getConnectedDevices()
                AlertDialog.show({ message: JSON.stringify(retArray, null, 2) })
              } catch (err) {
                console.error("errCode:" + (err as BusinessError).code + ",errMessage:" +
                (err as BusinessError).message);
              }
            })
        }
        .constraintSize({ minHeight: '100%' })
      }
      .width('100%')
      .height('100%')
    }
    .title('蓝牙控制测试')
    .titleMode(NavigationTitleMode.Mini)
  }
}

3、部分效果图

mmexport1756887949145.jpg