uni-app 蓝牙连接全面指南:API 流程实践解析

一. 前言

Uni-App 是一个使用 Vue.js 开发(所有)前端应用的框架,能够编译到 iOSAndroid、快应用以及各种小程序等多个平台。因此,如果你需要快速开发一款跨平台的应用,比如在 H5、小程序、iOSAndroid 等多个平台上线,那么 Uni-App 是一个不错的选择。

Uni-App 进行多平台开发的优势不言而喻,同时主要因为它拥有许多跨端的 API 兼容支持和条件编译,在各个平台可以使用同一套 API 或通过条件编译使用不同的代码。

以上说了这么多,今天我们主要学习蓝牙连接相关的 API,同时也是为了后续开发蓝牙打印功能打基础。

蓝牙功能的开发是移动应用中非常常见的一项特性,可以用于设备间的数据传输等场景。关于蓝牙连接的功能,Uni-App 提供了一系列的 API 来帮助开发者快速地实现跨平台应用开发。下面我总结了一张图,标识需要了解的蓝牙连接核心 API.

 

二. 蓝牙主要功能

Uni-App 提供的蓝牙 API 允许我们开发时主要实现以下功能:

  • 扫描并连接到蓝牙设备

  • 发现已连接设备的服务和特征值

  • 向设备发送数据

  • 接收设备发送的数据

流程图:

关于开发时进行蓝牙连接的流程,我总结了以下这张图:

三. 蓝牙核心 API 介绍

蓝牙 API 分为通用蓝牙 API 和低功耗蓝牙的 API

通用蓝牙 API

兼容性:

 

1. 初始化蓝牙模块

当开始使用蓝牙前,需要先初始化蓝牙模块,初始化蓝牙适配器成功后才可以继续使用其他的 API

uni.openBluetoothAdapter({
  success: function (res) {
    console.log('初始化蓝牙适配器成功', res)
  },
  fail: function (err) {
    console.error('初始化蓝牙适配器失败', err)
  }
})

2. 开始搜索蓝牙设备

初始化成功后,就可以通过调用 startBluetoothDevicesDiscovery 方法开始搜索附近的蓝牙设备:

注意:此操作比较耗费系统资源,请在搜索并连接到设备后调用  uni.stopBluetoothDevicesDiscovery  方法停止搜索。

uni.startBluetoothDevicesDiscovery({
  success: function (res) {
    console.log('开始搜索蓝牙设备', res)
  },
  fail: function (err) {
    console.error('开始搜索蓝牙设备失败', err)
  }
})

说明:App 端目前仅支持发现 BLE 低功耗蓝牙设备,其实我们也主要和低功耗蓝牙设备建立通信关系。一般为发送指令(开关机、蓝牙打印等),接收数据(蓝牙温度记录仪)

3. 停止搜索蓝牙设备

当不再需要继续搜索设备时,可以调用 stopBluetoothDevicesDiscovery 停止搜索:

uni.stopBluetoothDevicesDiscovery({
  success: function (res) {
    console.log('停止搜索蓝牙设备', res)
  },
  fail: function (err) {
    console.error('停止搜索蓝牙设备失败', err)
  }
})
4. 监听已发现的蓝牙设备

通过 onBluetoothDeviceFound 方法获取当前已发现的蓝牙设备列表,此方式是回调方法,只要发现了新的蓝牙设备,都会进入该回调:

uni.onBluetoothDeviceFound(function (devices) {
  console.log('new device list has founded')
  console.dir(devices)
})
5. 获取已发现的蓝牙设备列表

通过 getBluetoothDevices 方法获取在蓝牙模块生效期间所有已发现的蓝牙设备。包括已经和本机处于连接状态的设备。

uni.getBluetoothDevices({
  success: function (res) {
    console.log('已发现的蓝牙设备', res.devices)
  },
  fail: function (err) {
    console.error('获取已发现的蓝牙设备列表失败', err)
  }
})

 

6. 关闭蓝牙模块

通过调用 closeBluetoothAdapter 方法将关闭蓝牙模块,断开所有已建立的连接并释放系统资源。

调用该方法将断开所有已建立的连接并释放系统资源。一般在使用蓝牙流程完毕后,主动调用该方法,可在页面生命周期中使用。 应与  uni.openBluetoothAdapter 成对调用。

uni.closeBluetoothAdapter({
  success(res) {
    console.log(res)
  }
})

低功耗蓝牙 API

1. 连接到蓝牙设备

选择一个设备后,可以通过设备 ID 调用 createBLEConnection 方法建立与该设备的连接:

uni.createBLEConnection({
  deviceId: '目标设备ID',
  success: function (res) {
    console.log('连接蓝牙设备成功', res)
  },
  fail: function (err) {
    console.error('连接蓝牙设备失败', err)
  }
})
2. 获取蓝牙设备的服务

连接成功后,可以通过设备 ID 调用 getBLEDeviceServices 方法获取该设备提供的服务:

uni.getBLEDeviceServices({
  deviceId: '目标设备ID',
  success: function (res) {
    console.log('获取蓝牙设备服务成功', res.services)
  },
  fail: function (err) {
    console.error('获取蓝牙设备服务失败', err)
  }
})

 

3. 获取服务中的特征值

获取服务成功后,可以通过备 ID,服务 ID 调用 getBLEDeviceCharacteristics 方法获取特定服务下的特征值:

uni.getBLEDeviceCharacteristics({
  deviceId: '目标设备ID',
  serviceId: '服务ID',
  success: function (res) {
    console.log('获取蓝牙设备特征值成功', res.characteristics)
  },
  fail: function (err) {
    console.error('获取蓝牙设备特征值失败', err)
  }
})

 

4. 向蓝牙设备写入数据

确定了要使用的特征值后,可以使用 writeBLECharacteristicValue 方法向蓝牙设备写入数据:

注意:只有获取到支持读写的特征值后,才可以像蓝牙设备写入数据。

uni.writeBLECharacteristicValue({
  deviceId: '目标设备ID',
  serviceId: '服务ID',
  characteristicId: '特征值ID',
  value: new ArrayBuffer(2), // 示例数据
  success: function (res) {
    console.log('向蓝牙设备写入数据成功', res)
  },
  fail: function (err) {
    console.error('向蓝牙设备写入数据失败', err)
  }
})

说明:蓝牙打印机主要会使用该 API,将在下一文章中说明。

5. 监听来自蓝牙设备的数据

如果需要接收来自蓝牙设备的数据,可以监听 onBLECharacteristicValueChange 事件:

uni.onBLECharacteristicValueChange(function (res) {
  console.log('接收到蓝牙设备数据', res.value)
})
6. 断开蓝牙连接

通过调用 closeBLEConnection 断开与低功耗蓝牙设备的连接。

uni.closeBLEConnection({
  deviceId,
  success(res) {
    console.log(res)
  }
})

四. 使用蓝牙 API 前的准备

Uni-App 中使用蓝牙功能时,尤其是真机(AndroidiOS),需要添加蓝牙打包模块;除此之外,还需要确保在 manifest.json 文件中正确声明所需的蓝牙权限,并在运行时请求这些权限。

1. 添加蓝牙模块

2. Android 权限

处理 Android 蓝牙权限需要在 manifest.json 中声明权限,首先,打开你的 manifest.json 文件,并在 app-plus 节点下添加所需的蓝牙权限。

注意:根据不同的 Android 版本,你可能需要声明不同的权限。

基本权限

manifest.json 配置如下权限:

{
  "app-plus": {
    "distribute": {
      "android": {
        "permissions": ["android.permission.BLUETOOTH", "android.permission.BLUETOOTH_ADMIN"]
      }
    }
  }
}
高级权限(Android 12 及以上)

如果应用需要扫描附近的蓝牙设备,还需要声明 ACCESS_FINE_LOCATION 权限,从 Android 12 开始,还需要声明 BLUETOOTH_SCANBLUETOOTH_CONNECTBLUETOOTH_ADVERTISE 权限:

{
  "app-plus": {
    "distribute": {
      "android": {
        "permissions": [
          "android.permission.BLUETOOTH",
          "android.permission.BLUETOOTH_ADMIN",
          "android.permission.ACCESS_FINE_LOCATION",
          "android.permission.BLUETOOTH_SCAN",
          "android.permission.BLUETOOTH_CONNECT",
          "android.permission.BLUETOOTH_ADVERTISE"
        ]
      }
    }
  }
}

3. iOS

对于 iOS 平台,和 Android 平台类似,同样的需要 在manifest.json 文件,并在 app-plus 节点下添加所需的蓝牙权限。需要声明 NSBluetoothAlwaysUsageDescriptionNSBluetoothPeripheralUsageDescription,并在其中提供用途说明。

manifest.json 配置如下权限:

{
  "app-plus": {
    "distribute": {
      "ios": {
        "permissions": {
          "NSBluetoothAlwaysUsageDescription": "需要蓝牙权限以连接和控制外部设备",
          "NSBluetoothPeripheralUsageDescription": "需要蓝牙权限以连接和控制外部设备"
        }
      }
    }
  }
}

4. 运行时请求权限

Uni-App 中,你可以使用 uni.authorize 方法来请求运行时权限。以下示例代码,表示如何在应用启动时请求蓝牙相关权限:

export default {
  data() {
    return {}
  },
  onReady() {
    this.checkAndRequestPermissions()
  },
  methods: {
    checkAndRequestPermissions() {
      const permissions = ['scope.bluetooth', 'scope.location']

      // 检查权限
      uni.getSetting({
        success: res => {
          let authResult = true
          permissions.forEach(permission => {
            if (!res.authSetting[permission]) {
              authResult = false
              return
            }
          })

          if (!authResult) {
            // 请求权限
            this.requestPermissions()
          } else {
            // 已经有权限,可以进行蓝牙操作
            this.initBluetooth()
          }
        }
      })
    },

    requestPermissions() {
      const permissions = ['scope.bluetooth', 'scope.location']

      permissions.forEach(permission => {
        uni.authorize({
          scope: permission,
          success: () => {
            console.log(`权限 ${permission} 请求成功`)
          },
          fail: err => {
            console.error(`权限 ${permission} 请求失败`, err)
            uni.showModal({
              title: '提示',
              content: '请在设置中开启蓝牙和位置权限',
              showCancel: false
            })
          }
        })
      })
    },

    initBluetooth() {
      uni.openBluetoothAdapter({
        success: res => {
          console.log('初始化蓝牙适配器成功', res)
          // 继续进行蓝牙操作
        },
        fail: err => {
          console.error('初始化蓝牙适配器失败', err)
        }
      })
    }
  }
}

5. 处理用户拒绝权限的情况

如果用户拒绝了权限请求,可以通过 uni.showModal 方法提示用户在设置中手动开启权限。如下所示:

uni.showModal({
  title: '提示',
  content: '请在设置中开启蓝牙和位置权限',
  confirmText: '去设置',
  success: res => {
    if (res.confirm) {
      uni.openSetting({
        success: settingData => {
          console.log('用户设置结果', settingData)
        }
      })
    }
  }
})

小程序中的授权提示如下:

五. 注意事项

在使用蓝牙 API 时,请确保用户已经开启了手机的蓝牙功能和位置信息。

  1. 蓝牙 API 调用时机:蓝牙相关 API 的抵用必须在  uni.openBluetoothAdapter 调用之后使用,否则 API 会返回错误(errCode=10000)。

  2. 在用户蓝牙开关未开启或者手机不支持蓝牙功能的情况下,调用  uni.openBluetoothAdapter 会返回错误(errCode=10001),表示手机蓝牙功能不可用。

  3. 版本兼容性:部分蓝牙 API 可能因操作系统版本不同而有所差异,具体请参考官方文档。

  4. 用户提示:确保在请求蓝牙权限时提供清晰的提示信息,告知用户为什么需要这些权限。

  5. 蓝牙状态检查:在初始化蓝牙适配器之前,应检查蓝牙是否已开启。可以使用 uni.getBluetoothAdapterState 方法来检查蓝牙状态,如下代码:

uni.getBluetoothAdapterState({
  success: res => {
    if (!res.discovering && !res.available) {
      uni.showModal({
        title: '提示',
        content: '请确保蓝牙已开启',
        showCancel: false
      })
    }
  },
  fail: err => {
    console.error('检查蓝牙适配器状态失败', err)
  }
})

六. 总结

通过以上的蓝牙连接核心 API 的了解,基本可以在 Uni-App 中正确声明和请求蓝牙权限,并且和低功耗蓝牙建立连接,并成功获取蓝牙设备的服务和特征值。

文档链接

蓝牙 Bluetooth - uni-app 文档

低功耗蓝牙 BLE - uni-app 文档

小程序体验

想要体验蓝牙连接效果的同学,通过以下公众号获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端梦工厂+

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值