react-native-ble-plx扫描逻辑移入npm模块后不生效如何解决?
存在多份
react-native-ble-plx依赖实例
即使你在模块中声明了peer依赖,通过本地file:路径引入模块时,npm/yarn会默认在模块自身的node_modules目录下安装一份独立的react-native-ble-plx依赖,导致应用层和模块层分别引用了不同的包实例。原生层的BLE服务只会绑定第一个初始化的BleManager,你在模块中初始化的BleManager实际没有绑定原生服务,因此扫描无回调,而onStateChange属于JS层的状态监听所以能正常触发。
验证方法:在模块代码和应用代码中分别打印BleManager的引用,判断是否为同一个对象:console.log(BleManager === require('react-native-ble-plx').BleManager),返回false则说明存在多份依赖。
修复方案:修改metro.config.js配置,强制所有react-native-ble-plx的引用都指向应用层的node_modules:const path = require('path'); module.exports = { resolver: { extraNodeModules: { 'react-native-ble-plx': path.resolve(__dirname, 'node_modules/react-native-ble-plx'), 'react-native': path.resolve(__dirname, 'node_modules/react-native') } } };同时安装模块时可手动删除模块目录下的
node_modules/react-native-ble-plx文件夹避免重复加载。扫描发起时机早于BLE硬件就绪
你当前的代码没有监听BLE适配器状态就直接发起扫描,模块通常在应用启动阶段就被import加载,BleManager初始化的时机远早于普通业务代码,此时BLE适配器可能还未处于PoweredOn状态,直接扫描不会返回任何结果。应用本地代码运行时通常是用户触发操作时才调用,此时BLE适配器已经就绪,所以能正常扫描。
修复方案:在发起扫描前先等待BLE状态就绪,修改tryScan逻辑:export const tryScan = async () => { // 先请求权限 await PermissionsAndroid.request( PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, ); // 等待BLE状态变为可用 await new Promise((resolve) => { const subscription = manager.onStateChange((state) => { if (state === 'PoweredOn') { subscription.remove(); resolve(true); } }, true); }); // 再发起扫描 manager.startDeviceScan( null, { allowDuplicates: true }, (error, scannedDevice) => { console.log('Discovered device', scannedDevice); manager.stopDeviceScan(); }, ); };权限申请未完成就发起扫描
你当前代码中PermissionsAndroid.request是异步方法,你没有等待权限返回就直接发起扫描,当模块运行时权限申请的回调速度比应用本地运行慢,会导致扫描时还没有拿到定位权限,从而无法返回扫描结果,上述修改方案中的await逻辑也同时解决了该问题。
内容的提问来源于stack exchange,提问作者Viktor

