UniApp 对接蓝牙设备全攻略(含完整示例)
随着物联网(IoT)的快速发展,越来越多的移动应用需要与蓝牙设备进行通信,例如智能手环、蓝牙秤、蓝牙打印机、工业传感器等。在跨平台开发中,UniApp 作为一款支持一套代码多端运行的框架,天然具备对接蓝牙设备的优势。
本文将系统介绍 如何在 UniApp 中对接蓝牙设备,包括蓝牙原理、API 说明、完整示例代码、调试技巧及注意事项,帮助你快速上手蓝牙开发。
一、蓝牙开发原理简述
在开始写代码之前,我们先了解蓝牙的基本原理。
蓝牙通信主要分为两类:
- 经典蓝牙(BR/EDR)
- 常用于音频传输(如耳机、音箱)
- 速率较高
- 一般需要配对
- UniApp 暂时不支持经典蓝牙,主要支持 BLE
- 低功耗蓝牙(BLE,Bluetooth Low Energy)
- 功耗低,数据传输速率较低
- 常用于传感器、可穿戴设备、IoT
- 基于 GATT(Generic Attribute Profile)通信
- 以 Service(服务) 和 Characteristic(特征值) 为核心
- 支持读取(read)、写入(write)、通知(notify)等操作
在 UniApp 中,我们主要使用 低功耗蓝牙(BLE) 相关 API。
二、UniApp 蓝牙 API 总览
UniApp 提供了多套跨端蓝牙 API,主要与微信小程序 API 一致,核心流程如下:
- 初始化蓝牙适配器
uni.openBluetoothAdapter()
- 开始扫描设备
uni.startBluetoothDevicesDiscovery()
- 监听设备发现事件
uni.onBluetoothDeviceFound(callback)
- 连接设备
uni.createBLEConnection()
- 获取设备服务
uni.getBLEDeviceServices()
- 获取服务特征值
uni.getBLEDeviceCharacteristics()
- 读写数据
- 写入:
uni.writeBLECharacteristicValue()
- 读取:
uni.readBLECharacteristicValue()
- 监听:
uni.notifyBLECharacteristicValueChange()
- 关闭连接
- 断开设备:
uni.closeBLEConnection()
- 关闭蓝牙适配器:
uni.closeBluetoothAdapter()
三、开发前准备
- 真机调试
- 蓝牙相关 API 无法在浏览器或模拟器中运行,必须真机测试。
- 设备需支持 BLE。
- 权限配置
- 在微信小程序中,需要在
manifest.json
中勾选“蓝牙”权限。 - Android 还需定位权限(扫描设备需要)。
- iOS 需要在
manifest.json
配置NSBluetoothAlwaysUsageDescription
描述。
- 硬件信息
- 了解目标设备的 Service UUID 与 Characteristic 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>
五、调试与常见问题
- 无法扫描到设备
- 确保设备已开启蓝牙广播。
- Android 需要开启定位权限。
- iOS 需在
manifest.json
添加使用描述。
- 连接失败
- 检查设备是否已被其他手机连接。
- 检查 UUID 是否正确。
- 收不到数据
- 确认
notify
特征值已开启。 - 某些设备需要发送特定命令后才会返回数据。
- 数据乱码
- 确保数据编码方式一致(UTF-8、HEX等)。
- 使用
ArrayBuffer
进行传输,避免字符集问题。
六、最佳实践建议
- 断线重连:监听
uni.onBLEConnectionStateChange
,自动重连。 - 定时心跳:某些设备需要定期发送心跳包保持连接。
- MTU 调整:
uni.setBLEMTU()
可优化大数据传输效率。 - 封装模块:将蓝牙操作封装为独立模块,便于复用和维护。
七、总结
本文介绍了 UniApp 对接 BLE 蓝牙设备的完整流程,从蓝牙原理到 API 使用,再到完整示例与调试技巧,涵盖了大部分常见场景。掌握这些内容,你就可以轻松实现跨平台蓝牙功能,连接智能硬件、可穿戴设备、IoT 传感器等,为你的应用赋能。
蓝牙开发看似复杂,但只要理清流程并掌握关键 API,就能快速上手。在实际项目中,建议根据设备协议封装好数据收发逻辑,提高代码可维护性。
日期:2025-08-05