uni.openbluetoothadapter失败是90%连接问题的根源,需检查ios的nsbluetoothalwaysusagedescription配置和android 12+的bluetooth_scan/connect及定位权限,失败后必须通过errcode(如10001、10002)精准定位原因。
uni-app 连接低功耗蓝牙模块,90% 的失败发生在 uni.openbluetoothadapter 这一步——不是代码写错,而是权限、系统状态或平台差异没兜住。
uni.openBluetoothAdapter 失败的硬性条件检查
这一步卡住,后续所有操作都无效。它不报错、不弹窗、不回调,只静默失败,尤其在模拟器里必挂(真机才支持)。
- iOS 必须在
manifest.json的ios节点下配置NSBluetoothAlwaysUsageDescription字符串,且不能为空;Xcode 打包时还要勾选「Bluetooth Central」后台模式 - Android 12+(API 31+)需同时满足三件事:
android.permission.BLUETOOTH_SCAN、android.permission.BLUETOOTH_CONNECT、android.permission.ACCESS_FINE_LOCATION—— 缺一不可,且前两者必须动态调用uni.authorize({scope: 'scope.bluetoothScan'})等授权 - 调用后别急着搜设备,先用
uni.getBluetoothAdapterState()确认available: true且discovering: false,否则说明适配器没真正就绪 - 失败回调中务必打印
err.errCode:10001是系统蓝牙未开或定位开关关闭;10002是 iOS 描述文案缺失或 Android 权限被拒
搜索不到设备:参数和监听顺序不能错
uni.startBluetoothDevicesDiscovery 启动后没回调,大概率是“启动前没清理”或“监听注册太晚”。
- 每次 start 前加保险:先
uni.stopBluetoothDevicesDiscovery,再setTimeout300ms,避免系统认为上一次扫描还在进行中 -
uni.onBluetoothDeviceFound必须在start调用前注册,且不能用箭头函数(this绑定失效会导致监听丢失) - 传参显式指定
{ services: [], allowDuplicatesKey: true }:空services才能扫到不广播 service UUID 的设备(比如多数自定义硬件);allowDuplicatesKey: true防止 iOS 漏掉首条广播 - 别依赖
uni.getConnectedBluetoothDevices立即查结果——它只返回历史缓存,新设备只通过onBluetoothDeviceFound回调到达
连接后读不到数据:GATT 流程缺一不可
连上 ≠ 能通信。BLE 是分层协议,跳过任一环节,readBLECharacteristicValue 或 notifyBLECharacteristicValueChange 必报 10008(未找到特征值)或 10010(连接已断)。
- 必须等
uni.onBLEConnectionStateChange触发且connected: true后,再调uni.getConnectedBluetoothDevices查当前连接设备列表 - 接着调
uni.getBLEDeviceServices发现服务——很多医疗设备(如血压仪)用标准 service UUID00001810-0000-1000-8000-00805f9b34fb,建议直接写死,别全量扫 - 再调
uni.getBLEDeviceCharacteristics获取特征值;注意:iOS 和 Android 返回的特征值数组索引可能不同(iOS 常为[0],Android 常为[1]),需平台判断 - 启用通知前,先确认该特征值支持
notify属性(看properties.notify === true),否则notifyBLECharacteristicValueChange会静默失败
Android 14 下 MTU 协商失败怎么办
部分 Android 14 设备(尤其三星、Pixel)在调用 uni.setBLEMTU 时会报错或无响应,这不是 uni-app bug,而是系统限制变严。
- 不要在连接刚建立后立刻
setBLEMTU,等onBLEConnectionStateChange稳定 500ms 再执行 - 失败时降级处理:捕获错误后,继续用默认 MTU(23 字节)发送,拆包逻辑由应用层补足
- 对长指令(如打印标签),优先用分段
writeBLECharacteristicValue+ 重试机制,比强求大 MTU 更可靠 - 若必须协商,建议在
getBLEDeviceCharacteristics成功后、启用 notify 前执行,并设超时 2s,超时则跳过
最易被忽略的是:整个流程里没有“等待完成”的显式状态标记。比如 getBLEDeviceServices 是异步的,但它的 success 回调不保证服务树已加载完毕;实际开发中,最好用 Promise 封装每一步,并用 deviceId + serviceId + characteristicId 三级缓存做防抖,否则用户快速点击容易触发重复请求或状态错乱。











