From 0d7986a5ab59e0ac474b49e5fada2ed5462f689b Mon Sep 17 00:00:00 2001 From: Andreas Shimokawa Date: Sun, 22 May 2016 01:19:28 +0200 Subject: [PATCH] Pebble: rework incoming reconnection support This is now completely generic and should work for other devices also Fixes #296 --- .../BluetoothConnectReceiver.java | 43 ++++++++++++++++ .../service/DeviceCommunicationService.java | 20 ++++++++ .../devices/pebble/PebbleIoThread.java | 49 ++++--------------- .../service/devices/pebble/PebbleSupport.java | 1 + 4 files changed, 74 insertions(+), 39 deletions(-) create mode 100644 app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/BluetoothConnectReceiver.java diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/BluetoothConnectReceiver.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/BluetoothConnectReceiver.java new file mode 100644 index 00000000..5282e7a5 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/externalevents/BluetoothConnectReceiver.java @@ -0,0 +1,43 @@ +package nodomain.freeyourgadget.gadgetbridge.externalevents; + +import android.bluetooth.BluetoothDevice; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; +import nodomain.freeyourgadget.gadgetbridge.service.DeviceCommunicationService; + +public class BluetoothConnectReceiver extends BroadcastReceiver { + + private static final Logger LOG = LoggerFactory.getLogger(DeviceCommunicationService.class); + + final DeviceCommunicationService service; + + public BluetoothConnectReceiver(DeviceCommunicationService service) { + this.service = service; + } + + @Override + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + if (!action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) { + return; + } + LOG.info("got connection attempt"); + GBDevice gbDevice = service.getGBDevice(); + if (gbDevice != null) { + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + if (device.getAddress().equals(gbDevice.getAddress())) { + LOG.info("will connect to " + gbDevice.getName()); + GBApplication.deviceService().connect(); + } else { + LOG.info("won't connect to " + device.getAddress() + "(" + device.getName() + ")"); + } + } + } +} 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 7738f40c..37d217f8 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/DeviceCommunicationService.java @@ -2,6 +2,7 @@ package nodomain.freeyourgadget.gadgetbridge.service; import android.app.NotificationManager; import android.app.Service; +import android.bluetooth.BluetoothDevice; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -24,6 +25,7 @@ import java.util.UUID; import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.externalevents.BluetoothConnectReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.K9Receiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.MusicPlaybackReceiver; import nodomain.freeyourgadget.gadgetbridge.externalevents.PebbleReceiver; @@ -105,6 +107,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere private PebbleReceiver mPebbleReceiver = null; private MusicPlaybackReceiver mMusicPlaybackReceiver = null; private TimeChangeReceiver mTimeChangeReceiver = null; + private BluetoothConnectReceiver mBlueToothConnectReceiver = null; private Random mRandom = new Random(); @@ -279,6 +282,11 @@ public class DeviceCommunicationService extends Service implements SharedPrefere } case ACTION_DISCONNECT: { mDeviceSupport.dispose(); + if (mGBDevice != null && mGBDevice.getState() == GBDevice.State.WAITING_FOR_RECONNECT) { + setReceiversEnableState(false); + mGBDevice.setState(GBDevice.State.NOT_CONNECTED); + mGBDevice.sendDeviceUpdateIntent(this); + } mDeviceSupport = null; break; } @@ -457,6 +465,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere filter.addAction("android.intent.action.TIMEZONE_CHANGED"); registerReceiver(mTimeChangeReceiver, filter); } + if (mBlueToothConnectReceiver == null) { + mBlueToothConnectReceiver = new BluetoothConnectReceiver(this); + registerReceiver(mBlueToothConnectReceiver, new IntentFilter(BluetoothDevice.ACTION_ACL_CONNECTED)); + } } else { if (mPhoneCallReceiver != null) { unregisterReceiver(mPhoneCallReceiver); @@ -482,6 +494,10 @@ public class DeviceCommunicationService extends Service implements SharedPrefere unregisterReceiver(mTimeChangeReceiver); mTimeChangeReceiver = null; } + if (mBlueToothConnectReceiver != null) { + unregisterReceiver(mBlueToothConnectReceiver); + mBlueToothConnectReceiver = null; + } } } @@ -549,4 +565,8 @@ public class DeviceCommunicationService extends Service implements SharedPrefere public GBPrefs getGBPrefs() { return GBApplication.getGBPrefs(); } + + public GBDevice getGBDevice() { + return mGBDevice; + } } 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 43b86e2f..a14fb496 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 @@ -2,7 +2,6 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.pebble; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import android.content.BroadcastReceiver; import android.content.Context; @@ -48,9 +47,6 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs; public class PebbleIoThread extends GBDeviceIoThread { private static final Logger LOG = LoggerFactory.getLogger(PebbleIoThread.class); - private static final UUID PEBBLE_UUID_RECONNECT = UUID.fromString("00000000-deca-fade-deca-deafdecacafe"); - private static final UUID PEBBLE_UUID_RECONNECT3X = UUID.fromString("a924496e-cc7c-4dff-8a9f-9a76cc2e9d50"); - public static final String PEBBLEKIT_ACTION_PEBBLE_CONNECTED = "com.getpebble.action.PEBBLE_CONNECTED"; public static final String PEBBLEKIT_ACTION_PEBBLE_DISCONNECTED = "com.getpebble.action.PEBBLE_DISCONNECTED"; public static final String PEBBLEKIT_ACTION_APP_ACK = "com.getpebble.action.app.ACK"; @@ -71,7 +67,6 @@ public class PebbleIoThread extends GBDeviceIoThread { private boolean mIsTCP = false; private BluetoothAdapter mBtAdapter = null; private BluetoothSocket mBtSocket = null; - private BluetoothServerSocket mBtServerSocket = null; private Socket mTCPSocket = null; // for emulator private InputStream mInStream = null; private OutputStream mOutStream = null; @@ -365,7 +360,7 @@ public class PebbleIoThread extends GBDeviceIoThread { LOG.info(e.getMessage()); mIsConnected = false; int reconnectAttempts = prefs.getInt("pebble_reconnect_attempts", 10); - if (GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) { + if (!mQuit && GBApplication.getGBPrefs().getAutoReconnect() && reconnectAttempts > 0) { gbDevice.setState(GBDevice.State.CONNECTING); gbDevice.sendDeviceUpdateIntent(getContext()); int delaySeconds = 1; @@ -383,33 +378,10 @@ public class PebbleIoThread extends GBDeviceIoThread { } } } - if (!mIsConnected && !mQuit) { - try { - gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT); - gbDevice.sendDeviceUpdateIntent(getContext()); - UUID reconnectUUID = mPebbleProtocol.isFw3x ? PEBBLE_UUID_RECONNECT3X : PEBBLE_UUID_RECONNECT; - mBtServerSocket = mBtAdapter.listenUsingRfcommWithServiceRecord("PebbleReconnectListener", reconnectUUID); - mBtSocket = mBtServerSocket.accept(); - LOG.info("incoming connection on reconnect uuid (" + reconnectUUID + "), will connect actively"); - mBtSocket.close(); - mIsConnected = connect(gbDevice.getAddress()); - } catch (IOException ex) { - ex.printStackTrace(); - LOG.info("error while reconnecting"); - } finally { - try { - if (mBtServerSocket != null) { - mBtServerSocket.close(); - mBtServerSocket = null; - } - } catch (IOException ignore) { - } - } - } if (!mIsConnected) { mBtSocket = null; LOG.info("Bluetooth socket closed, will quit IO Thread"); - mQuit = true; + break; } } } @@ -421,10 +393,16 @@ public class PebbleIoThread extends GBDeviceIoThread { } catch (IOException e) { e.printStackTrace(); } + mBtSocket = null; } + enablePebbleKitReceiver(false); - mBtSocket = null; - gbDevice.setState(GBDevice.State.NOT_CONNECTED); + + if (mQuit) { + gbDevice.setState(GBDevice.State.NOT_CONNECTED); + } else { + gbDevice.setState(GBDevice.State.WAITING_FOR_RECONNECT); + } gbDevice.sendDeviceUpdateIntent(getContext()); } @@ -700,13 +678,6 @@ public class PebbleIoThread extends GBDeviceIoThread { e.printStackTrace(); } } - if (mBtServerSocket != null) { - try { - mBtServerSocket.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } if (mTCPSocket != null) { try { mTCPSocket.close(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java index 74e4736d..e396d03f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/pebble/PebbleSupport.java @@ -78,6 +78,7 @@ public class PebbleSupport extends AbstractSerialDeviceSupport { private boolean reconnect() { if (!isConnected() && useAutoConnect()) { if (getDevice().getState() == GBDevice.State.WAITING_FOR_RECONNECT) { + gbDeviceIOThread.quit(); gbDeviceIOThread.interrupt(); gbDeviceIOThread = null; if (!connect()) {