uni.openBluetoothAdapter失败是连接失败主因,需检查Android权限(BLUETOOTH、BLUETOOTH_ADMIN、ACCESS_FINE_LOCATION)和iOS的NSBluetoothAlwaysUsageDescription配置,再通过errCode判断具体问题。

uni.openBluetoothAdapter 失败就别往下走了
绝大多数连接失败,根源都在这一步没过。不是设备没开蓝牙,而是权限或系统状态卡住了——尤其 Android 6.0+ 必须同时拿到 android.permission.BLUETOOTH、android.permission.BLUETOOTH_ADMIN 和 android.permission.ACCESS_FINE_LOCATION,缺一个 openBluetoothAdapter 就静默失败;iOS 则必须在 manifest.json 的 ios 节点里配好 NSBluetoothAlwaysUsageDescription,否则首次调用直接 reject。
实操建议:
- 别只看 success 回调,
fail里一定要打errCode:比如10001是适配器不可用(用户没开蓝牙),10002是未授权定位(Android)或描述文案为空(iOS) - 调用
uni.openBluetoothAdapter后,立刻跟一句uni.getBluetoothAdapterState,确认available: true且discovering: false再启动搜索 - 小程序端无需定位权限,但真机调试时微信会强制要求开启“位置信息”,这个开关藏得深,容易漏
uni.startBluetoothDevicesDiscovery 搜索不到设备?先看它有没有被提前 stop
这是最隐蔽的坑:你点了“搜索”,代码执行了 startBluetoothDevicesDiscovery,但没反应——很可能上一次搜索没 clean up,系统认为还在进行中,新请求直接被忽略。uni-app 的蓝牙 API 是单例模型,不允许多个 discovery 并行。
实操建议:
- 每次开始前加一层保险:
uni.stopBluetoothDevicesDiscovery+setTimeout等 300ms 再 start,避免状态残留 - 搜索时间别设太长,10 秒足够;超时后必须手动
stop,否则 iOS 会持续耗电,Android 可能触发系统限频 -
onBluetoothDeviceFound是唯一可靠监听入口,别依赖getBluetoothDevices立即拿到结果——它返回的是历史缓存,新设备要等回调触发后才入库
连上了却读不到数据?大概率是没走通 GATT 流程
BLE 不是“连上就能发”,而是严格按 GATT 分层:先 createBLEConnection 建链,再 getBLEDeviceServices 找服务,再 getBLEDeviceCharacteristics 找特征值,最后才能 notifyBLECharacteristicValueChange 或 writeBLECharacteristicValue。跳过任一环,read 或 notify 都会报错 10008(未找到特征值)或 10010(连接已断)。
实操建议:
- 血压仪、血糖仪这类医疗设备,服务 UUID 和特征值 UUID 通常固定,比如标准血压服务是
00001810-0000-1000-8000-00805f9b34fb,别硬扫,直接写死更稳 -
notifyBLECharacteristicValueChange必须在onBLECharacteristicValueChange监听注册之后再启用,顺序反了监听收不到数据 - Android 上某些设备(尤其老款国产血压仪)需要先
write一条启动指令(如0101),才会开始广播测量数据,空等 notify 是徒劳
设备列表里 deviceId 为空?iOS 下只能靠 advertisData 解析 MAC
iOS 系统禁止 App 获取蓝牙设备真实 MAC 地址,deviceId 字段恒为随机字符串(如 8A2E7F1C-...-B5D9),每次重启 App 都变。如果你要做“记住上次连接设备”,不能存 deviceId,得让硬件厂商把真实 MAC 放进广播包的 advertisData 里,然后你自己解析。
实操建议:
- 安卓端可直接用
device.deviceId做本地缓存;iOS 必须解析device.advertisData(ArrayBuffer类型),常见做法是转成 hex 字符串后取后 6 字节(如"0201060303aafe1316aafe..."中提取"aafe1316aafe") - 别在
onBluetoothDeviceFound里直接处理连接逻辑——该回调可能高频触发,重复连接会失败;应该先收集进devicesList,由用户点击后统一 connect - 连接成功后立即调用
uni.closeBLEConnection关闭,否则下次createBLEConnection会因“设备忙”报错10003
真正难的从来不是调用几个 API,而是理解 BLE 的状态机本质:每一步都依赖上一步的完成态,且 iOS/Android 在底层行为上存在不可抹平的差异。别迷信“一次写完跑全端”,该分平台写的判断就得写,该让硬件配合改广播的也别硬扛。











