diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/discovery/DiscoveryActivityV2.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/discovery/DiscoveryActivityV2.java index 410362fc0..452e96ea2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/discovery/DiscoveryActivityV2.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/discovery/DiscoveryActivityV2.java @@ -611,6 +611,22 @@ public class DiscoveryActivityV2 extends AbstractGBActivity implements AdapterVi } } + if (coordinator.suggestUnbindBeforePair() && deviceCandidate.isBonded()) { + new MaterialAlertDialogBuilder(getContext()) + .setTitle(R.string.unbind_before_pair_title) + .setMessage(R.string.unbind_before_pair_message) + .setIcon(R.drawable.ic_warning_gray) + .setPositiveButton(R.string.ok, (dialog, whichButton) -> { + startPair(deviceCandidate, coordinator); + }) + .setNegativeButton(android.R.string.cancel, null) + .show(); + } else { + startPair(deviceCandidate, coordinator); + } + } + + private void startPair(final GBDeviceCandidate deviceCandidate, final DeviceCoordinator coordinator) { final Class pairingActivity = coordinator.getPairingActivity(); if (pairingActivity != null) { final Intent intent = new Intent(this, pairingActivity); @@ -784,7 +800,6 @@ public class DiscoveryActivityV2 extends AbstractGBActivity implements AdapterVi private void loadSettings() { final Prefs prefs = GBApplication.getPrefs(); - deviceFoundProcessor.setIgnoreBonded(prefs.getBoolean("ignore_bonded_devices", true)); deviceFoundProcessor.setDiscoverUnsupported(prefs.getBoolean("discover_unsupported_devices", false)); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/discovery/GBScanEventProcessor.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/discovery/GBScanEventProcessor.java index f701399a3..220c03b6e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/discovery/GBScanEventProcessor.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/discovery/GBScanEventProcessor.java @@ -24,13 +24,11 @@ import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; @@ -55,14 +53,11 @@ public final class GBScanEventProcessor implements Runnable { private static final ParcelUuid ZERO_UUID = ParcelUuid.fromString("00000000-0000-0000-0000-000000000000"); - // Devices that can be ignored by just the address (eg. already bonded) - private final Set devicesToIgnore = new HashSet<>(); private final Map candidatesByAddress = new LinkedHashMap<>(); private final BlockingQueue eventsToProcessQueue = new LinkedBlockingQueue<>(); private final Map> eventsToProcessMap = new HashMap<>(); - private boolean ignoreBonded = true; private boolean discoverUnsupported = false; private volatile boolean running = false; @@ -121,16 +116,11 @@ public final class GBScanEventProcessor implements Runnable { } public void clear() { - devicesToIgnore.clear(); candidatesByAddress.clear(); eventsToProcessMap.clear(); eventsToProcessQueue.clear(); } - public void setIgnoreBonded(boolean ignoreBonded) { - this.ignoreBonded = ignoreBonded; - } - public void setDiscoverUnsupported(boolean discoverUnsupported) { this.discoverUnsupported = discoverUnsupported; } @@ -203,11 +193,6 @@ public final class GBScanEventProcessor implements Runnable { return false; } - if (devicesToIgnore.contains(address)) { - LOG.trace("Ignoring {} events for {}", events.size(), address); - return false; - } - LOG.debug("Processing {} events for {}", events.size(), address); GBDeviceCandidate candidate = candidatesByAddress.get(address); @@ -228,12 +213,6 @@ public final class GBScanEventProcessor implements Runnable { previousUuids = candidate.getServiceUuids(); } - if (candidate.isBonded() && ignoreBonded) { - LOG.trace("Ignoring already bonded device {}", address); - devicesToIgnore.add(address); - return false; - } - // Update the device with the remaining events for (final GBScanEvent event : events) { candidate.setRssi(event.getRssi()); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/DeviceCandidateAdapter.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/DeviceCandidateAdapter.java index f10823e77..40126b3d1 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/DeviceCandidateAdapter.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/adapter/DeviceCandidateAdapter.java @@ -17,7 +17,6 @@ along with this program. If not, see . */ package nodomain.freeyourgadget.gadgetbridge.adapter; -import android.bluetooth.BluetoothDevice; import android.content.Context; import android.text.TextUtils; import android.view.LayoutInflater; @@ -30,7 +29,6 @@ import android.widget.TextView; import java.util.ArrayList; import java.util.List; -import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; @@ -76,9 +74,6 @@ public class DeviceCandidateAdapter extends ArrayAdapter { final List statusLines = new ArrayList<>(); if (device.isBonded()) { statusLines.add(getContext().getString(R.string.device_is_currently_bonded)); - if (!GBApplication.getPrefs().getBoolean("ignore_bonded_devices", true)) { // This could be passed to the constructor instead - deviceImageView.setImageResource(coordinator.getDisabledIconResource()); - } } if (!deviceType.isSupported()) { 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 b0f012e13..2c81b660e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractDeviceCoordinator.java @@ -382,6 +382,11 @@ public abstract class AbstractDeviceCoordinator implements DeviceCoordinator { return BONDING_STYLE_ASK; } + @Override + public boolean suggestUnbindBeforePair() { + return true; + } + @Override public boolean isExperimental() { return false; 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 3a4b3df7e..13140e5ac 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/DeviceCoordinator.java @@ -457,6 +457,12 @@ public interface DeviceCoordinator { */ int getBondingStyle(); + /** + * Whether it is recommended to unbind the device before pairing due to compatibility issues. Returns false + * if the device is known to pair without issues even when already bound in Android bluetooth settings. + */ + boolean suggestUnbindBeforePair(); + /** * Returns true if this device is in an experimental state / not tested. */ diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java index f81f31e3b..a52093792 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/banglejs/BangleJSCoordinator.java @@ -148,6 +148,11 @@ public class BangleJSCoordinator extends AbstractBLEDeviceCoordinator { return BuildConfig.INTERNET_ACCESS ? AppsManagementActivity.class : null; } + @Override + public boolean suggestUnbindBeforePair() { + return false; + } + @Override protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) { } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cmfwatchpro/CmfWatchProCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cmfwatchpro/CmfWatchProCoordinator.java index efceba4d7..e8d5240ba 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cmfwatchpro/CmfWatchProCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/cmfwatchpro/CmfWatchProCoordinator.java @@ -87,6 +87,11 @@ public class CmfWatchProCoordinator extends AbstractBLEDeviceCoordinator { return handler.isValid() ? handler : null; } + @Override + public boolean suggestUnbindBeforePair() { + return false; + } + @Override protected void deleteDevice(@NonNull final GBDevice gbDevice, @NonNull final Device device, diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java index 0ab6e45bd..dea49d364 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/huami/HuamiCoordinator.java @@ -78,6 +78,11 @@ public abstract class HuamiCoordinator extends AbstractBLEDeviceCoordinator { return Collections.singletonList(filter); } + @Override + public boolean suggestUnbindBeforePair() { + return false; + } + @Override protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { Long deviceId = device.getId(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCoordinator.java index 453fc710e..89b395313 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/sony/headphones/SonyHeadphonesCoordinator.java @@ -58,6 +58,11 @@ public abstract class SonyHeadphonesCoordinator extends AbstractBLClassicDeviceC return new SonyHeadphonesSettingsCustomizer(device); } + @Override + public boolean suggestUnbindBeforePair() { + return false; + } + @Override protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException { } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index fefc526f2..1a497058f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1812,8 +1812,6 @@ Error exporting device specific preferences Error setting alias: Error retrieving devices from database - Ignore bonded devices - Enabling this option will ignore devices that have been bonded/paired already when scanning Discover unsupported devices Enabling this option will display all discovered bluetooth devices when scanning. Short tap will copy device name and mac address to clipboard. Long press will launch `Add test device` dialog. Can cause potential app freezing issues. Location must be turned on to scan for devices @@ -2709,4 +2707,6 @@ Scanning 1 device Scanning %d devices Scan service + Already bound + This device is already bound in Android settings, which can make pairing fail for some devices.\n\nIf adding the device fails, please remove it in Android settings and try again. diff --git a/app/src/main/res/xml/discovery_pairing_preferences.xml b/app/src/main/res/xml/discovery_pairing_preferences.xml index 9c427ae3d..59aea4a59 100644 --- a/app/src/main/res/xml/discovery_pairing_preferences.xml +++ b/app/src/main/res/xml/discovery_pairing_preferences.xml @@ -2,13 +2,6 @@ -