react-native-ble-manager 扫描结果突然变成 空数组 ,通常不是代码逻辑问题,而是 权限 / 系统策略 / BLE 设备广播变化。你这段代码本身逻辑是没问题的。常见原因主要有下面几类(按概率排序):
1️⃣ Android 12+ 蓝牙权限变化(最常见)
如果你的 targetSdkVersion ≥ 31 (Android 12) ,必须增加新的蓝牙权限,否则 scan 会成功执行但返回空设备。
AndroidManifest.xml 必须增加
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
兼容旧版本:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
同时需要运行时权限
React Native 代码:
import {PermissionsAndroid} from 'react-native';
async function requestPermissions() {
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
]);
}
启动 BLE 前调用:
await requestPermissions();
否则:
getDiscoveredPeripherals() = []
2️⃣ 没有监听
BleManagerDiscoverPeripheral
事件
BleManager.getDiscoveredPeripherals() 依赖 扫描事件缓存。
新版 Android 有时不会自动缓存。
建议监听事件:
import {NativeEventEmitter, NativeModules} from 'react-native';
const bleManagerEmitter = new NativeEventEmitter(NativeModules.BleManager);
bleManagerEmitter.addListener(
'BleManagerDiscoverPeripheral',
(peripheral) => {
console.log('discover', peripheral);
}
);
如果这里 没有任何输出
说明 scan 根本没有发现设备。
3️⃣ 打印机不再广播 name
很多 BLE 打印机升级固件后:
peripheral.name = null
设备名称在:
peripheral.advertising.localName
所以建议改为:
const printer = peripherals.find(
p =>
p.name === printerName ||
p.advertising?.localName === printerName
);
4️⃣ scan 参数问题
你现在:
BleManager.scan([], 5, true);
第三个参数 true 是 allowDuplicates
建议改成:
BleManager.scan([], 5, false);
有些 Android 会过滤。
5️⃣ Android 没打开定位
Android BLE 扫描必须开启:
Location Service
否则:
scan = []
6️⃣ iOS 17 / Android 13 扫描策略改变
如果是新系统:
扫描必须:
BleManager.start({showAlert: false})
在扫描前调用:
await BleManager.start({showAlert: false});
7️⃣ 你的 timeout 可能太短
你扫描:
scan 5 秒
timeout 6 秒
建议:
scan 8 秒
timeout 9 秒
推荐改进代码
_scan(printerName) {
return new Promise(async (resolve, reject) => {
try {
await BleManager.start({showAlert:false})
console.log('===========> scanAndConnect');
await BleManager.scan([], 8, false);
setTimeout(async () => {
try {
const peripherals = await BleManager.getDiscoveredPeripherals();
console.log('peripherals', peripherals);
const printer = peripherals.find(p =>
p.name === printerName ||
p.advertising?.localName === printerName
);
resolve(printer);
} catch (e) {
console.log('_scan get device failed', e);
reject(e);
}
}, 9000);
} catch (e) {
console.log('_scan failed', e);
reject(e);
}
});
}
8️⃣ 最关键的排查方法(强烈推荐)
先打印:
console.log(JSON.stringify(peripherals,null,2))
看真实返回结构。
很多时候你会看到:
{
"name": null,
"advertising": {
"localName": "Printer_123"
}
}