diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java index 214349c0..9020d883 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/GBApplication.java @@ -34,6 +34,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs; import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; @@ -57,6 +58,7 @@ public class GBApplication extends Application { private static LimitedQueue mIDSenderLookup = new LimitedQueue(16); private static Appender fileLogger; private static Prefs prefs; + private static GBPrefs gbPrefs; public static final String ACTION_QUIT = "nodomain.freeyourgadget.gadgetbridge.gbapplication.action.quit"; @@ -91,6 +93,7 @@ public class GBApplication extends Application { sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context); prefs = new Prefs(sharedPrefs); + gbPrefs = new GBPrefs(prefs); // don't do anything here before we set up logging, otherwise // slf4j may be implicitly initialized before we properly configured it. @@ -366,4 +369,8 @@ public class GBApplication extends Application { public static Prefs getPrefs() { return prefs; } + + public static GBPrefs getGBPrefs() { + return gbPrefs; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java index 683829c5..21d7965b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/AbstractDeviceSupport.java @@ -59,6 +59,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { protected GBDevice gbDevice; private BluetoothAdapter btAdapter; private Context context; + private boolean autoReconnect; public void setContext(GBDevice gbDevice, BluetoothAdapter btAdapter, Context context) { this.gbDevice = gbDevice; @@ -81,6 +82,16 @@ public abstract class AbstractDeviceSupport implements DeviceSupport { return gbDevice.isInitialized(); } + @Override + public void setAutoReconnect(boolean enable) { + autoReconnect = enable; + } + + @Override + public boolean getAutoReconnect() { + return autoReconnect; + } + @Override public GBDevice getDevice() { return gbDevice; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java index b5b4b7fb..ee681cad 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -6,6 +6,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; +import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.os.IBinder; @@ -37,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.GB; +import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_CONFIGURE; @@ -88,7 +90,7 @@ import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_NOT import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_PERFORM_PAIR; import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI; -public class DeviceCommunicationService extends Service { +public class DeviceCommunicationService extends Service implements SharedPreferences.OnSharedPreferenceChangeListener { private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class); private boolean mStarted = false; @@ -130,6 +132,9 @@ public class DeviceCommunicationService extends Service { super.onCreate(); LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(GBDevice.ACTION_DEVICE_CHANGED)); mFactory = new DeviceSupportFactory(this); + + Prefs prefs = GBApplication.getPrefs(); + prefs.getPreferences().registerOnSharedPreferenceChangeListener(this); } @Override @@ -190,8 +195,10 @@ public class DeviceCommunicationService extends Service { btDeviceAddress = gbDevice.getAddress(); } + boolean autoReconnect = GBPrefs.AUTO_RECONNECT_DEFAULT; if (prefs != null) { prefs.getPreferences().edit().putString("last_device_address", btDeviceAddress).apply(); + autoReconnect = prefs.getPreferences().getBoolean(GBPrefs.AUTO_RECONNECT, GBPrefs.AUTO_RECONNECT_DEFAULT); } if (gbDevice != null && !isConnecting() && !isConnected()) { @@ -203,6 +210,7 @@ public class DeviceCommunicationService extends Service { if (pair) { deviceSupport.pair(); } else { + deviceSupport.setAutoReconnect(autoReconnect); deviceSupport.connect(); } } else { @@ -478,6 +486,8 @@ public class DeviceCommunicationService extends Service { @Override public void onDestroy() { + GBApplication.getPrefs().getPreferences().unregisterOnSharedPreferenceChangeListener(this); + LOG.debug("DeviceCommunicationService is being destroyed"); super.onDestroy(); @@ -514,4 +524,14 @@ public class DeviceCommunicationService extends Service { return name; } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (GBPrefs.AUTO_RECONNECT.equals(key)) { + boolean autoReconnect = GBApplication.getGBPrefs().getAutoReconnect(); + if (mDeviceSupport != null) { + mDeviceSupport.setAutoReconnect(autoReconnect); + } + } + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupport.java index bce4e64b..61646c54 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceSupport.java @@ -62,6 +62,20 @@ public interface DeviceSupport extends EventHandler { */ boolean useAutoConnect(); + /** + * Configures this instance to automatically attempt to reconnect after a connection loss. + * How, how long, or how often is up to the implementation. + * Note that tome implementations may not support automatic reconnection at all. + * @param enable + */ + void setAutoReconnect(boolean enable); + + /** + * Returns whether this instance to configured to automatically attempt to reconnect after a + * connection loss. + */ + boolean getAutoReconnect(); + /** * Attempts to pair and connect this device with the gadget device. Success * will be reported via a device change Intent. diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java index 2a0de20e..8047aad6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/ServiceDeviceSupport.java @@ -56,6 +56,16 @@ public class ServiceDeviceSupport implements DeviceSupport { return delegate.connect(); } + @Override + public void setAutoReconnect(boolean enable) { + delegate.setAutoReconnect(enable); + } + + @Override + public boolean getAutoReconnect() { + return delegate.getAutoReconnect(); + } + @Override public void dispose() { delegate.dispose(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java index 6361431a..04179458 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/AbstractBTLEDeviceSupport.java @@ -42,10 +42,19 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im public boolean connect() { if (mQueue == null) { mQueue = new BtLEQueue(getBluetoothAdapter(), getDevice(), this, getContext()); + mQueue.setAutoReconnect(getAutoReconnect()); } return mQueue.connect(); } + @Override + public void setAutoReconnect(boolean enable) { + super.setAutoReconnect(enable); + if (mQueue != null) { + mQueue.setAutoReconnect(enable); + } + } + /** * Subclasses should populate the given builder to initialize the device (if necessary). * diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java index 71d1beaf..f6009435 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/btle/BtLEQueue.java @@ -34,12 +34,6 @@ public final class BtLEQueue { private final GBDevice mGbDevice; private final BluetoothAdapter mBluetoothAdapter; private BluetoothGatt mBluetoothGatt; - /** - * When an automatic reconnect was attempted after a connection breakdown (error) - */ - private long lastReconnectTime = System.currentTimeMillis(); - - private static final long MIN_MILLIS_BEFORE_RECONNECT = 1000 * 60 * 5; // 5 minutes private final BlockingQueue mTransactions = new LinkedBlockingQueue<>(); private volatile boolean mDisposed; @@ -51,6 +45,7 @@ public final class BtLEQueue { private CountDownLatch mConnectionLatch; private BluetoothGattCharacteristic mWaitCharacteristic; private final InternalGattCallback internalGattCallback; + private boolean mAutoReconnect; private Thread dispatchThread = new Thread("GadgetBridge GATT Dispatcher") { @@ -130,6 +125,10 @@ public final class BtLEQueue { dispatchThread.start(); } + public void setAutoReconnect(boolean enable) { + mAutoReconnect = enable; + } + protected boolean isConnected() { return mGbDevice.isConnected(); } @@ -222,11 +221,9 @@ public final class BtLEQueue { * @return true if a reconnection attempt was made, or false otherwise */ private boolean maybeReconnect() { - long currentTime = System.currentTimeMillis(); - if (currentTime - lastReconnectTime >= MIN_MILLIS_BEFORE_RECONNECT) { - LOG.info("Automatic reconnection attempt..."); - lastReconnectTime = currentTime; - return connect(); + if (mAutoReconnect && mBluetoothGatt != null) { + LOG.info("Enabling automatic ble reconnect..."); + return mBluetoothGatt.connect(); } return false; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java index 482e0d5a..d2265027 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleIoThread.java @@ -365,7 +365,7 @@ public class PebbleIoThread extends GBDeviceIoThread { LOG.info(e.getMessage()); mIsConnected = false; int reconnectAttempts = prefs.getInt("pebble_reconnect_attempts", 10); - if (reconnectAttempts > 0) { + if (GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) { gbDevice.setState(GBDevice.State.CONNECTING); gbDevice.sendDeviceUpdateIntent(getContext()); int delaySeconds = 1; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GBPrefs.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GBPrefs.java new file mode 100644 index 00000000..e895919d --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/util/GBPrefs.java @@ -0,0 +1,16 @@ +package nodomain.freeyourgadget.gadgetbridge.util; + +public class GBPrefs { + + public static final String AUTO_RECONNECT = "general_autocreconnect"; + public static boolean AUTO_RECONNECT_DEFAULT = true; + private final Prefs mPrefs; + + public GBPrefs(Prefs prefs) { + mPrefs = prefs; + } + + public boolean getAutoReconnect() { + return mPrefs.getBoolean(AUTO_RECONNECT, AUTO_RECONNECT_DEFAULT); + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1df50a7a..1ec538ec 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -244,5 +244,6 @@ Firmware not sent Heart Rate Heart Rate + Reconnect automatically diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index dad3bc0b..4def8d01 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -7,6 +7,10 @@ android:defaultValue="false" android:key="general_autoconnectonbluetooth" android:title="@string/pref_title_general_autoconnectonbluetooth" /> +