mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-06-05 21:49:48 +02:00
Make automatic reconnect after connection loss configurable #293
Mi Band: automatically reconnect when the device is back in range Also: #89
This commit is contained in:
@@ -34,6 +34,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
import nodomain.freeyourgadget.gadgetbridge.model.DeviceService;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
|
import nodomain.freeyourgadget.gadgetbridge.util.LimitedQueue;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
|
|
||||||
@@ -57,6 +58,7 @@ public class GBApplication extends Application {
|
|||||||
private static LimitedQueue mIDSenderLookup = new LimitedQueue(16);
|
private static LimitedQueue mIDSenderLookup = new LimitedQueue(16);
|
||||||
private static Appender<ILoggingEvent> fileLogger;
|
private static Appender<ILoggingEvent> fileLogger;
|
||||||
private static Prefs prefs;
|
private static Prefs prefs;
|
||||||
|
private static GBPrefs gbPrefs;
|
||||||
|
|
||||||
public static final String ACTION_QUIT
|
public static final String ACTION_QUIT
|
||||||
= "nodomain.freeyourgadget.gadgetbridge.gbapplication.action.quit";
|
= "nodomain.freeyourgadget.gadgetbridge.gbapplication.action.quit";
|
||||||
@@ -91,6 +93,7 @@ public class GBApplication extends Application {
|
|||||||
|
|
||||||
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
prefs = new Prefs(sharedPrefs);
|
prefs = new Prefs(sharedPrefs);
|
||||||
|
gbPrefs = new GBPrefs(prefs);
|
||||||
|
|
||||||
// don't do anything here before we set up logging, otherwise
|
// don't do anything here before we set up logging, otherwise
|
||||||
// slf4j may be implicitly initialized before we properly configured it.
|
// slf4j may be implicitly initialized before we properly configured it.
|
||||||
@@ -366,4 +369,8 @@ public class GBApplication extends Application {
|
|||||||
public static Prefs getPrefs() {
|
public static Prefs getPrefs() {
|
||||||
return prefs;
|
return prefs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GBPrefs getGBPrefs() {
|
||||||
|
return gbPrefs;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -59,6 +59,7 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
|||||||
protected GBDevice gbDevice;
|
protected GBDevice gbDevice;
|
||||||
private BluetoothAdapter btAdapter;
|
private BluetoothAdapter btAdapter;
|
||||||
private Context context;
|
private Context context;
|
||||||
|
private boolean autoReconnect;
|
||||||
|
|
||||||
public void setContext(GBDevice gbDevice, BluetoothAdapter btAdapter, Context context) {
|
public void setContext(GBDevice gbDevice, BluetoothAdapter btAdapter, Context context) {
|
||||||
this.gbDevice = gbDevice;
|
this.gbDevice = gbDevice;
|
||||||
@@ -81,6 +82,16 @@ public abstract class AbstractDeviceSupport implements DeviceSupport {
|
|||||||
return gbDevice.isInitialized();
|
return gbDevice.isInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAutoReconnect(boolean enable) {
|
||||||
|
autoReconnect = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getAutoReconnect() {
|
||||||
|
return autoReconnect;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GBDevice getDevice() {
|
public GBDevice getDevice() {
|
||||||
return gbDevice;
|
return gbDevice;
|
||||||
|
@@ -6,6 +6,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
@@ -37,6 +38,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
import nodomain.freeyourgadget.gadgetbridge.model.NotificationType;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||||
|
import nodomain.freeyourgadget.gadgetbridge.util.GBPrefs;
|
||||||
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
|
||||||
|
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.ACTION_APP_CONFIGURE;
|
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_PERFORM_PAIR;
|
||||||
import static nodomain.freeyourgadget.gadgetbridge.model.DeviceService.EXTRA_URI;
|
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 static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class);
|
||||||
|
|
||||||
private boolean mStarted = false;
|
private boolean mStarted = false;
|
||||||
@@ -130,6 +132,9 @@ public class DeviceCommunicationService extends Service {
|
|||||||
super.onCreate();
|
super.onCreate();
|
||||||
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(GBDevice.ACTION_DEVICE_CHANGED));
|
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, new IntentFilter(GBDevice.ACTION_DEVICE_CHANGED));
|
||||||
mFactory = new DeviceSupportFactory(this);
|
mFactory = new DeviceSupportFactory(this);
|
||||||
|
|
||||||
|
Prefs prefs = GBApplication.getPrefs();
|
||||||
|
prefs.getPreferences().registerOnSharedPreferenceChangeListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -190,8 +195,10 @@ public class DeviceCommunicationService extends Service {
|
|||||||
btDeviceAddress = gbDevice.getAddress();
|
btDeviceAddress = gbDevice.getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean autoReconnect = GBPrefs.AUTO_RECONNECT_DEFAULT;
|
||||||
if (prefs != null) {
|
if (prefs != null) {
|
||||||
prefs.getPreferences().edit().putString("last_device_address", btDeviceAddress).apply();
|
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()) {
|
if (gbDevice != null && !isConnecting() && !isConnected()) {
|
||||||
@@ -203,6 +210,7 @@ public class DeviceCommunicationService extends Service {
|
|||||||
if (pair) {
|
if (pair) {
|
||||||
deviceSupport.pair();
|
deviceSupport.pair();
|
||||||
} else {
|
} else {
|
||||||
|
deviceSupport.setAutoReconnect(autoReconnect);
|
||||||
deviceSupport.connect();
|
deviceSupport.connect();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -478,6 +486,8 @@ public class DeviceCommunicationService extends Service {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
|
GBApplication.getPrefs().getPreferences().unregisterOnSharedPreferenceChangeListener(this);
|
||||||
|
|
||||||
LOG.debug("DeviceCommunicationService is being destroyed");
|
LOG.debug("DeviceCommunicationService is being destroyed");
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
|
|
||||||
@@ -514,4 +524,14 @@ public class DeviceCommunicationService extends Service {
|
|||||||
|
|
||||||
return name;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -62,6 +62,20 @@ public interface DeviceSupport extends EventHandler {
|
|||||||
*/
|
*/
|
||||||
boolean useAutoConnect();
|
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
|
* Attempts to pair and connect this device with the gadget device. Success
|
||||||
* will be reported via a device change Intent.
|
* will be reported via a device change Intent.
|
||||||
|
@@ -56,6 +56,16 @@ public class ServiceDeviceSupport implements DeviceSupport {
|
|||||||
return delegate.connect();
|
return delegate.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAutoReconnect(boolean enable) {
|
||||||
|
delegate.setAutoReconnect(enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getAutoReconnect() {
|
||||||
|
return delegate.getAutoReconnect();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
delegate.dispose();
|
delegate.dispose();
|
||||||
|
@@ -42,10 +42,19 @@ public abstract class AbstractBTLEDeviceSupport extends AbstractDeviceSupport im
|
|||||||
public boolean connect() {
|
public boolean connect() {
|
||||||
if (mQueue == null) {
|
if (mQueue == null) {
|
||||||
mQueue = new BtLEQueue(getBluetoothAdapter(), getDevice(), this, getContext());
|
mQueue = new BtLEQueue(getBluetoothAdapter(), getDevice(), this, getContext());
|
||||||
|
mQueue.setAutoReconnect(getAutoReconnect());
|
||||||
}
|
}
|
||||||
return mQueue.connect();
|
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).
|
* Subclasses should populate the given builder to initialize the device (if necessary).
|
||||||
*
|
*
|
||||||
|
@@ -34,12 +34,6 @@ public final class BtLEQueue {
|
|||||||
private final GBDevice mGbDevice;
|
private final GBDevice mGbDevice;
|
||||||
private final BluetoothAdapter mBluetoothAdapter;
|
private final BluetoothAdapter mBluetoothAdapter;
|
||||||
private BluetoothGatt mBluetoothGatt;
|
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<Transaction> mTransactions = new LinkedBlockingQueue<>();
|
private final BlockingQueue<Transaction> mTransactions = new LinkedBlockingQueue<>();
|
||||||
private volatile boolean mDisposed;
|
private volatile boolean mDisposed;
|
||||||
@@ -51,6 +45,7 @@ public final class BtLEQueue {
|
|||||||
private CountDownLatch mConnectionLatch;
|
private CountDownLatch mConnectionLatch;
|
||||||
private BluetoothGattCharacteristic mWaitCharacteristic;
|
private BluetoothGattCharacteristic mWaitCharacteristic;
|
||||||
private final InternalGattCallback internalGattCallback;
|
private final InternalGattCallback internalGattCallback;
|
||||||
|
private boolean mAutoReconnect;
|
||||||
|
|
||||||
private Thread dispatchThread = new Thread("GadgetBridge GATT Dispatcher") {
|
private Thread dispatchThread = new Thread("GadgetBridge GATT Dispatcher") {
|
||||||
|
|
||||||
@@ -130,6 +125,10 @@ public final class BtLEQueue {
|
|||||||
dispatchThread.start();
|
dispatchThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAutoReconnect(boolean enable) {
|
||||||
|
mAutoReconnect = enable;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean isConnected() {
|
protected boolean isConnected() {
|
||||||
return mGbDevice.isConnected();
|
return mGbDevice.isConnected();
|
||||||
}
|
}
|
||||||
@@ -222,11 +221,9 @@ public final class BtLEQueue {
|
|||||||
* @return true if a reconnection attempt was made, or false otherwise
|
* @return true if a reconnection attempt was made, or false otherwise
|
||||||
*/
|
*/
|
||||||
private boolean maybeReconnect() {
|
private boolean maybeReconnect() {
|
||||||
long currentTime = System.currentTimeMillis();
|
if (mAutoReconnect && mBluetoothGatt != null) {
|
||||||
if (currentTime - lastReconnectTime >= MIN_MILLIS_BEFORE_RECONNECT) {
|
LOG.info("Enabling automatic ble reconnect...");
|
||||||
LOG.info("Automatic reconnection attempt...");
|
return mBluetoothGatt.connect();
|
||||||
lastReconnectTime = currentTime;
|
|
||||||
return connect();
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@@ -365,7 +365,7 @@ public class PebbleIoThread extends GBDeviceIoThread {
|
|||||||
LOG.info(e.getMessage());
|
LOG.info(e.getMessage());
|
||||||
mIsConnected = false;
|
mIsConnected = false;
|
||||||
int reconnectAttempts = prefs.getInt("pebble_reconnect_attempts", 10);
|
int reconnectAttempts = prefs.getInt("pebble_reconnect_attempts", 10);
|
||||||
if (reconnectAttempts > 0) {
|
if (GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) {
|
||||||
gbDevice.setState(GBDevice.State.CONNECTING);
|
gbDevice.setState(GBDevice.State.CONNECTING);
|
||||||
gbDevice.sendDeviceUpdateIntent(getContext());
|
gbDevice.sendDeviceUpdateIntent(getContext());
|
||||||
int delaySeconds = 1;
|
int delaySeconds = 1;
|
||||||
|
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
@@ -244,5 +244,6 @@
|
|||||||
<string name="updatefirmwareoperation_firmware_not_sent">Firmware not sent</string>
|
<string name="updatefirmwareoperation_firmware_not_sent">Firmware not sent</string>
|
||||||
<string name="charts_legend_heartrate">Heart Rate</string>
|
<string name="charts_legend_heartrate">Heart Rate</string>
|
||||||
<string name="live_activity_heart_rate">Heart Rate</string>
|
<string name="live_activity_heart_rate">Heart Rate</string>
|
||||||
|
<string name="pref_title_general_autocreonnect">Reconnect automatically</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@@ -7,6 +7,10 @@
|
|||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="general_autoconnectonbluetooth"
|
android:key="general_autoconnectonbluetooth"
|
||||||
android:title="@string/pref_title_general_autoconnectonbluetooth" />
|
android:title="@string/pref_title_general_autoconnectonbluetooth" />
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:defaultValue="false"
|
||||||
|
android:key="general_autocreconnect"
|
||||||
|
android:title="@string/pref_title_general_autocreonnect" />
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="default"
|
android:defaultValue="default"
|
||||||
android:key="audio_player"
|
android:key="audio_player"
|
||||||
|
@@ -5,7 +5,7 @@ buildscript {
|
|||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.0.0'
|
classpath 'com.android.tools.build:gradle:2.1.0'
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
Reference in New Issue
Block a user