-
Notifications
You must be signed in to change notification settings - Fork 518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Android] After migration from 2.0.3 to 3.1.2 device disconnect after 5 second. #1157
Comments
Happens to me as well (only on Android). Works fine on version 2.0.3 |
I have the same issue 🤔. |
I have the same issue |
@dominik-czupryna-withintent @dimninik can you help us to find the issue? |
Don't want to do just a +1, but this seems like an important issue. |
Same situation for me, Android 2.0.3 works fine, 3.1.2 gets disconnected after max 30s await bleManagerDevice.connectToDevice(device.id, { timeout: 15000 });
// disconnect will be after 15s. but increasing timeout to more than 30000 won't increase connection time |
@andreyukD thats works for you? |
@p4bl1t0 version 3.1.2 works only for a few seconds (max 30 seconds - if I set timeout: 30000), if I set timeout 5000 it will work for a 5s, but if I set for instance timeout: 60000 it will be disconnected after ~30 seconds version 2.0.3. works fine |
I seem to be getting the same behaviour in 3.x: the connection always drops after an amount of time roughly equal to the timeout. Android 10 but it seems to be affecting many different devices in production. |
I found the disconnect originates from the onFinally clause here. react-native-ble-plx/android/src/main/java/com/bleplx/adapter/BleModule.java Lines 1227 to 1234 in c60eff0
The problem is that the timeout is added just below, constructed from the original observable. I believe that when the observable made on L1260 errors, it will unsubscribe from the original one constructed on L1227, which triggers the doFinally and disconnects. I don't know Rx for languages other than js. I suppose doFinally is meant to cancel the connection when the connection observable is unsubscribed from. I think the connection can be interrupted as the subscription made on L1264 can be disposed later through the #1135 is a duplicate. Edit: Removing the |
Great find @macksal It's a pitty that dotintent team is so silenced |
Hi,
This function is mainly called in two cases. The first one is when the cancelDeviceConnection function is called, and the second one is when the timeout (https://dotintent.github.io/react-native-ble-plx/#connectionoptions) time that you specify when connecting run out. BluetoothGatt logs when timeout is set in v3:
BluetoothGatt logs when timeout is set in v2:
I also checked error mentoned by @andreyukD that it is not possible to set a timeout longer than 30 seconds but on my devices it occurs after the time I declare (90 sec)
Could you please show me the process you implemented to handle the connection and what devices you use? I'm stuck at the moment and don't know what I could do to get cancelOpen() called in different case. |
I've debugged both versions a bit, so I have two screens:
const processJoinBleQr = (
data: BarCodeScannerResult,
setBleDevices: React.Dispatch<React.SetStateAction<Device[]>>,
navigation: UserStackScreenProps<Routes.AddFromQRScreen>['navigation']
) => {
requestPermissions((isGranted) => {
if (isGranted) {
const onDeviceDisconnected = async (device: Device) => {
const deviceId = device.id;
if (device) {
const subscription = device.onDisconnected((error, device) => {
Alert.alert(translate('ui.bluetoothDevice.deviceWasDisconnected'), `ID: ${deviceId}`);
setBleDevices((prev) => prev.filter((el) => el.id !== deviceId));
subscription.remove();
});
}
};
const disconnectFromDevice = (id: string) => {
bleManagerDevice.cancelDeviceConnection(id);
setBleDevices((prev) => prev.filter((el) => el.id !== id));
};
const stopScanning = () => {
bleManagerDevice.stopDeviceScan();
};
bleManagerDevice.startDeviceScan(undefined, null, async (error, device) => {
if (error) {
Alert.alert(error.message);
return navigation.goBack();
}
if (
device &&
[device.localName, device.name].some((el) => el?.startsWith('BLE-MY-DEVICE-123'))
) {
await stopScanning();
try {
const isConnected = await device.isConnected(); // check if device was previously connected
const deviceConnection = isConnected
? device
: await bleManagerDevice.connectToDevice(device.id, {
timeout: 15000,
});
setBleDevices((prev) =>
!prev.find((el) => el.id === deviceConnection.id) ? [...prev, deviceConnection] : prev
);
await deviceConnection.discoverAllServicesAndCharacteristics();
stopScanning();
!isConnected && onDeviceDisconnected(deviceConnection);
return navigation.replace(Routes.MainStack, {
screen: Routes.ReadCharacteristicScreen,
params: { deviceId: device.id },
});
} catch (e) {
stopScanning();
if (await device.isConnected()) disconnectFromDevice(device.id);
Alert.alert(JSON.stringify(e, Object.getOwnPropertyNames(e)));
return navigation.goBack();
}
}
});
} else {
Alert.alert(
translate('ui.bluetooth.notEnoughPermissions'),
translate('ui.bluetooth.notEnoughPermissionsDescription')
);
return navigation.goBack();
}
});
};
type VoidCallback = (result: boolean) => void;
const requestPermissions = async (cb: VoidCallback) => {
if (Platform.OS === 'android') {
const apiLevel = await DeviceInfo.getApiLevel();
if (apiLevel < 31) {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
{
title: 'Location Permission',
message: 'Bluetooth Low Energy requires Location',
buttonNeutral: 'Ask Later',
buttonNegative: 'Cancel',
buttonPositive: 'OK',
}
);
cb(granted === PermissionsAndroid.RESULTS.GRANTED);
} else {
const result = await requestMultiple([
PERMISSIONS.ANDROID.BLUETOOTH_SCAN,
PERMISSIONS.ANDROID.BLUETOOTH_CONNECT,
PERMISSIONS.ANDROID.ACCESS_FINE_LOCATION,
]);
const isGranted =
result['android.permission.BLUETOOTH_CONNECT'] === PermissionsAndroid.RESULTS.GRANTED &&
result['android.permission.BLUETOOTH_SCAN'] === PermissionsAndroid.RESULTS.GRANTED &&
result['android.permission.ACCESS_FINE_LOCATION'] === PermissionsAndroid.RESULTS.GRANTED;
cb(isGranted);
}
} else {
cb(true);
}
};
useInterval(
async () => {
handleGetBleData();
},
!isLoading ? 1000 : null
);
const handleGetBleData = async () => {
if (device?.id) {
try {
setIsLoading(true);
setErrors([]);
if (await device.isConnected()) {
const lastUpdatedCharacteristic = await device.readCharacteristicForService(
'00000000-0000-0000-0000-123400000000',
'00000000-0000-4000-0000-123456789012'
);
console.log(lastUpdatedCharacteristic);
}
} catch (error) {
setErrors([error.message]);
} finally {
setIsLoading(false);
}
}
}; Logs from 2.0.3 (working version)
Logs from 3.1.2 (auto disconnect)
Tested on device OPPO Reno5 Lite (CPH2205), Android 13 |
timeout paramter works in 3.1.2 and doesn't work on 2.0.3 and you are declared that the device should be disconnected after 15 seconds and it is (29.035 - 13.778 = 15.257). So should it be autodisconnected or not? |
@dominik-czupryna-withintent |
Okay, I understood, I was looking for the error in the wrong place. Bug confirmed. We're working on it. |
As stated by @macksal above, removing the timeout to the connection is a functional workaround and the connection doesn't drop. |
The problem persist in the new version 3.2.0 @dominik-czupryna-withintent , and removing the timeout is not a workaround for me. We found that issue in Android 14. In Android 12 is working perfect. This is the error I'm receiving now:
|
when this pr will be released? |
This continues to be an issue in version 3.2.0. |
@alex-freeaim the pr is merged but no new release was made after the merge 😐 |
@adumat @alex-freeaim you can use the latest version pointing to the master branch |
Okay, I made a fix already that I tested on android and ios, so I can wait until the next release. Below is my fix, where it will time out after 10 seconds.
|
Prerequisites
Question
I've upgrade from v2 to v3. Now while connecting from an Android phone the BLE device disconnect 5 seconds without any other error. On the event "onDeviceDisconnected" error is equal to null.
The documentation said that this is because of a call to cancelConnection but no call is made.
Using exactly the same code with version 2 works all fine so I asking for hint to help me to find the problem with connection. It's has to be a changed in the library.
In JavaScript I doesn't have any log information. This is the phone logcat
The text was updated successfully, but these errors were encountered: