restart BTLE after backgrounding
IvanSeleznevSpb opened this issue · 2 comments
IvanSeleznevSpb commented
Internal/NewNode
has a startNearby()
method that calls Bluetooth.bluetoothOn() -> Bluetooth.startServer() -> Bluetooth.tryStartServer() -> BluetoothManager.openGattServer()
.
The
startNearby()
method is called in onActivityResumed()
which causes a new BluetoothGattServer
to be created each time a new activity is opened.It works fine a few times (usually 1 or 3 times), and then
openGattServer()
starts returning null
, which results in the exception described above. Before returning null
, the openGattServer()
method runs for a long time and does it on the main thread, which causes the interface to freeze.
Bluetooth com.newnode.messenger E startServer
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.bluetooth.BluetoothGattServer.addService(android.bluetooth.BluetoothGattService)' on a null object reference
at com.clostra.newnode.internal.Bluetooth.tryStartServer(Bluetooth.java:280)
at com.clostra.newnode.internal.Bluetooth.startServer(Bluetooth.java:288)
at com.clostra.newnode.internal.Bluetooth.bluetoothOn(Bluetooth.java:142)
at com.clostra.newnode.internal.NewNode.startNearby(NewNode.java:590)
at com.clostra.newnode.internal.NewNode.onActivityResumed(NewNode.java:622)
at android.app.Application.dispatchActivityResumed(Application.java:450)
at android.app.Activity.dispatchActivityResumed(Activity.java:1482)
at android.app.Activity.onResume(Activity.java:2043)
at androidx.fragment.app.FragmentActivity.onResume(FragmentActivity.java:455)
at com.clostra.nnm.BaseActivity.onResume(BaseActivity.java:46)
at com.clostra.nnm.PassphraseRequiredActivity.onResume(PassphraseRequiredActivity.java:78)
at com.clostra.nnm.conversation.ConversationActivity.onResume(ConversationActivity.java:508)
at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1531)
at android.app.Activity.performResume(Activity.java:8734)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:5351)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:5444)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:54)
at android.app.servertransaction.ActivityTransactionItem.execute(ActivityTransactionItem.java:45)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2574)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8757)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
IvanSeleznevSpb commented
@ghazel, It looks like GattServer should be run from the main thread. Therefore, the only thing that can be done is to check before starting that server is not running. Something like this:
if (gattServer != null) {
return;
}
// run openGattServer
ghazel commented
More research is needed here. L2cap channels are also exhausted by recreating advertise/scan objects every time. In particular listenUsingInsecureL2capChannel()
.
The question is what, if anything, needs to be restarted or recreated after the app has been backgrounded for long enough that BTLE advertise/scan has stopped.