UniApp 对接蓝牙设备全攻略(含完整示例)

随着物联网(IoT)的快速发展,越来越多的移动应用需要与蓝牙设备进行通信,例如智能手环、蓝牙秤、蓝牙打印机、工业传感器等。在跨平台开发中,UniApp 作为一款支持一套代码多端运行的框架,天然具备对接蓝牙设备的优势。

本文将系统介绍 如何在 UniApp 中对接蓝牙设备,包括蓝牙原理、API 说明、完整示例代码、调试技巧及注意事项,帮助你快速上手蓝牙开发。


一、蓝牙开发原理简述

在开始写代码之前,我们先了解蓝牙的基本原理。

蓝牙通信主要分为两类:

  1. 经典蓝牙(BR/EDR)
  • 常用于音频传输(如耳机、音箱)
  • 速率较高
  • 一般需要配对
  • UniApp 暂时不支持经典蓝牙,主要支持 BLE
  1. 低功耗蓝牙(BLE,Bluetooth Low Energy)
  • 功耗低,数据传输速率较低
  • 常用于传感器、可穿戴设备、IoT
  • 基于 GATT(Generic Attribute Profile)通信
  • Service(服务)Characteristic(特征值) 为核心
  • 支持读取(read)、写入(write)、通知(notify)等操作

在 UniApp 中,我们主要使用 低功耗蓝牙(BLE) 相关 API。


二、UniApp 蓝牙 API 总览

UniApp 提供了多套跨端蓝牙 API,主要与微信小程序 API 一致,核心流程如下:

  1. 初始化蓝牙适配器
    uni.openBluetoothAdapter()
  2. 开始扫描设备
    uni.startBluetoothDevicesDiscovery()
  3. 监听设备发现事件
    uni.onBluetoothDeviceFound(callback)
  4. 连接设备
    uni.createBLEConnection()
  5. 获取设备服务
    uni.getBLEDeviceServices()
  6. 获取服务特征值
    uni.getBLEDeviceCharacteristics()
  7. 读写数据
  • 写入:uni.writeBLECharacteristicValue()
  • 读取:uni.readBLECharacteristicValue()
  • 监听:uni.notifyBLECharacteristicValueChange()
  1. 关闭连接
  • 断开设备:uni.closeBLEConnection()
  • 关闭蓝牙适配器:uni.closeBluetoothAdapter()

三、开发前准备

  1. 真机调试
  • 蓝牙相关 API 无法在浏览器或模拟器中运行,必须真机测试。
  • 设备需支持 BLE。
  1. 权限配置
  • 在微信小程序中,需要在 manifest.json 中勾选“蓝牙”权限。
  • Android 还需定位权限(扫描设备需要)。
  • iOS 需要在 manifest.json 配置 NSBluetoothAlwaysUsageDescription 描述。
  1. 硬件信息
  • 了解目标设备的 Service UUIDCharacteristic UUID
  • 确定是否需要加密、配对、认证等。

四、完整示例代码

<template><view class="container"><button @click="initBluetooth">初始化蓝牙</button><button @click="startDiscovery">开始扫描</button><view v-for="item in deviceList" :key="item.deviceId" @click="connectDevice(item)">{{ item.name || '未命名设备' }} - {{ item.deviceId }}</view></view>
</template><script>
export default {data() {return {deviceList: [],connectedDeviceId: '',serviceId: '',writeCharId: '',notifyCharId: ''}},methods: {// 初始化蓝牙适配器initBluetooth() {uni.openBluetoothAdapter({success: () => {console.log('蓝牙适配器初始化成功');},fail: err => {console.error('初始化失败', err);}});},// 开始扫描蓝牙设备startDiscovery() {uni.startBluetoothDevicesDiscovery({allowDuplicatesKey: false,success: () => {console.log('开始扫描设备');uni.onBluetoothDeviceFound(res => {res.devices.forEach(device => {if (device.name || device.localName) {if (!this.deviceList.some(d => d.deviceId === device.deviceId)) {this.deviceList.push(device);}}});});}});},// 连接蓝牙设备connectDevice(device) {uni.createBLEConnection({deviceId: device.deviceId,success: () => {console.log('连接成功', device.deviceId);this.connectedDeviceId = device.deviceId;this.getServices();},fail: err => {console.error('连接失败', err);}});},// 获取服务getServices() {uni.getBLEDeviceServices({deviceId: this.connectedDeviceId,success: res => {const service = res.services.find(s => s.isPrimary);if (service) {this.serviceId = service.uuid;this.getCharacteristics();}}});},// 获取特征值getCharacteristics() {uni.getBLEDeviceCharacteristics({deviceId: this.connectedDeviceId,serviceId: this.serviceId,success: res => {res.characteristics.forEach(item => {if (item.properties.write) this.writeCharId = item.uuid;if (item.properties.notify) {this.notifyCharId = item.uuid;this.enableNotify();}});}});},// 开启通知监听enableNotify() {uni.notifyBLECharacteristicValueChange({state: true,deviceId: this.connectedDeviceId,serviceId: this.serviceId,characteristicId: this.notifyCharId,success: () => {console.log('通知已开启');uni.onBLECharacteristicValueChange(res => {const value = this.ab2str(res.value);console.log('收到数据:', value);});}});},// 写入数据writeData(data) {const buffer = this.str2ab(data);uni.writeBLECharacteristicValue({deviceId: this.connectedDeviceId,serviceId: this.serviceId,characteristicId: this.writeCharId,value: buffer,success: () => {console.log('数据写入成功');}});},// 工具方法:字符串转ArrayBufferstr2ab(str) {const buf = new ArrayBuffer(str.length);const bufView = new Uint8Array(buf);for (let i = 0; i < str.length; i++) {bufView[i] = str.charCodeAt(i);}return buf;},// 工具方法:ArrayBuffer转字符串ab2str(buf) {return String.fromCharCode.apply(null, new Uint8Array(buf));}}
}
</script>

五、调试与常见问题

  1. 无法扫描到设备
  • 确保设备已开启蓝牙广播。
  • Android 需要开启定位权限。
  • iOS 需在 manifest.json 添加使用描述。
  1. 连接失败
  • 检查设备是否已被其他手机连接。
  • 检查 UUID 是否正确。
  1. 收不到数据
  • 确认 notify 特征值已开启。
  • 某些设备需要发送特定命令后才会返回数据。
  1. 数据乱码
  • 确保数据编码方式一致(UTF-8、HEX等)。
  • 使用 ArrayBuffer 进行传输,避免字符集问题。

六、最佳实践建议

  • 断线重连:监听 uni.onBLEConnectionStateChange,自动重连。
  • 定时心跳:某些设备需要定期发送心跳包保持连接。
  • MTU 调整uni.setBLEMTU() 可优化大数据传输效率。
  • 封装模块:将蓝牙操作封装为独立模块,便于复用和维护。

七、总结

本文介绍了 UniApp 对接 BLE 蓝牙设备的完整流程,从蓝牙原理到 API 使用,再到完整示例与调试技巧,涵盖了大部分常见场景。掌握这些内容,你就可以轻松实现跨平台蓝牙功能,连接智能硬件、可穿戴设备、IoT 传感器等,为你的应用赋能。

蓝牙开发看似复杂,但只要理清流程并掌握关键 API,就能快速上手。在实际项目中,建议根据设备协议封装好数据收发逻辑,提高代码可维护性。



日期:2025-08-05