uni-app蓝牙连接失败主因是环境与权限未到位:iOS需配置NSBluetoothAlwaysUsageDescription及后台模式,Android 12+需动态申请BLUETOOTH_SCAN/CONNECT及定位权限;必须监听onBluetoothAdapterStateChange确认可用后操作,搜索需传services数组,连接后须按“发现服务→特征值→启用通知”完整流程执行。

uni-app 蓝牙连接失败常见原因和基础校验
绝大多数连接失败不是代码写错,而是环境或权限没到位。iOS 和 Android 行为差异大,必须分平台处理。
- iOS 必须在
info.plist中添加NSBluetoothAlwaysUsageDescription描述,且 App 需开启「蓝牙后台模式」(Xcode → Signing & Capabilities → Background Modes → Bluetooth Central) - Android 12+(API 31+)需在
AndroidManifest.xml中声明BLUETOOTH_SCAN、BLUETOOTH_CONNECT权限,并在运行时动态申请;低于 API 31 还要加ACCESS_FINE_LOCATION(因为蓝牙扫描被归类为定位相关行为) - 调用
uni.openBluetoothAdapter()后,务必监听onBluetoothAdapterStateChange,确认available: true且discovering: false才能继续 - 部分安卓厂商(如华为、小米)系统会自动关闭蓝牙扫描,建议在扫描前弹窗提示用户“请保持蓝牙开启并允许位置权限”
搜索设备时搜不到?重点检查 serviceUUID 和 scan 参数
uni-app 的 uni.startBluetoothDevicesDiscovery() 默认不传 services 数组,等价于“扫所有设备”,但很多低功耗蓝牙(BLE)设备广播时不带 serviceUUID,导致无法被发现——这不是 bug,是 BLE 协议限制。
- 如果目标设备有公开的主 service UUID(比如心率表常用
0000180D-0000-1000-8000-00805F9B34FB),务必显式传入:services: ['0000180D-0000-1000-8000-00805F9B34FB'] -
allowDuplicatesKey设为true可避免重复触发onBluetoothDeviceFound,但会增加内存占用;生产环境建议设false并自己做去重(按deviceId缓存) - 某些设备只在特定时间窗口广播(比如每 2 秒发一次),所以
duration至少设为 10 秒,别依赖“立刻出现” - 真机调试时禁用 HBuilderX 的“USB 连接调试”,改用 Wi-Fi 调试或离线打包,否则蓝牙 API 可能被拦截
连接成功后读取 characteristic 数据总返回 null 或报错
连接 ≠ 可读。BLE 通信必须走完整流程:连接 → 发现服务 → 发现特征值 → 启用通知/读取值。跳过任意一步都会失败。
- 务必等
uni.getConnectedBluetoothDevices()返回目标设备后再调用uni.createBLEConnection(),否则 iOS 会直接拒绝 -
uni.getBLEDeviceServices()成功后,再调用uni.getBLEDeviceCharacteristics(),注意传入正确的serviceId(从上一步返回中取,不是你猜的) - 读取前先确认 characteristic 的
properties.read === true;若要监听实时数据,需先uni.notifyBLECharacteristicValueChange()开启通知,再等onBLECharacteristicValueChange回调——这个回调才是真实数据来源 - 安卓上若读取返回
errMsg: "readCharacteristic:fail not connected",大概率是连接已断开但没监听onBLEConnectionStateChange,建议在连接后立即注册该监听
iOS 上 notify 失败或收不到回调?关键在 descriptor 写入
iOS 要求必须向 characteristic 对应的 CCCD(Client Characteristic Configuration Descriptor)写入启用字节(0x01, 0x00),否则即使调用了 notifyBLECharacteristicValueChange,也不会触发通知。
- 调用
uni.notifyBLECharacteristicValueChange({ state: true, ... })后,uni-app 内部会自动尝试写 CCCD,但某些固件要求手动写——此时需用uni.writeBLECharacteristicValue(),value是ArrayBuffer,内容为new Uint8Array([0x01, 0x00]).buffer - CCCD 的 handle 通常为原 characteristic handle + 1,但不可硬编码;稳妥做法是先用
uni.readBLECharacteristicValue()读一次(即使无意义),再查日志看返回的 descriptor handle(HBuilderX 调试器 → Console → 点开 ble 日志) - 写 descriptor 前必须确保 characteristic 支持
write属性,否则报"writeCharacteristic:fail not support write"
BLE 设备协议千差万别,同一型号不同固件版本可能改变 characteristic handle 或 descriptor 行为。抓包(nRF Connect + HCI log)比猜更可靠。











