首次使用react-native-ble-manager调用scan()致APP崩溃求助
React Native BleManager调用scan()时APP直接闪退问题排查
首次使用react-native-ble-manager进行开发,APP已配置所需全部权限,但调用BleManager.scan()时,APP无任何错误日志直接闪退。
测试代码(结构较粗糙,仅作测试用)
import BleManager from 'react-native-ble-manager'; const BleManagerModule = NativeModules.BleManager; const bleManagerEmitter = new NativeEventEmitter(BleManagerModule); const handleDiscoverPeripheral = (peripheral) => { console.log('Got ble peripheral', peripheral); if (!peripheral.name) { peripheral.name = 'NO NAME'; } peripherals.set(peripheral.id, peripheral); setList(Array.from(peripherals.values())); } const handleStopScan = () => { console.log('Scan is stopped'); } let interval; let gImageShow = true; let gTime = 0; BleManager.enableBluetooth() .then(() => { // Success code console.log("The bluetooth is already enabled or the user confirm"); }) .catch((error) => { // Failure code console.log("The user refuse to enable bluetooth"); }); function App(props) { const [shouldShow, setShouldShow] = useState(gImageShow); useEffect(() => { interval = setInterval(() => { if (gTime == 1) { BleManager.start({showAlert: true}); bleManagerEmitter.addListener('BleManagerDiscoverPeripheral', handleDiscoverPeripheral); bleManagerEmitter.addListener('BleManagerStopScan', handleStopScan ); PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION).then((result) => { if (result) { console.log("Permission is OK"); } }); } if (gTime == 5) { BleManager.scan([], 10, true); } gImageShow = !gImageShow; setShouldShow(gImageShow); gTime = gTime + 1; },1000); return () => clearInterval(interval); }, []); useEffect(() => { });
AndroidManifest配置
xmlns:tools="http://schemas.android.com/tools" package="com.diagnostic_ble"> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="28"/> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" tools:targetApi="Q"/> <!-- Needed only if your app looks for Bluetooth devices. --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" /> <uses-permission-sdk-23 android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
代码逻辑:启动后先开启蓝牙,1秒时初始化蓝牙管理器并添加监听,5秒时执行扫描操作,但APP在5秒时立即崩溃,以下是可能的原因:
- 权限配置不完整:Android 12+的
BLUETOOTH_SCAN权限需要额外声明属性。如果你的扫描不需要位置信息,需给BLUETOOTH_SCAN添加android:usesPermissionFlags="neverForLocation";如果需要位置关联,要确保已动态获取ACCESS_FINE_LOCATION权限,当前配置缺少该属性可能触发权限验证崩溃。 - 全局变量引发状态冲突:代码中用全局变量
gTime、gImageShow管理状态,在setInterval中直接修改并更新React状态,容易导致组件状态不一致,触发扫描时引发内存或状态异常。应改用useState管理这些变量,避免全局副作用。 - 蓝牙初始化时机错误:
BleManager.enableBluetooth()在组件外部调用,此时组件尚未挂载,蓝牙初始化流程与组件生命周期冲突,可能导致扫描时蓝牙服务未正确初始化。需将蓝牙启用逻辑移到组件内部的useEffect中。 - 监听器重复添加风险:
gTime == 1分支中每次执行都会添加监听器,若setInterval逻辑异常导致分支重复执行,会引发监听器重复绑定,造成内存泄漏或事件处理冲突,最终导致崩溃。应将监听器添加逻辑移到单独的useEffect中,确保只绑定一次。 - 未捕获扫描异常:
BleManager.scan()返回Promise但未添加.catch()处理,扫描过程中的错误无法被捕获,直接导致APP闪退。需补充错误捕获:BleManager.scan([], 10, true) .then(() => console.log('Scan started')) .catch(err => console.error('Scan error:', err));
内容的提问来源于stack exchange,提问作者damooo
相关产品推荐
相关产品推荐

