diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java index 8b780dd7c..e655de30d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DiscoveryActivity.java @@ -20,6 +20,7 @@ package nodomain.freeyourgadget.gadgetbridge.activities; import android.Manifest; import android.annotation.TargetApi; import android.app.Activity; +import android.app.AlertDialog; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothManager; @@ -30,6 +31,7 @@ import android.bluetooth.le.ScanResult; import android.bluetooth.le.ScanSettings; import android.content.BroadcastReceiver; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.PackageManager; @@ -123,7 +125,7 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC } case BluetoothDevice.ACTION_BOND_STATE_CHANGED: { BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); - if (device != null && device.getAddress().equals(bondingAddress)) { + if (device != null && bondingDevice != null && device.getAddress().equals(bondingDevice.getMacAddress())) { int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, BluetoothDevice.BOND_NONE); if (bondState == BluetoothDevice.BOND_BONDED) { handleDeviceBonded(); @@ -134,11 +136,57 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC } }; - private void handleDeviceBonded() { - GB.toast(DiscoveryActivity.this, "Successfully bonded with: " + bondingAddress, Toast.LENGTH_SHORT, GB.INFO); + private void connectAndFinish(GBDevice device) { + GB.toast(DiscoveryActivity.this, getString(R.string.discovery_trying_to_connect_to, device.getName()), Toast.LENGTH_SHORT, GB.INFO); + GBApplication.deviceService().connect(device); finish(); } + private void createBond(final GBDeviceCandidate deviceCandidate, int bondingStyle) { + if (bondingStyle == DeviceCoordinator.BONDING_STYLE_NONE) { + return; + } + if (bondingStyle == DeviceCoordinator.BONDING_STYLE_ASK) { + new AlertDialog.Builder(this) + .setCancelable(true) + .setTitle(DiscoveryActivity.this.getString(R.string.discovery_pair_title, deviceCandidate.getName())) + .setMessage(DiscoveryActivity.this.getString(R.string.discovery_pair_question)) + .setPositiveButton(DiscoveryActivity.this.getString(R.string.discovery_yes_pair), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + doCreatePair(deviceCandidate); + } + }) + .setNegativeButton(R.string.discovery_dont_pair, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + GBDevice device = DeviceHelper.getInstance().toSupportedDevice(deviceCandidate); + connectAndFinish(device); + } + }) + .show(); + } else { + doCreatePair(deviceCandidate); + } + } + + private void doCreatePair(GBDeviceCandidate deviceCandidate) { + GB.toast(DiscoveryActivity.this, getString(R.string.discovery_attempting_to_pair, deviceCandidate.getName()), Toast.LENGTH_SHORT, GB.INFO); + if (deviceCandidate.getDevice().createBond()) { + // async, wait for bonding event to finish this activity + LOG.info("Bonding in progress..."); + bondingDevice = deviceCandidate; + } else { + GB.toast(DiscoveryActivity.this, getString(R.string.discovery_bonding_failed_immediately, deviceCandidate.getName()), Toast.LENGTH_SHORT, GB.ERROR); + } + } + + private void handleDeviceBonded() { + GB.toast(DiscoveryActivity.this, getString(R.string.discovery_successfully_bonded, bondingDevice.getName()), Toast.LENGTH_SHORT, GB.INFO); + GBDevice device = DeviceHelper.getInstance().toSupportedDevice(bondingDevice); + connectAndFinish(device); + } + private final BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { @@ -203,7 +251,7 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC private DeviceCandidateAdapter cadidateListAdapter; private Button startButton; private Scanning isScanning = Scanning.SCANNING_OFF; - private String bondingAddress; + private GBDeviceCandidate bondingDevice; private enum Scanning { SCANNING_BT, @@ -358,7 +406,7 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC } } else { discoveryFinished(); - Toast.makeText(this, "Enable Bluetooth to discover devices.", Toast.LENGTH_LONG).show(); + GB.toast(DiscoveryActivity.this, getString(R.string.discovery_enable_bluetooth), Toast.LENGTH_SHORT, GB.ERROR); } } @@ -535,19 +583,24 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC intent.putExtra(DeviceCoordinator.EXTRA_DEVICE_CANDIDATE, deviceCandidate); startActivity(intent); } else { + GBDevice device = DeviceHelper.getInstance().toSupportedDevice(deviceCandidate); + int bondingStyle = coordinator.getBondingStyle(deviceCandidate); + if (bondingStyle == DeviceCoordinator.BONDING_STYLE_NONE) { + LOG.info("No bonding needed, according to coordinator, so connecting right away"); + connectAndFinish(device); + return; + } + try { BluetoothDevice btDevice = adapter.getRemoteDevice(deviceCandidate.getMacAddress()); switch (btDevice.getBondState()) { case BluetoothDevice.BOND_NONE: { - if (btDevice.createBond()) { - // async, wait for bonding event to finish this activity - bondingAddress = btDevice.getAddress(); - } + createBond(deviceCandidate, bondingStyle); break; } case BluetoothDevice.BOND_BONDING: // async, wait for bonding event to finish this activity - bondingAddress = btDevice.getAddress(); + bondingDevice = deviceCandidate; break; case BluetoothDevice.BOND_BONDED: handleDeviceBonded(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java index 07abf001d..055156a43 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java @@ -119,4 +119,9 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator { } return false; } + + @Override + public int getBondingStyle(GBDeviceCandidate deviceCandidate) { + return BONDING_STYLE_ASK; + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java index 66ebdddf6..9b74d3f7c 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java @@ -47,6 +47,21 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType; */ public interface DeviceCoordinator { String EXTRA_DEVICE_CANDIDATE = "nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate.EXTRA_DEVICE_CANDIDATE"; + /** + * Do not attempt to bond after discovery. + */ + int BONDING_STYLE_NONE = 0; + /** + * Bond after discovery. + * This is not recommended, as there are mobile devices on which bonding does not work. + * Prefer to use #BONDING_STYLE_ASK instead. + */ + int BONDING_STYLE_BOND = 1; + /** + * Let the user decide whether to bond or not after discovery. + * Prefer this over #BONDING_STYLE_BOND + */ + int BONDING_STYLE_ASK = 2; /** * Checks whether this coordinator handles the given candidate. @@ -207,4 +222,10 @@ public interface DeviceCoordinator { * @return */ Class getAppsManagementActivity(); + + /** + * Returns how/if the given device should be bonded before connecting to it. + * @param deviceCandidate + */ + int getBondingStyle(GBDeviceCandidate deviceCandidate); } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4b6a5d23a..2361af924 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -412,4 +412,13 @@ Text notifications = 1.0.1.28 and Mili_pro.ft* installed.]]> off + Attempting to pair with %1$s + Bonding with %1$s failed immediately. + Trying to connect to: %1$s + Enable Bluetooth to discover devices. + Successfully bonded with %1$s. + Pair with %1$s? + Select Pair to pair your devices. If this fails, try again without pairing. + Pair + Don\'t Pair