From c7a1a0c38d6f4c1497e10464a058e213a2dd3a5e Mon Sep 17 00:00:00 2001 From: Aleksander Nowakowski Date: Mon, 13 Mar 2017 16:59:06 +0100 Subject: [PATCH] Stability improvement: Delaying BLE operations after Bluetooth enabled --- .../nrftoolbox/profile/BleProfileService.java | 9 +++++ .../BleMulticonnectProfileService.java | 19 +++++++++- .../proximity/ProximityService.java | 38 ++++++++++++++----- 3 files changed, 55 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileService.java index 1edb01a9..d42ac701 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileService.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileService.java @@ -209,6 +209,14 @@ public abstract class BleProfileService extends Service implements BleManagerCal } } + /** + * Returns a handler that is created in onCreate(). + * The handler may be used to postpone execution of some operations or to run them in UI thread. + */ + protected Handler getHandler() { + return mHandler; + } + /** * Returns the binder implementation. This must return class implementing the additional manager interface that may be used in the bound activity. * @@ -361,6 +369,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal mBluetoothDevice = null; mDeviceName = null; mLogSession = null; + mHandler = null; } /** diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileService.java index f1d7aef0..45f58529 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileService.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileService.java @@ -88,7 +88,15 @@ public abstract class BleMulticonnectProfileService extends Service implements B switch (state) { case BluetoothAdapter.STATE_ON: - onBluetoothEnabled(); + // On older phones (tested on Nexus 4 with Android 5.0.1) the Bluetooth requires some time + // after it has been enabled before some operations can start. Starting the GATT server here + // without a delay is very likely to cause a DeadObjectException from BluetoothManager#openGattServer(...). + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + onBluetoothEnabled(); + } + }, 600); break; case BluetoothAdapter.STATE_TURNING_OFF: case BluetoothAdapter.STATE_OFF: @@ -224,6 +232,14 @@ public abstract class BleMulticonnectProfileService extends Service implements B } } + /** + * Returns a handler that is created in onCreate(). + * The handler may be used to postpone execution of some operations or to run them in UI thread. + */ + protected Handler getHandler() { + return mHandler; + } + /** * Returns the binder implementation. This must return class implementing the additional manager interface that may be used in the bound activity. * @@ -360,6 +376,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B public void onDestroy() { super.onDestroy(); onServiceStopped(); + mHandler = null; } /** diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityService.java index d8e0a59f..8999cf92 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityService.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityService.java @@ -73,6 +73,9 @@ public class ProximityService extends BleMulticonnectProfileService implements P */ private List mDevicesWithAlarm; + private int mAttempt; + private final static int MAX_ATTEMPTS = 1; + /** * This local binder is an interface for the bonded activity to operate with the proximity sensor */ @@ -170,18 +173,33 @@ public class ProximityService extends BleMulticonnectProfileService implements P @Override protected void onBluetoothEnabled() { - // Start the GATT Server only if Bluetooth is enabled - mServerManager.openGattServer(this, new ProximityServerManager.OnServerOpenCallback() { + mAttempt = 0; + getHandler().post(new Runnable() { @Override - public void onGattServerOpen() { - // We are now ready to reconnect devices - ProximityService.super.onBluetoothEnabled(); - } + public void run() { + final Runnable that = this; + // Start the GATT Server only if Bluetooth is enabled + mServerManager.openGattServer(ProximityService.this, new ProximityServerManager.OnServerOpenCallback() { + @Override + public void onGattServerOpen() { + // We are now ready to reconnect devices + ProximityService.super.onBluetoothEnabled(); + } - @Override - public void onGattServerFailed(final int error) { - mServerManager.closeGattServer(); - showToast(getString(R.string.proximity_server_error, error)); + @Override + public void onGattServerFailed(final int error) { + mServerManager.closeGattServer(); + + if (mAttempt < MAX_ATTEMPTS) { + mAttempt++; + getHandler().postDelayed(that, 2000); + } else { + showToast(getString(R.string.proximity_server_error, error)); + // GATT server failed to start, but we may connect as a client + ProximityService.super.onBluetoothEnabled(); + } + } + }); } }); }