onConnectionStateChange callback passed null gatt parameter
JSmyth886 opened this issue · 10 comments
When connecting my devices there is an intermittent issue with the onConnectionStateChange
callback being passed a null value to the gatt parameter. I think the problem may lie in my implementation of handling reconnection after the app is closed or killed and reopened, as I think it may be trying to connect to the same device multiple times (something I should fix).
However I do think there are somethings that could be added/updated in the library to help mitigate this issue:
- Should the
BluetoothGattCallback
implementation expect the BluetoothGatt parameter be non-null when this is not the case in the Java abstract? - In the areas calling the
onConnectionStateChange
callback can thebluetoothGatt
variable be unwrapped via a?.let {}
call or some other guard clause to ensureonConnectionStateChange
is not invoked with a null value?
See stack trace below:
E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-8
Process: com.jsmyth.bletest, PID: 26842
java.lang.NullPointerException: Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkNotNullParameter, parameter gatt
at com.welie.blessed.BluetoothPeripheral$bluetoothGattCallback$1.onConnectionStateChange(Unknown Source:2)
at com.welie.blessed.BluetoothPeripheral$startConnectionTimer$1$1.invokeSuspend(BluetoothPeripheral.kt:1518)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:39)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
Hmmm, I have never ever seen this. It doesn't make much sense if bluetoothGatt
ever was null....because then I wouldn't be able to do any additional gatt operations...
The only thing I can imagine is that there is a race condition between a connect and disconnect operation because the disconnect will nullify the bluetoothGatt
variable. I see you are running the code in a coroutine that is being resumed....
Could it be you are causing this yourself?
Another question, does it happen when you are doing a connect? Or when a disconnect happens? Can't see it from the logs...
I have been checking the code and I see a possible improvement in my code. I will add another check in the method startConnectionTimer
and some other methods to make sure there is a valid non-null reference.
But the only way it can become null is when connecting and disconnecting are happening very fast after each other....so you probably may want to check your code as well.
Released 2.2.3
Please check if this fixes your issue
Any update? Does the new release fix the issue?
Sorry was on holidays and away from any internet.
To answer these messages in order:
- Yes I do think my connection code could be causing an issue, I think it may have something to do with multiple connections being attempted to the same device (I think I need some protection in my code to catch that)
- How I think this manifests, is on connection to the same device multiple times (again more protection around my connection code should mitigate this). So the same device gets the connection attempt multiple times, one connection attempt succeeds, the other fails and is returned a null gatt in the process (maybe?)
- I'll do some rework to my connection/disconnection code and see what I can do to stop this from happening
4/5. Will update the library today and do some testing to see if I still see the issue.
Thanks so much for the fast response and sorry for not responding until now
I'm an idiot. I just realised that I'm using the blessed-android-coroutines version of the library and I've posted this issue with the original java version. So sorry about that. Feel free to close this off whilst I fork and test the fix in the coroutines version.
Would you like me to upstream this particular fix into the blessed-android-coroutines version?
If I'm seeing the changes correctly it's the if
check around the onConnectionStateChange
callback within startConnectionTimer
. Was there anything else added to v2.2.3 that you'd like ported to the coroutines version?
oooooh, right. I guess I should have realized as well....
In the coroutines version the code is slightly different. Mainly because I didn't carry over some improvements I did on the Java version.
So the the coroutines code, this issues is probably caused by the fact that the connection timer isn't being cancelled. And that's because the connection state management works slightly different.
Let me do some re-alignment because it is more than just adding one check..... I'll try to do this soon
I just released a new version with fixes: 0.3.2 . So your PR is not needed anymore...
Can you give it a try?
No it's completely my fault, in too much of a rush before holidays 😅
Have given 0.3.2 a try with a number of phones and bluetooth devices. Working without any issues so far, feels really stable. (Note: I haven't made any major changes to my own connection/disconnection code, though I will still check it out)
Thanks again for the quick response. If you want some help with any minor updates to the library I'm happy to help or even test things.