From 18bc100d5ab05355aa71cbf06e3e0a7605f94b09 Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Fri, 4 Dec 2020 19:20:43 +0100 Subject: [PATCH] BLE sensors: Miband3's is now considered a heart rate sensor during discovery. Some BLE devices do not announce all there supported services in the BLE advertisement packages. Android's ScanFilter decides based upon this information only. When connecting to such a device (and trigger service discovery), the service can still be used. Fixes #447. --- .../opentracks/settings/SettingsActivity.java | 2 +- .../BluetoothLeSensorPreference.java | 24 +++++++++++-------- .../opentracks/util/BluetoothUtils.java | 9 +++++++ 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java b/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java index a7f425b6b..8fa5de2e6 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java +++ b/src/main/java/de/dennisguse/opentracks/settings/SettingsActivity.java @@ -154,7 +154,7 @@ public class SettingsActivity extends AppCompatActivity implements ChooseActivit activityPreferenceDialog = ActivityTypePreference.ActivityPreferenceDialog.newInstance(preference.getKey()); dialogFragment = activityPreferenceDialog; } else if (preference instanceof BluetoothLeHeartRatePreference) { - dialogFragment = BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(preference.getKey(), BluetoothUtils.HEART_RATE_SERVICE_UUID); + dialogFragment = BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(preference.getKey(), BluetoothUtils.HEART_RATE_SUPPORTING_DEVICES); } else if (preference instanceof BluetoothLeCyclingCadenceAndSpeedPreference) { dialogFragment = BluetoothLeSensorPreference.BluetoothLeSensorPreferenceDialog.newInstance(preference.getKey(), BluetoothUtils.CYCLING_SPEED_CADENCE_SERVICE_UUID); } else if (preference instanceof BluetoothLeCyclingPowerPreference) { diff --git a/src/main/java/de/dennisguse/opentracks/settings/bluetooth/BluetoothLeSensorPreference.java b/src/main/java/de/dennisguse/opentracks/settings/bluetooth/BluetoothLeSensorPreference.java index b6e8b818a..466f14f77 100644 --- a/src/main/java/de/dennisguse/opentracks/settings/bluetooth/BluetoothLeSensorPreference.java +++ b/src/main/java/de/dennisguse/opentracks/settings/bluetooth/BluetoothLeSensorPreference.java @@ -23,8 +23,10 @@ import androidx.preference.DialogPreference; import androidx.preference.PreferenceDialogFragmentCompat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.UUID; +import java.util.stream.Collectors; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.settings.BluetoothLeAdapter; @@ -39,7 +41,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference { private static final String TAG = BluetoothLeSensorPreference.class.getSimpleName(); - private static final String ARG_BLUETOOTH_UUID = "bluetoothUUID"; + private static final String ARG_BLE_SERVICE_UUIDS = "bluetoothUUID"; private static final int DEVICE_NONE_RESOURCEID = R.string.value_none; @@ -109,8 +111,9 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference { @Override public void onBatchScanResults(List results) { - for (ScanResult scanResult : results) { - listAdapter.add(scanResult.getDevice()); + for (ScanResult result : results) { + Log.d(TAG, "Found device " + result.getDevice().getName() + " " + result); + listAdapter.add(result.getDevice()); } } @@ -124,10 +127,14 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference { }; public static BluetoothLeSensorPreferenceDialog newInstance(String preferenceKey, UUID sensorUUID) { + return newInstance(preferenceKey, Collections.singletonList(sensorUUID)); + } + + public static BluetoothLeSensorPreferenceDialog newInstance(String preferenceKey, List sensorUUIDs) { final BluetoothLeSensorPreferenceDialog fragment = new BluetoothLeSensorPreferenceDialog(); final Bundle b = new Bundle(1); b.putString(ARG_KEY, preferenceKey); - b.putSerializable(ARG_BLUETOOTH_UUID, sensorUUID); + b.putParcelableArrayList(ARG_BLE_SERVICE_UUIDS, new ArrayList<>(sensorUUIDs.stream().map(ParcelUuid::new).collect(Collectors.toList()))); fragment.setArguments(b); return fragment; } @@ -136,8 +143,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - UUID sensorUUID = (UUID) getArguments().getSerializable(ARG_BLUETOOTH_UUID); - Log.i(TAG, "UUID: " + sensorUUID); + List serviceUUIDs = getArguments().getParcelableArrayList(ARG_BLE_SERVICE_UUIDS); BluetoothAdapter bluetoothAdapter = BluetoothUtils.getAdapter(getContext()); if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) { @@ -148,7 +154,7 @@ public abstract class BluetoothLeSensorPreference extends DialogPreference { } if (bluetoothAdapter.isDiscovering()) { - Log.i(TAG, "Cancelling ongoing B scanFilter = new ArrayList<>(); - scanFilter.add(scanFilterBuilder.build()); + List scanFilter = serviceUUIDs.stream().map(it -> new ScanFilter.Builder().setServiceUuid(it).build()).collect(Collectors.toList()); ScanSettings.Builder scanSettingsBuilder = new ScanSettings.Builder(); scanSettingsBuilder.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY); diff --git a/src/main/java/de/dennisguse/opentracks/util/BluetoothUtils.java b/src/main/java/de/dennisguse/opentracks/util/BluetoothUtils.java index 37a5aab09..5150ec5a0 100644 --- a/src/main/java/de/dennisguse/opentracks/util/BluetoothUtils.java +++ b/src/main/java/de/dennisguse/opentracks/util/BluetoothUtils.java @@ -23,6 +23,9 @@ import android.util.Log; import androidx.annotation.NonNull; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.UUID; import de.dennisguse.opentracks.content.sensor.SensorDataCycling; @@ -39,6 +42,12 @@ public class BluetoothUtils { public static final UUID HEART_RATE_SERVICE_UUID = new UUID(0x180D00001000L, 0x800000805f9b34fbL); public static final UUID HEART_RATE_MEASUREMENT_CHAR_UUID = new UUID(0x2A3700001000L, 0x800000805f9b34fbL); + public static final List HEART_RATE_SUPPORTING_DEVICES = Collections.unmodifiableList(Arrays.asList( + BluetoothUtils.HEART_RATE_SERVICE_UUID, + //Devices that support HEART_RATE_SERVICE_UUID, but do not announce HEART_RATE_SERVICE_UUID in there BLE announcement messages (during device discovery). + UUID.fromString("0000fee0-0000-1000-8000-00805f9b34fb") //Miband3 + )); + public static final UUID CYCLING_POWER_UUID = new UUID(0x181800001000L, 0x800000805f9b34fbL); public static final UUID CYCLING_POWER_MEASUREMENT_CHAR_UUID = new UUID(0x2A6300001000L, 0x800000805f9b34fbL);