flutter_reactive_ble
flutter_reactive_ble copied to clipboard
Not Able To Disconnect When BLE Device Is Disconnected/Switched Off Manually
Bug
When I try connect to a BLE Device with 'flutterReactiveBle.connectTo()' after manually switching off the BLE device, the code stays in the 'connecting' state. Any other BLE device is also not connecting after this. Note that, I am calling 'openStream?.cancel()' for disconnection before calling flutterReactiveBle.connectTo().
To Reproduce
- Connect to one BLE device with
connectTo()
. This will work. - Switch off that BLE.
- Again connect using
**connectTo()**
. Connection state stream will get stuck at 'DeviceConnectionState.Connecting' for current or any other BLE device.
Expected behavior Current BLE stream should produce DeviceConnectionState.Disconnected state and app should be able to connect to any other BLE and the connection state stream should produce a DeviceConnectionState.Connected state.
Smartphone / tablet
- Samsung M32
- Android 11
- Reactive BLE 5.0.2
Code Snippet
void connectToBLEDevice(String connectionMACID)async{
if (isConnectionInProgress == false) {
await Future.delayed(Duration(milliseconds: 1));
await openStreamSubs?.cancel();
Stream<ConnectionStateUpdate>? connectStream =
flutterReactiveBle.connectToDevice(
id: connectionMACID.trim(),
servicesWithCharacteristicsToDiscover:
getDiscoverCharacteristics(),
connectionTimeout: Duration(milliseconds: 3500));
openStreamSubs = connectStream.listen(
(state) async {
if (state.connectionState == DeviceConnectionState.connecting) {
connectingCheckTimerOpen?.cancel();
connectingCheckTimerOpen =
Timer(Duration(milliseconds: 3500), () async {
isBLEConnected = false;
isConnectionInProgress = false;
await openStreamSubs?.cancel();
});
} else if (state.connectionState == DeviceConnectionState.connected) {
isBLEConnected = true;
connectingCheckTimerOpen?.cancel();
//? proceed write operation
final characteristic =
getWriteCharacteristic(connectionMACID.trim());
flutterReactiveBle
.writeCharacteristicWithResponse(characteristic,
value: CommandStructures.writeCommand)
.then((value) async {
isLockOpenWriteSuccess = true;
openLockRetryCount = 0;
isConnectionInProgress = false;
await openStreamSubs?.cancel();
isBLEConnected = false;
connectingCheckTimerOpen?.cancel();
}, onError: (err, stackTrace) async {
isLockOpenWriteSuccess = false;
isConnectionInProgress = false;
await openStreamSubs?.cancel();
isLockConnectedOpen = false;
connectingCheckTimerOpen?.cancel();
});
} else if (state.connectionState ==
DeviceConnectionState.disconnected) {
isBLEConnected = false;
connectingCheckTimerOpen?.cancel();
isConnectionInProgress = false;
await openStreamSubs?.cancel();
},
onError: (err) async {
await openStreamSubs?.cancel();
isConnectionInProgress = false;
},
);
} else {
print('Connection In Progress');
}
}
This looks like something wrong with your code, can you reproduce this in example app?
I can confirm this is happening with example app also. After I manually switch off the BLE device, connection state is stuck at 'Connecting'. Also when I tried to connect with another BLE device which is switched on, connection state is again stuck at 'Connecting'.
Expected behaviour is if it can't connect it should go to state of 'Disconnected' after some time.
Have a look at attached screenshot.
Any suggestions? Same issue here.
Encountering the same issue also :)
I have similar issue too with iOS 15 (not tested Android) When I tried to lose device connection dispose function give error.
@override void dispose() { subscribeStream?.cancel(); super.dispose(); }
Error is:
flutter: Error unsubscribing from notifications: PlatformException(reactive_ble_mobile.Central.(unknown context at $104f8ba50).Failure:1, The operation couldn’t be completed. (reactive_ble_mobile.Central.(unknown context at $104f8ba50).Failure error 1.), {}, null) reactive_ble_mobile/ConnectTaskController.swift:16: Assertion failed reactive_ble_mobile/ConnectTaskController.swift:16: Assertion failed
- thread #1, queue = 'com.apple.main-thread', stop reason = Assertion failed
frame #0: 0x00000001b9df2458 libswiftCore.dylib
_swift_runtime_on_report libswiftCore.dylib
_swift_runtime_on_report: -> 0x1b9df2458 <+0>: ret
libswiftCore.dylib_swift_reportToDebugger: 0x1b9df245c <+0>: b 0x1b9df2458 ; _swift_runtime_on_report libswiftCore.dylib
_swift_shouldReportFatalErrorsToDebugger: 0x1b9df2460 <+0>: adrp x8, 334840 0x1b9df2464 <+4>: ldrb w0, [x8, #0x65c] Target 0: (Runner) stopped. Lost connection to device.
I have the same problem here. I have two BLE boxes. When I connect to one at first, it works fine. When I detect the other one and then connect to it (and both are on) I can also connect to the other one. However, when I turn off one of them, quit the application and then try to reconnect to one of the two boxes (the only one that remains on), I get a "connecting" status that remains without ever connecting...
The same issue, but Stream<ConnectionStateUpdate>
even has no cancel()
member now (for some reason?), so I even can't cancel the subscription.
similar issue. after Bluetooth device is powered off, no DeviceConnectionState.disconnected is received.
Any update on this issue guys ? I am facing this issue still
I was able solved this by using a state listener, I am using Riverpod.
add this function
void connectingListener() {
ref.listen(connectionStateUpdateStateprovider, (previous, next) {
if (ref.watch(connectionStateUpdateStateprovider).connectionState ==
DeviceConnectionState.connecting) {
Future.delayed(Duration(seconds: 5), () {
if (ref.watch(connectionStateUpdateStateprovider).connectionState ==
DeviceConnectionState.connecting) {
ref
.watch(connectorProvider)
.disconnect(onConnectingDevice.id, onConnectingDevice.name);
connectFailAlert();
}
});
}
});
}
then place connectingListener(); inside build
The code is listening the change of DeviceConnectionState, then if it still connecting after a delay (I use 5 seconds here) then cancel the connecting (using disconnect method). The method is a little bit bloated but it is useful.