uni-app蓝牙搜索与连接必须真机运行,模拟器必失败;iOS需manifest配置NSBluetoothAlwaysUsageDescription及后台模式,Android 12+须动态申请bluetoothScan/connect权限,低于API 31还需定位权限,且openBluetoothAdapter前须确认系统蓝牙已开启。
uni-app 蓝牙搜索与连接在真机上才能跑通,模拟器必失败且无提示;ios 和 android 权限路径完全不同,不区分平台直接写会卡死在 uni.openbluetoothadapter。
uni.openBluetoothAdapter 失败的 4 个硬性前提
这不是代码 bug,而是系统级门槛没跨过去:
- iOS 必须在
manifest.json的app-plus → permissions中勾选「蓝牙」,并填写NSBluetoothAlwaysUsageDescription文案(Xcode 打包后还需手动开启 Background Modes → Bluetooth Central) - Android 12+(API 31+)必须动态申请
scope.bluetoothScan和scope.bluetoothConnect,不能只调一次uni.authorize—— 这两个 scope 要分开授权 - Android 低于 API 31 仍需
scope.location(因为系统把蓝牙扫描归为定位行为),且部分厂商(华为/小米)会静默关闭扫描,得弹窗提醒用户手动打开 - 调用前先确认系统蓝牙已开:
uni.getConnectedBluetoothDevices或uni.getBluetoothAdapterState返回available: true,否则uni.openBluetoothAdapter会静默失败或返回errCode=10001
startBluetoothDevicesDiscovery 搜不到设备的 3 种典型原因
不是外设坏了,大概率是参数或监听时机错了:
- 没等
uni.openBluetoothAdapter的success回调执行完,就直接调uni.startBluetoothDevicesDiscovery—— 这会导致errCode=10000 -
uni.onBluetoothDeviceFound必须在start之前注册,且不能用箭头函数(this绑定失效会导致监听丢失);它只对本次 discovery 有效,重启扫描就得重绑 - 没传
services参数:很多 BLE 设备广播时不带 service UUID,必须显式传空数组{services: []},否则 iOS/iOS 15+ 会过滤掉
createBLEConnection 后读不到数据?流程断在中间了
连接成功 ≠ 可通信。BLE 是状态机驱动,跳过任意一步都会报 errCode=10006:
- 必须监听
uni.onBLEConnectionStateChange,确认connected: true后再走下一步 - 调
uni.getBLEDeviceServices获取服务列表,注意检查isPrimary: true的主服务 - 再用该服务的
uuid调uni.getBLEDeviceCharacteristics,重点看properties.read或properties.notify是否为true(大小写敏感) - 启用通知必须用
uni.notifyBLECharacteristicValueChange,且state: true;别漏掉serviceId和characteristicId参数,它们必须来自上一步返回值
真机调试时最常被忽略的细节
这些点不写进文档,但一踩一个准:
- HBuilderX 的「USB 连接调试」会拦截蓝牙 API,务必改用 Wi-Fi 调试或离线打包
- Android 下某些设备只在广播窗口期(比如每 2 秒一次)发包,
duration至少设 10 秒,别指望“秒出结果” - 设备名为空时,
device.name是undefined,得 fallback 到device.localName;但 iOS 对localName支持不稳定,建议优先用deviceId做唯一标识 - 连接后别忘了调
uni.stopBluetoothDevicesDiscovery—— 不停扫会持续耗电,部分安卓机型还会因此触发系统级降频











