Some more improvements to discovery
- pass service uuids to GBDeviceCandaidate so that DeviceCoordinators can detect devices by their services. Note: they should not rely on service uuids being available
This commit is contained in:
parent
b9ff2cd468
commit
2f7eb9ef23
|
@ -8,6 +8,7 @@ import android.bluetooth.BluetoothDevice;
|
|||
import android.bluetooth.BluetoothManager;
|
||||
import android.bluetooth.le.ScanCallback;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.bluetooth.le.ScanRecord;
|
||||
import android.bluetooth.le.ScanResult;
|
||||
import android.bluetooth.le.ScanSettings;
|
||||
import android.content.BroadcastReceiver;
|
||||
|
@ -42,6 +43,7 @@ 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.AndroidUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
|
@ -95,6 +97,14 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||
handleDeviceFound(device, rssi);
|
||||
break;
|
||||
}
|
||||
case BluetoothDevice.ACTION_UUID: {
|
||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, GBDevice.RSSI_UNKNOWN);
|
||||
Parcelable[] uuids = intent.getParcelableArrayExtra(BluetoothDevice.EXTRA_UUID);
|
||||
ParcelUuid[] uuids2 = AndroidUtils.toParcelUUids(uuids);
|
||||
handleDeviceFound(device, rssi, uuids2);
|
||||
break;
|
||||
}
|
||||
case BluetoothDevice.ACTION_BOND_STATE_CHANGED: {
|
||||
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
|
||||
if (device != null && device.getAddress().equals(bondingAddress)) {
|
||||
|
@ -131,10 +141,18 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||
public void onScanResult(int callbackType, ScanResult result) {
|
||||
super.onScanResult(callbackType, result);
|
||||
try {
|
||||
ScanRecord scanRecord = result.getScanRecord();
|
||||
ParcelUuid[] uuids = null;
|
||||
if (scanRecord != null) {
|
||||
//logMessageContent(scanRecord.getBytes());
|
||||
List<ParcelUuid> serviceUuids = scanRecord.getServiceUuids();
|
||||
if (serviceUuids != null) {
|
||||
uuids = serviceUuids.toArray(new ParcelUuid[0]);
|
||||
}
|
||||
}
|
||||
LOG.warn(result.getDevice().getName() + ": " +
|
||||
((result.getScanRecord() != null) ? result.getScanRecord().getBytes().length : -1));
|
||||
//logMessageContent(result.getScanRecord().getBytes());
|
||||
handleDeviceFound(result.getDevice(), (short) result.getRssi());
|
||||
((scanRecord != null) ? scanRecord.getBytes().length : -1));
|
||||
handleDeviceFound(result.getDevice(), (short) result.getRssi(), uuids);
|
||||
} catch (NullPointerException e) {
|
||||
LOG.warn("Error handling scan result", e);
|
||||
}
|
||||
|
@ -199,6 +217,7 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||
|
||||
IntentFilter bluetoothIntents = new IntentFilter();
|
||||
bluetoothIntents.addAction(BluetoothDevice.ACTION_FOUND);
|
||||
bluetoothIntents.addAction(BluetoothDevice.ACTION_UUID);
|
||||
bluetoothIntents.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
|
||||
bluetoothIntents.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
|
||||
bluetoothIntents.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
|
||||
|
@ -247,9 +266,20 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||
}
|
||||
|
||||
private void handleDeviceFound(BluetoothDevice device, short rssi) {
|
||||
ParcelUuid[] uuids = device.getUuids();
|
||||
if (uuids == null) {
|
||||
if (device.fetchUuidsWithSdp()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handleDeviceFound(device, rssi, uuids);
|
||||
}
|
||||
|
||||
|
||||
private void handleDeviceFound(BluetoothDevice device, short rssi, ParcelUuid[] uuids) {
|
||||
LOG.debug("found device: " + device.getName() + ", " + device.getAddress());
|
||||
if (LOG.isDebugEnabled()) {
|
||||
ParcelUuid[] uuids = device.getUuids();
|
||||
if (uuids != null && uuids.length > 0) {
|
||||
for (ParcelUuid uuid : uuids) {
|
||||
LOG.debug(" supports uuid: " + uuid.toString());
|
||||
|
@ -260,7 +290,7 @@ public class DiscoveryActivity extends GBActivity implements AdapterView.OnItemC
|
|||
return; // ignore already bonded devices
|
||||
}
|
||||
|
||||
GBDeviceCandidate candidate = new GBDeviceCandidate(device, rssi);
|
||||
GBDeviceCandidate candidate = new GBDeviceCandidate(device, rssi, uuids);
|
||||
DeviceType deviceType = DeviceHelper.getInstance().getSupportedType(candidate);
|
||||
if (deviceType.isSupported()) {
|
||||
candidate.setDeviceType(deviceType);
|
||||
|
|
|
@ -40,8 +40,13 @@ public class MiBand2Coordinator extends MiBandCoordinator {
|
|||
return Collections.singletonList(filter);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
if (candidate.supportsService(MiBand2Service.UUID_SERVICE_MIBAND2_SERVICE)) {
|
||||
return DeviceType.MIBAND2;
|
||||
}
|
||||
|
||||
// and a heuristic for now
|
||||
try {
|
||||
BluetoothDevice device = candidate.getDevice();
|
||||
|
|
|
@ -49,6 +49,7 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
|
|||
return Collections.singletonList(filter);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DeviceType getSupportedType(GBDeviceCandidate candidate) {
|
||||
String macAddress = candidate.getMacAddress().toUpperCase();
|
||||
|
|
|
@ -5,17 +5,22 @@ import android.os.Parcel;
|
|||
import android.os.ParcelUuid;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.AndroidUtils;
|
||||
|
||||
/**
|
||||
* A device candidate is a Bluetooth device that is not yet managed by
|
||||
|
@ -27,21 +32,25 @@ public class GBDeviceCandidate implements Parcelable {
|
|||
|
||||
private final BluetoothDevice device;
|
||||
private final short rssi;
|
||||
private final ParcelUuid[] serviceUuds;
|
||||
private DeviceType deviceType = DeviceType.UNKNOWN;
|
||||
|
||||
public GBDeviceCandidate(BluetoothDevice device, short rssi) {
|
||||
public GBDeviceCandidate(BluetoothDevice device, short rssi, ParcelUuid[] serviceUuds) {
|
||||
this.device = device;
|
||||
this.rssi = rssi;
|
||||
this.serviceUuds = mergeServiceUuids(serviceUuds, device.getUuids());
|
||||
}
|
||||
|
||||
private GBDeviceCandidate(Parcel in) {
|
||||
device = in.readParcelable(getClass().getClassLoader());
|
||||
rssi = (short) in.readInt();
|
||||
deviceType = DeviceType.valueOf(in.readString());
|
||||
|
||||
if (device == null) {
|
||||
throw new IllegalStateException("Unable to read state from Parcel");
|
||||
}
|
||||
rssi = (short) in.readInt();
|
||||
deviceType = DeviceType.valueOf(in.readString());
|
||||
|
||||
ParcelUuid[] uuids = AndroidUtils.toParcelUUids(in.readParcelableArray(getClass().getClassLoader()));
|
||||
serviceUuds = mergeServiceUuids(uuids, device.getUuids());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,8 +58,21 @@ public class GBDeviceCandidate implements Parcelable {
|
|||
dest.writeParcelable(device, 0);
|
||||
dest.writeInt(rssi);
|
||||
dest.writeString(deviceType.name());
|
||||
dest.writeArray(serviceUuds);
|
||||
}
|
||||
|
||||
public static final Creator<GBDeviceCandidate> CREATOR = new Creator<GBDeviceCandidate>() {
|
||||
@Override
|
||||
public GBDeviceCandidate createFromParcel(Parcel in) {
|
||||
return new GBDeviceCandidate(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GBDeviceCandidate[] newArray(int size) {
|
||||
return new GBDeviceCandidate[size];
|
||||
}
|
||||
};
|
||||
|
||||
public BluetoothDevice getDevice() {
|
||||
return device;
|
||||
}
|
||||
|
@ -67,9 +89,25 @@ public class GBDeviceCandidate implements Parcelable {
|
|||
return device != null ? device.getAddress() : GBApplication.getContext().getString(R.string._unknown_);
|
||||
}
|
||||
|
||||
private ParcelUuid[] mergeServiceUuids(ParcelUuid[] serviceUuds, ParcelUuid[] deviceUuids) {
|
||||
Set<ParcelUuid> uuids = new HashSet<>();
|
||||
if (serviceUuds != null) {
|
||||
uuids.addAll(Arrays.asList(serviceUuds));
|
||||
}
|
||||
if (deviceUuids != null) {
|
||||
uuids.addAll(Arrays.asList(deviceUuids));
|
||||
}
|
||||
return uuids.toArray(new ParcelUuid[0]);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ParcelUuid[] getServiceUuids() {
|
||||
return serviceUuds;
|
||||
}
|
||||
|
||||
public boolean supportsService(UUID aService) {
|
||||
ParcelUuid[] uuids = device.getUuids();
|
||||
if (uuids == null) {
|
||||
ParcelUuid[] uuids = getServiceUuids();
|
||||
if (uuids.length == 0) {
|
||||
LOG.warn("no cached services available for " + this);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||
|
||||
import android.os.ParcelUuid;
|
||||
import android.os.Parcelable;
|
||||
|
||||
public class AndroidUtils {
|
||||
public static ParcelUuid[] toParcelUUids(Parcelable[] uuids) {
|
||||
if (uuids == null) {
|
||||
return null;
|
||||
}
|
||||
ParcelUuid[] uuids2 = new ParcelUuid[uuids.length];
|
||||
System.arraycopy(uuids, 0, uuids2, 0, uuids.length);
|
||||
return uuids2;
|
||||
}
|
||||
}
|
|
@ -120,7 +120,7 @@ public class DeviceHelper {
|
|||
}
|
||||
|
||||
public GBDevice toSupportedDevice(BluetoothDevice device) {
|
||||
GBDeviceCandidate candidate = new GBDeviceCandidate(device, GBDevice.RSSI_UNKNOWN);
|
||||
GBDeviceCandidate candidate = new GBDeviceCandidate(device, GBDevice.RSSI_UNKNOWN, device.getUuids());
|
||||
|
||||
for (DeviceCoordinator coordinator : getAllCoordinators()) {
|
||||
if (coordinator.supports(candidate)) {
|
||||
|
|
Loading…
Reference in New Issue