🐛 startDeviceScan errors with "BleManager was destroyed" on android API level 33 (android 13) when published (works fine when running with metro)
Prerequisites
- [X] I checked the documentation and FAQ without finding a solution
- [X] I checked to make sure that this issue has not already been filed
Expected Behavior
startDeviceScan should work as normal
Current Behavior
My app works on ios, android 11, android 14. It also works on android 14 when running with metro (npx react-native run-android) When running the published app, startDeviceScan always errors with "BleManger was destroyed". I've even tried conditionally reinitialising bleManager imediately before device scan: if(!bleManager) bleManager = new BleManager()
Library version
3.2.1
Device
all android 13 (api level 33) devices
Environment info
react-native 0.74.0
Steps to reproduce
attempt startDeviceScan in published app on android 13 (api 33)
Formatted code sample or link to a repository
const callBleScanner = async () => {
// if no bleManager: reinitialise
if(!bleManager){
bleManager = new BleManager();
// verify that the ble manager is created.
logger(`BLE Manager reinitialized? ${bleManager}`)
}
// to ensure useEffect is triggered by errors: reset 'scanError' state
setScanError(false);
// Use a try catch for more robust error catching
try{
// Attempt scanning
logger("Attempt startDeviceScan:")
bleManager.startDeviceScan(
null,
// use low latency scan on android for quicker discovery.
Platform.OS === "android" ? {scanMode: ScanMode.LowLatency} : null,
// handle scan error.
(error, scannedDevice) => {
if (error) {
// stringify the ble error to get all available information.
setScanError(true);
logger(`Bluetooth scanning error: ${JSON.stringify(error)}`)
}
if (!scannedDevice) return
if(!scannedDevice.name) return
let nameContainsKeyChars = /(ES-|IS-)/.test(scannedDevice.name)
if(!nameContainsKeyChars) return
logger(`DEVICE FOUND: ${scannedDevice.name}`)
// conditionally update state with new device.
setDevicesFound((prevState: Device[]) => {
if (isOriginalDevice(prevState, scannedDevice)) {
return [...prevState, scannedDevice];
}
return prevState;
});
}
);
} catch (error) {
// this catch always runs on android 13 (api 33) in the published app (not in dev)
logger(`Failed Bluetooth-state check & scan-start: ${error}`)
setScanError(true)
}
}
Relevant log output
"Failed Bluetooth-state check & scan-start: BleManagerWasDestroyed"
Additional information
No response
Hi @ArthurRuxton-DY
Where do you store your bleManager? According to the documentation it should be initialized once, outside of React.
Aside from that, your code looks fine, so I would need more context to determine what's causing the error.
Hi @intent-kacper-cyranowski thanks for your response. I have a custom hook where all blw methods live. Originally my bleManager was initialised at the top of that file, so outside of React. I think Android 13 did not agree with some other aspect of my set up.
In the end the only way to get my implementation to work on all api levels was to initialise the bleManager after permissions had been granted rather than before. This solution actually caused the same bug in IOS, so now I conditionally initialise the bleManger before / after permissions are granted.
for IOS: initialise bleManager > request permissions > check permissions granted > start scanning for Android: request permissions > check permissions granted > initialise bleManager > start scanning
Hello @ArthurRuxton-DY. I suppose there's an issue with your hook implementation (I'm not 100% sure, because it's not included in the code snipped). The ble manager must be initialised once. If for some reason it gets re-initialised you will see such error. Please check our implementation in the example app.