Skip to content

Commit

Permalink
Merge pull request #100 from NordicSemiconductor/develop
Browse files Browse the repository at this point in the history
Version 1.5.0
  • Loading branch information
philips77 authored Jun 7, 2021
2 parents 7b35496 + b838fff commit cd137c1
Show file tree
Hide file tree
Showing 12 changed files with 123 additions and 142 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ The compat library may be found on Maven Central repository. Add it to your proj
following dependency:

```Groovy
implementation 'no.nordicsemi.android.support.v18:scanner:1.4.5'
implementation 'no.nordicsemi.android.support.v18:scanner:1.5.0'
```

Projects not migrated to Android Jetpack should use version 1.3.1, which is feature-equal to 1.4.0.
Expand All @@ -48,6 +48,11 @@ allprojects {
}
```

Since version 1.5 you will need to [enable desugaring of Java 8 language features](https://developer.android.com/studio/write/java8-support.html#supported_features)
if you have not already done so.(And if you are releasing an Android library, then anyone who uses
that library will also have to enable desugaring.) We expect for nearly all Android projects to have
already enabled desugaring. But if this causes problems for you, please use version 1.4.5.

## API

The Scanner Compat API is very similar to the original one, known from Android Oreo.
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
# org.gradle.parallel=true
android.useAndroidX=true

VERSION_NAME=1.4.5
VERSION_NAME=1.5.0
GROUP=no.nordicsemi.android.support.v18

POM_DESCRIPTION=Android Bluetooth LE Scanner Compat library
Expand Down
4 changes: 2 additions & 2 deletions scanner/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ android {
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
*
* @see ScanFilter
*/
@SuppressWarnings("WeakerAccess")
@SuppressWarnings({"WeakerAccess", "unused"})
public abstract class BluetoothLeScannerCompat {

/**
Expand Down Expand Up @@ -129,7 +129,7 @@ public final void startScan(@NonNull final ScanCallback callback) {
throw new IllegalArgumentException("callback is null");
}
final Handler handler = new Handler(Looper.getMainLooper());
startScanInternal(Collections.<ScanFilter>emptyList(), new ScanSettings.Builder().build(),
startScanInternal(Collections.emptyList(), new ScanSettings.Builder().build(),
callback, handler);
}

Expand All @@ -156,7 +156,7 @@ public final void startScan(@Nullable final List<ScanFilter> filters,
throw new IllegalArgumentException("callback is null");
}
final Handler handler = new Handler(Looper.getMainLooper());
startScanInternal(filters != null ? filters : Collections.<ScanFilter>emptyList(),
startScanInternal(filters != null ? filters : Collections.emptyList(),
settings != null ? settings : new ScanSettings.Builder().build(),
callback, handler);
}
Expand Down Expand Up @@ -185,7 +185,7 @@ public final void startScan(@Nullable final List<ScanFilter> filters,
if (callback == null) {
throw new IllegalArgumentException("callback is null");
}
startScanInternal(filters != null ? filters : Collections.<ScanFilter>emptyList(),
startScanInternal(filters != null ? filters : Collections.emptyList(),
settings != null ? settings : new ScanSettings.Builder().build(),
callback, handler != null ? handler : new Handler(Looper.getMainLooper()));
}
Expand Down Expand Up @@ -278,7 +278,7 @@ public final void startScan(@Nullable final List<ScanFilter> filters,
if (context == null) {
throw new IllegalArgumentException("context is null");
}
startScanInternal(filters != null ? filters : Collections.<ScanFilter>emptyList(),
startScanInternal(filters != null ? filters : Collections.emptyList(),
settings != null ? settings : new ScanSettings.Builder().build(),
context, callbackIntent, requestCode);
}
Expand Down Expand Up @@ -424,17 +424,6 @@ public final void stopScan(@NonNull final Context context,
/** A collection of scan result of devices in range. */
@NonNull private final Map<String, ScanResult> devicesInRange = new HashMap<>();

@NonNull
private final Runnable flushPendingScanResultsTask = new Runnable() {
@Override
public void run() {
if (!scanningStopped) {
flushPendingScanResults();
handler.postDelayed(this, scanSettings.getReportDelayMillis());
}
}
};

/** A task, called periodically, that notifies about match lost. */
@NonNull
private final Runnable matchLostNotifierTask = new Runnable() {
Expand All @@ -448,12 +437,7 @@ public void run() {
final ScanResult result = iterator.next();
if (result.getTimestampNanos() < now - scanSettings.getMatchLostDeviceTimeout()) {
iterator.remove();
handler.post(new Runnable() {
@Override
public void run() {
scanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST, result);
}
});
handler.post(() -> scanCallback.onScanResult(ScanSettings.CALLBACK_TYPE_MATCH_LOST, result));
}
}

Expand Down Expand Up @@ -488,6 +472,15 @@ public void run() {
final long delay = settings.getReportDelayMillis();
emulateBatching = delay > 0 && (!offloadedBatchingSupported || !settings.getUseHardwareBatchingIfSupported());
if (emulateBatching) {
final Runnable flushPendingScanResultsTask = new Runnable() {
@Override
public void run() {
if (!scanningStopped) {
flushPendingScanResults();
handler.postDelayed(this, scanSettings.getReportDelayMillis());
}
}
};
handler.postDelayed(flushPendingScanResultsTask, delay);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import android.Manifest;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
Expand Down Expand Up @@ -234,22 +233,14 @@ private void setPowerSaveSettings() {
}
}

private final BluetoothAdapter.LeScanCallback scanCallback = new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
final ScanResult scanResult = new ScanResult(device, ScanRecord.parseFromBytes(scanRecord),
rssi, SystemClock.elapsedRealtimeNanos());

synchronized (wrappers) {
final Collection<ScanCallbackWrapper> scanCallbackWrappers = wrappers.values();
for (final ScanCallbackWrapper wrapper : scanCallbackWrappers) {
wrapper.handler.post(new Runnable() {
@Override
public void run() {
wrapper.handleScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult);
}
});
}
private final BluetoothAdapter.LeScanCallback scanCallback = (device, rssi, scanRecord) -> {
final ScanResult scanResult = new ScanResult(device, ScanRecord.parseFromBytes(scanRecord),
rssi, SystemClock.elapsedRealtimeNanos());

synchronized (wrappers) {
final Collection<ScanCallbackWrapper> scanCallbackWrappers = wrappers.values();
for (final ScanCallbackWrapper wrapper : scanCallbackWrappers) {
wrapper.handler.post(() -> wrapper.handleScanResult(ScanSettings.CALLBACK_TYPE_ALL_MATCHES, scanResult));
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,73 +249,63 @@ private ScanCallbackWrapperLollipop(final boolean offloadedBatchingSupported,

@Override
public void onScanResult(final int callbackType, final android.bluetooth.le.ScanResult nativeScanResult) {
handler.post(new Runnable() {
@Override
public void run() {
final BluetoothLeScannerImplLollipop scannerImpl =
(BluetoothLeScannerImplLollipop) BluetoothLeScannerCompat.getScanner();
final ScanResult result = scannerImpl.fromNativeScanResult(nativeScanResult);
handleScanResult(callbackType, result);
}
handler.post(() -> {
final BluetoothLeScannerImplLollipop scannerImpl =
(BluetoothLeScannerImplLollipop) BluetoothLeScannerCompat.getScanner();
final ScanResult result = scannerImpl.fromNativeScanResult(nativeScanResult);
handleScanResult(callbackType, result);
});
}

@Override
public void onBatchScanResults(final List<android.bluetooth.le.ScanResult> nativeScanResults) {
handler.post(new Runnable() {
@Override
public void run() {
// On several phones the onBatchScanResults is called twice for every batch.
// Skip the second call if came to early.
final long now = SystemClock.elapsedRealtime();
if (lastBatchTimestamp > now - scanSettings.getReportDelayMillis() + 5) {
return;
}
lastBatchTimestamp = now;

final BluetoothLeScannerImplLollipop scannerImpl =
(BluetoothLeScannerImplLollipop) BluetoothLeScannerCompat.getScanner();
final List<ScanResult> results = scannerImpl.fromNativeScanResults(nativeScanResults);
handleScanResults(results);
handler.post(() -> {
// On several phones the onBatchScanResults is called twice for every batch.
// Skip the second call if came to early.
final long now = SystemClock.elapsedRealtime();
if (lastBatchTimestamp > now - scanSettings.getReportDelayMillis() + 5) {
return;
}
lastBatchTimestamp = now;

final BluetoothLeScannerImplLollipop scannerImpl =
(BluetoothLeScannerImplLollipop) BluetoothLeScannerCompat.getScanner();
final List<ScanResult> results = scannerImpl.fromNativeScanResults(nativeScanResults);
handleScanResults(results);
});
}

@Override
public void onScanFailed(final int errorCode) {
handler.post(new Runnable() {
@Override
@RequiresPermission(allOf = {Manifest.permission.BLUETOOTH_ADMIN, Manifest.permission.BLUETOOTH})
public void run() {
// We were able to determine offloaded batching and filtering before we started scan,
// but there is no method checking if callback types FIRST_MATCH and MATCH_LOST
// are supported. We get an error here it they are not.
if (scanSettings.getUseHardwareCallbackTypesIfSupported()
&& scanSettings.getCallbackType() != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
// On Nexus 6 with Android 6.0 (MPA44G, M Pre-release 3) the errorCode = 5 (SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES)
// On Pixel 2 with Android 9.0 the errorCode = 4 (SCAN_FAILED_FEATURE_UNSUPPORTED)

// This feature seems to be not supported on your phone.
// Let's try to do pretty much the same in the code.
scanSettings.disableUseHardwareCallbackTypes();

final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
try {
scanner.stopScan(scanCallback);
} catch (final Exception e) {
// Ignore
}
try {
scanner.startScanInternal(filters, scanSettings, scanCallback, handler);
} catch (final Exception e) {
// Ignore
}
return;
handler.post(() -> {
// We were able to determine offloaded batching and filtering before we started scan,
// but there is no method checking if callback types FIRST_MATCH and MATCH_LOST
// are supported. We get an error here it they are not.
if (scanSettings.getUseHardwareCallbackTypesIfSupported()
&& scanSettings.getCallbackType() != ScanSettings.CALLBACK_TYPE_ALL_MATCHES) {
// On Nexus 6 with Android 6.0 (MPA44G, M Pre-release 3) the errorCode = 5 (SCAN_FAILED_OUT_OF_HARDWARE_RESOURCES)
// On Pixel 2 with Android 9.0 the errorCode = 4 (SCAN_FAILED_FEATURE_UNSUPPORTED)

// This feature seems to be not supported on your phone.
// Let's try to do pretty much the same in the code.
scanSettings.disableUseHardwareCallbackTypes();

final BluetoothLeScannerCompat scanner = BluetoothLeScannerCompat.getScanner();
try {
scanner.stopScan(scanCallback);
} catch (final Exception e) {
// Ignore
}

// else, notify user application
handleScanError(errorCode);
try {
scanner.startScanInternal(filters, scanSettings, scanCallback, handler);
} catch (final Exception e) {
// Ignore
}
return;
}

// else, notify user application
handleScanError(errorCode);
});
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
throw new IllegalStateException("BT le scanner not available");

final ScanSettings nonNullSettings = settings != null ? settings : new ScanSettings.Builder().build();
final List<ScanFilter> nonNullFilters = filters != null ? filters : Collections.<ScanFilter>emptyList();
final List<ScanFilter> nonNullFilters = filters != null ? filters : Collections.emptyList();

final android.bluetooth.le.ScanSettings nativeSettings = toNativeScanSettings(adapter, nonNullSettings, false);
List<android.bluetooth.le.ScanFilter> nativeFilters = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ static <T> String toString(@Nullable final Map<T, byte[]> map) {
while (it.hasNext()) {
final Map.Entry<T, byte[]> entry = it.next();
final Object key = entry.getKey();
//noinspection SuspiciousMethodCalls
buffer.append(key).append("=").append(Arrays.toString(map.get(key)));
if (it.hasNext()) {
buffer.append(", ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
@Nullable private Context service;

private long lastBatchTimestamp;
private long reportDelay;
private final long reportDelay;

/**
* Creates the {@link PendingIntent} executor that will be used from a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,25 @@ public final class ScanResult implements Parcelable {
static final int ET_CONNECTABLE_MASK = 0x01;

// Remote Bluetooth device.
@SuppressWarnings("NullableProblems")
@NonNull
private BluetoothDevice device;
private final BluetoothDevice device;

// Scan record, including advertising data and scan response data.
@Nullable
private ScanRecord scanRecord;

// Received signal strength.
private int rssi;
private final int rssi;

// Device timestamp when the result was last seen.
private long timestampNanos;
private final long timestampNanos;

private int eventType;
private int primaryPhy;
private int secondaryPhy;
private int advertisingSid;
private int txPower;
private int periodicAdvertisingInterval;
private final int eventType;
private final int primaryPhy;
private final int secondaryPhy;
private final int advertisingSid;
private final int txPower;
private final int periodicAdvertisingInterval;

/**
* Constructs a new ScanResult.
Expand Down Expand Up @@ -155,7 +154,18 @@ public ScanResult(@NonNull final BluetoothDevice device, final int eventType,
}

private ScanResult(final Parcel in) {
readFromParcel(in);
device = BluetoothDevice.CREATOR.createFromParcel(in);
if (in.readInt() == 1) {
scanRecord = ScanRecord.parseFromBytes(in.createByteArray());
}
rssi = in.readInt();
timestampNanos = in.readLong();
eventType = in.readInt();
primaryPhy = in.readInt();
secondaryPhy = in.readInt();
advertisingSid = in.readInt();
txPower = in.readInt();
periodicAdvertisingInterval = in.readInt();
}

@Override
Expand All @@ -177,21 +187,6 @@ public void writeToParcel(final Parcel dest, final int flags) {
dest.writeInt(periodicAdvertisingInterval);
}

private void readFromParcel(final Parcel in) {
device = BluetoothDevice.CREATOR.createFromParcel(in);
if (in.readInt() == 1) {
scanRecord = ScanRecord.parseFromBytes(in.createByteArray());
}
rssi = in.readInt();
timestampNanos = in.readLong();
eventType = in.readInt();
primaryPhy = in.readInt();
secondaryPhy = in.readInt();
advertisingSid = in.readInt();
txPower = in.readInt();
periodicAdvertisingInterval = in.readInt();
}

@Override
public int describeContents() {
return 0;
Expand Down
Loading

0 comments on commit cd137c1

Please sign in to comment.