A few improvements to discovery
- display the right icon for found device candidates - scan for specific LE services
This commit is contained in:
parent
b2e86ca061
commit
b9ff2cd468
|
@ -7,6 +7,7 @@ import android.bluetooth.BluetoothAdapter;
|
|||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.bluetooth.le.ScanCallback;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.bluetooth.le.ScanResult;
|
||||
import android.bluetooth.le.ScanSettings;
|
||||
import android.content.BroadcastReceiver;
|
||||
|
@ -32,6 +33,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
|
@ -39,9 +41,11 @@ import nodomain.freeyourgadget.gadgetbridge.adapter.DeviceCandidateAdapter;
|
|||
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
import static android.bluetooth.le.ScanSettings.CALLBACK_TYPE_ALL_MATCHES;
|
||||
import static android.bluetooth.le.ScanSettings.MATCH_MODE_STICKY;
|
||||
import static android.bluetooth.le.ScanSettings.SCAN_MODE_LOW_LATENCY;
|
||||
|
||||
|
@ -257,7 +261,9 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||
}
|
||||
|
||||
GBDeviceCandidate candidate = new GBDeviceCandidate(device, rssi);
|
||||
if (DeviceHelper.getInstance().isSupported(candidate)) {
|
||||
DeviceType deviceType = DeviceHelper.getInstance().getSupportedType(candidate);
|
||||
if (deviceType.isSupported()) {
|
||||
candidate.setDeviceType(deviceType);
|
||||
int index = deviceCandidates.indexOf(candidate);
|
||||
if (index >= 0) {
|
||||
deviceCandidates.set(index, candidate); // replace
|
||||
|
@ -410,7 +416,15 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||
LOG.info("Start New BTLE Discovery");
|
||||
handler.removeMessages(0, stopRunnable);
|
||||
handler.sendMessageDelayed(getPostMessage(stopRunnable), SCAN_DURATION);
|
||||
adapter.getBluetoothLeScanner().startScan(null, getScanSettings(), getScanCallback());
|
||||
adapter.getBluetoothLeScanner().startScan(getScanFilters(), getScanSettings(), getScanCallback());
|
||||
}
|
||||
|
||||
private List<ScanFilter> getScanFilters() {
|
||||
List<ScanFilter> allFilters = new ArrayList<>();
|
||||
for (DeviceCoordinator coordinator : DeviceHelper.getInstance().getAllCoordinators()) {
|
||||
allFilters.addAll(coordinator.createBLEScanFilters());
|
||||
}
|
||||
return allFilters;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
|
|
|
@ -2,11 +2,15 @@ package nodomain.freeyourgadget.gadgetbridge.devices;
|
|||
|
||||
import android.bluetooth.BluetoothClass;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import de.greenrobot.dao.query.QueryBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
|
@ -21,12 +25,22 @@ import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
|
|||
public abstract class AbstractDeviceCoordinator implements DeviceCoordinator {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(AbstractDeviceCoordinator.class);
|
||||
|
||||
@Override
|
||||
public final boolean supports(GBDeviceCandidate candidate) {
|
||||
return getSupportedType(candidate).isSupported();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(GBDevice device) {
|
||||
return getDeviceType().equals(device.getType());
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Collection<? extends ScanFilter> createBLEScanFilters() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public GBDevice createDevice(GBDeviceCandidate candidate) {
|
||||
return new GBDevice(candidate.getDevice().getAddress(), candidate.getName(), getDeviceType());
|
||||
|
|
|
@ -1,8 +1,14 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.devices;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
|
@ -24,7 +30,18 @@ public interface DeviceCoordinator {
|
|||
String EXTRA_DEVICE_MAC_ADDRESS = "nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate.EXTRA_MAC_ADDRESS";
|
||||
|
||||
/**
|
||||
* Checks whether this candidate handles the given candidate.
|
||||
* Checks whether this coordinator handles the given candidate.
|
||||
* Returns the supported device type for the given candidate or
|
||||
* DeviceType.UNKNOWN
|
||||
*
|
||||
* @param candidate
|
||||
* @return the supported device type for the given candidate.
|
||||
*/
|
||||
@NonNull
|
||||
DeviceType getSupportedType(GBDeviceCandidate candidate);
|
||||
|
||||
/**
|
||||
* Checks whether this coordinator handles the given candidate.
|
||||
*
|
||||
* @param candidate
|
||||
* @return true if this coordinator handles the given candidate.
|
||||
|
@ -39,6 +56,15 @@ public interface DeviceCoordinator {
|
|||
*/
|
||||
boolean supports(GBDevice device);
|
||||
|
||||
/**
|
||||
* Returns a list of scan filters that shall be used to discover devices supported
|
||||
* by this coordinator.
|
||||
* @return the list of scan filters, may be empty
|
||||
*/
|
||||
@NonNull
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
Collection<? extends ScanFilter> createBLEScanFilters();
|
||||
|
||||
GBDevice createDevice(GBDeviceCandidate candidate);
|
||||
|
||||
/**
|
||||
|
@ -154,5 +180,4 @@ public interface DeviceCoordinator {
|
|||
* @return
|
||||
*/
|
||||
Class<? extends Activity> getAppsManagementActivity();
|
||||
|
||||
}
|
||||
|
|
|
@ -82,8 +82,8 @@ public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(GBDeviceCandidate candidate) {
|
||||
return false;
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
return DeviceType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.devices.miband;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelUuid;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
|
||||
|
@ -23,19 +31,30 @@ public class MiBand2Coordinator extends MiBandCoordinator {
|
|||
return DeviceType.MIBAND2;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public boolean supports(GBDeviceCandidate candidate) {
|
||||
// and a heuristic
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public Collection<? extends ScanFilter> createBLEScanFilters() {
|
||||
ParcelUuid mi2Service = new ParcelUuid(MiBandService.UUID_SERVICE_MIBAND2_SERVICE);
|
||||
ScanFilter filter = new ScanFilter.Builder().setServiceUuid(mi2Service).build();
|
||||
return Collections.singletonList(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
// and a heuristic for now
|
||||
try {
|
||||
BluetoothDevice device = candidate.getDevice();
|
||||
if (isHealthWearable(device)) {
|
||||
String name = device.getName();
|
||||
return name != null && name.equalsIgnoreCase(MiBandConst.MI_BAND2_NAME);
|
||||
if (name != null && name.equalsIgnoreCase(MiBandConst.MI_BAND2_NAME)) {
|
||||
return DeviceType.MIBAND2;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.error("unable to check device support", ex);
|
||||
}
|
||||
return false;
|
||||
return DeviceType.UNKNOWN;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,21 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.devices.miband;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.ParcelUuid;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import de.greenrobot.dao.query.QueryBuilder;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBException;
|
||||
|
@ -32,28 +40,39 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
|
|||
public MiBandCoordinator() {
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public boolean supports(GBDeviceCandidate candidate) {
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public Collection<? extends ScanFilter> createBLEScanFilters() {
|
||||
ParcelUuid mi1Service = new ParcelUuid(MiBandService.UUID_SERVICE_MIBAND_SERVICE);
|
||||
ScanFilter filter = new ScanFilter.Builder().setServiceUuid(mi1Service).build();
|
||||
return Collections.singletonList(filter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
String macAddress = candidate.getMacAddress().toUpperCase();
|
||||
if (macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1_1A)
|
||||
|| macAddress.startsWith(MiBandService.MAC_ADDRESS_FILTER_1S)) {
|
||||
return true;
|
||||
return DeviceType.MIBAND;
|
||||
}
|
||||
if (candidate.supportsService(MiBandService.UUID_SERVICE_MIBAND_SERVICE)
|
||||
&& !candidate.supportsService(MiBandService.UUID_SERVICE_MIBAND2_SERVICE)) {
|
||||
return true;
|
||||
return DeviceType.MIBAND;
|
||||
}
|
||||
// and a heuristic
|
||||
try {
|
||||
BluetoothDevice device = candidate.getDevice();
|
||||
if (isHealthWearable(device)) {
|
||||
String name = device.getName();
|
||||
return name != null && name.toUpperCase().startsWith(MiBandConst.MI_GENERAL_NAME_PREFIX.toUpperCase());
|
||||
if (name != null && name.toUpperCase().startsWith(MiBandConst.MI_GENERAL_NAME_PREFIX.toUpperCase())) {
|
||||
return DeviceType.MIBAND;
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.error("unable to check device support", ex);
|
||||
}
|
||||
return false;
|
||||
return DeviceType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -30,9 +30,12 @@ public class PebbleCoordinator extends AbstractDeviceCoordinator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(GBDeviceCandidate candidate) {
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
String name = candidate.getDevice().getName();
|
||||
return name != null && name.startsWith("Pebble");
|
||||
if (name != null && name.startsWith("Pebble")) {
|
||||
return DeviceType.PEBBLE;
|
||||
}
|
||||
return DeviceType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -45,6 +48,7 @@ public class PebbleCoordinator extends AbstractDeviceCoordinator {
|
|||
return PebblePairingActivity.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Activity> getPrimaryActivity() {
|
||||
return AppManagerActivity.class;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,12 @@ import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
|||
|
||||
public class VibratissimoCoordinator extends AbstractDeviceCoordinator {
|
||||
@Override
|
||||
public boolean supports(GBDeviceCandidate candidate) {
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
String name = candidate.getDevice().getName();
|
||||
return name != null && name.startsWith("Vibratissimo");
|
||||
if (name != null && name.startsWith("Vibratissimo")) {
|
||||
return DeviceType.VIBRATISSIMO;
|
||||
}
|
||||
return DeviceType.UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.bluetooth.BluetoothDevice;
|
|||
import android.os.Parcel;
|
||||
import android.os.ParcelUuid;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -38,7 +39,7 @@ public class GBDeviceCandidate implements Parcelable {
|
|||
rssi = (short) in.readInt();
|
||||
deviceType = DeviceType.valueOf(in.readString());
|
||||
|
||||
if (device == null || deviceType == null) {
|
||||
if (device == null) {
|
||||
throw new IllegalStateException("Unable to read state from Parcel");
|
||||
}
|
||||
}
|
||||
|
@ -54,6 +55,10 @@ public class GBDeviceCandidate implements Parcelable {
|
|||
return device;
|
||||
}
|
||||
|
||||
public void setDeviceType(DeviceType type) {
|
||||
deviceType = type;
|
||||
}
|
||||
|
||||
public DeviceType getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ public enum DeviceType {
|
|||
return key;
|
||||
}
|
||||
|
||||
public boolean isSupported() {
|
||||
return this != UNKNOWN;
|
||||
}
|
||||
|
||||
public static DeviceType fromKey(int key) {
|
||||
for (DeviceType type : values()) {
|
||||
if (type.key == key) {
|
||||
|
|
|
@ -8,7 +8,6 @@ import android.widget.Toast;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -47,16 +46,17 @@ public class DeviceHelper {
|
|||
// lazily created
|
||||
private List<DeviceCoordinator> coordinators;
|
||||
|
||||
public boolean isSupported(GBDeviceCandidate candidate) {
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
for (DeviceCoordinator coordinator : getAllCoordinators()) {
|
||||
if (coordinator.supports(candidate)) {
|
||||
return true;
|
||||
DeviceType deviceType = coordinator.getSupportedType(candidate);
|
||||
if (deviceType.isSupported()) {
|
||||
return deviceType;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return DeviceType.UNKNOWN;
|
||||
}
|
||||
|
||||
public boolean isSupported(GBDevice device) {
|
||||
public boolean getSupportedType(GBDevice device) {
|
||||
for (DeviceCoordinator coordinator : getAllCoordinators()) {
|
||||
if (coordinator.supports(device)) {
|
||||
return true;
|
||||
|
@ -174,7 +174,7 @@ public class DeviceHelper {
|
|||
List<Device> activeDevices = DBHelper.getActiveDevices(lockHandler.getDaoSession());
|
||||
for (Device dbDevice : activeDevices) {
|
||||
GBDevice gbDevice = toGBDevice(dbDevice);
|
||||
if (gbDevice != null && DeviceHelper.getInstance().isSupported(gbDevice)) {
|
||||
if (gbDevice != null && DeviceHelper.getInstance().getSupportedType(gbDevice)) {
|
||||
result.add(gbDevice);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue