盘点Uniapp BLE低功耗蓝牙开发常见问题(一)
项目场景:
在 UniApp 开发蓝牙设备联动应用(如智能硬件、设备控制、数据采集)时,蓝牙模块是兼容性问题最多、调试难度最大的功能之一。官方 API 封装虽简化了原生调用,但平台差异、权限机制、设备适配、连接稳定性等问题,很容易让新手踩坑。
本文基于 UniApp 官方 uni.openBluetoothAdapter 等蓝牙 API,适用APP 端(安卓 /iOS),小程序端逻辑基本通用,仅部分权限 / 生命周期略有差异。
问题1:iOS 蓝牙初始化成功,安卓直接报错 / 不执行回调
问题现象
调用 uni.openBluetoothAdapter 初始化蓝牙适配器:
- iOS 端正常回调 success;
- 安卓端直接无响应、报错 fail,或提示「未发现蓝牙适配器」。
原因分析:
1.安卓动态权限缺失:安卓 6.0+ 蓝牙需要位置权限、蓝牙扫描权限,仅配置清单文件无效;
2.安卓蓝牙依赖 GPS 开启:安卓 10 以下,蓝牙扫描必须打开 GPS,否则初始化 / 扫描失败;
3.部分安卓机蓝牙模块加载慢,未等待系统就绪就调用 API。
解决方案:
1.配置安卓权限
manifest.json → App 权限配置
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
2.初始化前先校验权限 + GPS
// 蓝牙初始化通用方法
async initBluetooth() {
// 1. 先判断蓝牙是否可用
const systemInfo = uni.getSystemInfoSync();
if(systemInfo.platform === 'android'){
// 安卓强制校验GPS
const locationStatus = await this.checkAndroidGPS();
if(!locationStatus){
uni.showModal({title:'提示',content:'请打开手机GPS和位置权限'});
return false;
}
}
return new Promise((resolve) => {
uni.openBluetoothAdapter({
success: () => resolve(true),
fail: (err) => {
uni.showToast({title:'蓝牙初始化失败',icon:'none'});
resolve(false);
}
})
})
}
3.延迟重试
安卓机初始化失败后,延迟 500ms 重试一次。
问题2:扫描不到蓝牙设备,iOS 能扫到,安卓扫不到
问题现象
调用 uni.startBluetoothDevicesDiscovery 启动扫描,iOS 能正常发现设备,安卓列表为空。
原因分析:
- 安卓未授权位置权限,扫描直接被系统拦截;
- 扫描服务 UUID 填写错误 / 不填;
- 安卓后台限制扫描频率,扫描未持续执行。
解决方案:
1.动态申请位置权限
// 安卓扫描前申请权限
async requestAndroidPermission() {
const status = await uni.requestPermissions({
platform: 'android',
permissions: ['android.permission.ACCESS_FINE_LOCATION']
});
return status[0] === 'authorized';
}
2.扫描时必须传入 services UUID
uni.startBluetoothDevicesDiscovery({
services: ['0000ffe0-0000-1000-8000-00805f9b34fb'], // 硬件对应的服务UUID
allowDuplicatesKey: false,
success: () => {}
})
3.延迟停止
安卓扫描持续至少 2 秒,不要立即停止扫描。
问题3:连接设备提示 fail:connection fail/ 超时断开
问题现象
扫描到设备后调用 uni.createBLEConnection,直接报错连接失败,或连接后 1 秒自动断开。
原因分析:
- 设备地址问题:安卓用 deviceId 是 MAC 地址,iOS 是 UUID,直接混用会连接失败;
- 连接前未停止扫描,系统资源冲突;
- 设备已被其他手机绑定 / 连接;
- 服务 / 特征值未获取,连接流程不完整。
解决方案:
1.连接前必须停止扫描
// 标准连接流程
async connectDevice(deviceId) {
// 第一步:停止扫描
await uni.stopBluetoothDevicesDiscovery();
// 第二步:创建连接
return new Promise((resolve, reject) => {
uni.createBLEConnection({
deviceId,
timeout: 10000,
success: () => resolve(true),
fail: (err) => reject(err)
})
})
}
2.严格使用 API 返回的 deviceId,不要手动修改 / 拼接;
3.延迟获取服务
连接成功后延迟 500ms 再获取服务,避免时序问题。
问题4:获取服务 / 特征值失败,提示 get service fail
问题现象
连接成功后,调用 uni.getBLEDeviceServices 或 uni.getBLEDeviceCharacteristics 失败,无法拿到特征值。
原因分析:
- 连接刚建立就调用 API,通信未就绪;
- 设备服务 UUID 不匹配,硬件未正确广播;
- iOS 对服务获取有严格时序要求。
解决方案:
1.连接成功后加延迟(500ms~800ms)
2.遍历服务 + 特征值,不要硬编码索引
// 正确获取特征值
async getDeviceChar(deviceId) {
const { services } = await uni.getBLEDeviceServices({ deviceId });
// 遍历所有服务
for (let service of services) {
const { characteristics } = await uni.getBLEDeviceCharacteristics({
deviceId,
serviceId: service.uuid
});
// 找到可写/可读特征值
const writeChar = characteristics.find(item => item.properties.write);
const notifyChar = characteristics.find(item => item.properties.notify);
if(writeChar && notifyChar) return { writeChar, notifyChar };
}
}
问题5:开启 notify 失败,收不到设备返回的数据
问题现象
调用 uni.notifyBLECharacteristicValueChange 开启监听,回调成功,但设备发送数据时,APP 完全收不到。
原因分析:
- 特征值属性错误:开启 notify 必须用带有 notify/indicate 属性的特征值;
- 未监听 onBLECharacteristicValueChange 全局事件;
- iOS 必须先写descriptor才能正常接收数据(官方隐藏坑点)。
解决方案:
1.确保特征值支持 notify
2.提前注册全局监听
onLoad() {
uni.onBLECharacteristicValueChange((res) => {
// 接收设备数据
const data = this.arrayBuffer2hex(res.value);
console.log('收到数据:', data);
})
}
更多推荐

所有评论(0)