Skip to content

Commit

Permalink
Merge pull request #281 from NordicSemiconductor/develop
Browse files Browse the repository at this point in the history
Release v1.11.1
  • Loading branch information
roshanrajaratnam authored Nov 25, 2020
2 parents 07bdaa5 + 20e8e7d commit b5d587b
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 87 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ If your device is using the Nordic Buttonless Service for switching from app mod
DFU bootloader mode, this library will handle switching automatically. In case your bootloader is
configured to advertise with incremented MAC address (that is you use Secure DFU and the device
is not bonded) this library will need to scan for the new `BluetoothDevice`. Starting from Android
Marshmallow, **location permission** is required and has to be granted in runtime before DFU is started.
Marshmallow, **location permission** is required and has to be granted in runtime before DFU is started.

Starting from Android 8.1.0, all scans done without a scan filter whilst the screen is turned off
will not return any scan results.

>Note: "ACCESS_BACKGROUND_LOCATION" permission would also be required to trigger a successful DFU
whilst the device screen is turned off, mainly to receive the scan results when scanning and connecting to the
peripheral in bootloader mode while the device screen is turned off.

#### Retrying
Starting from version 1.9.0 the library is able to retry a DFU update in case of an unwanted
Expand Down
4 changes: 2 additions & 2 deletions dfu/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ android {
defaultConfig {
minSdkVersion 18
targetSdkVersion 29
versionCode 24
versionCode 25
versionName VERSION_NAME
}

Expand All @@ -19,7 +19,7 @@ android {
}

dependencies {
implementation 'androidx.core:core:1.5.0-alpha01'
implementation 'androidx.core:core:1.5.0-alpha05'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
implementation 'androidx.annotation:annotation:1.1.0'
implementation 'com.google.code.gson:gson:2.8.6'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,98 +26,110 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.os.Build;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
* @see BootloaderScanner
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public class BootloaderScannerLollipop extends ScanCallback implements BootloaderScanner {
private final Object mLock = new Object();
private String mDeviceAddress;
private String mDeviceAddressIncremented;
private String mBootloaderAddress;
private boolean mFound;

@Override
public String searchFor(final String deviceAddress) {
final String firstBytes = deviceAddress.substring(0, 15);
final String lastByte = deviceAddress.substring(15); // assuming that the device address is correct
final String lastByteIncremented = String.format(Locale.US, "%02X", (Integer.valueOf(lastByte, 16) + ADDRESS_DIFF) & 0xFF);

mDeviceAddress = deviceAddress;
mDeviceAddressIncremented = firstBytes + lastByteIncremented;
mBootloaderAddress = null;
mFound = false;

// Add timeout
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(BootloaderScanner.TIMEOUT);
} catch (final InterruptedException e) {
// do nothing
}

if (mFound)
return;

mBootloaderAddress = null;
mFound = true;

// Notify the waiting thread
synchronized (mLock) {
mLock.notifyAll();
}
}
}, "Scanner timer").start();

final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null || adapter.getState() != BluetoothAdapter.STATE_ON)
return null;
final BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
if (scanner == null)
return null;
/*
* Scanning with filters does not work on Nexus 9 (Android 5.1). No devices are found and scanner terminates on timeout.
* We will match the device address in the callback method instead. It's not like it should be, but at least it works.
*/
//final List<ScanFilter> filters = new ArrayList<>();
//filters.add(new ScanFilter.Builder().setDeviceAddress(mDeviceAddress).build());
//filters.add(new ScanFilter.Builder().setDeviceAddress(mDeviceAddressIncremented).build());
final ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
scanner.startScan(/*filters*/ null, settings, this);

try {
synchronized (mLock) {
while (!mFound)
mLock.wait();
}
} catch (final InterruptedException e) {
// do nothing
}

scanner.stopScan(this);
return mBootloaderAddress;
}

@Override
public void onScanResult(final int callbackType, final ScanResult result) {
final String address = result.getDevice().getAddress();

if (mDeviceAddress.equals(address) || mDeviceAddressIncremented.equals(address)) {
mBootloaderAddress = address;
mFound = true;

// Notify the waiting thread
synchronized (mLock) {
mLock.notifyAll();
}
}
}
private final Object mLock = new Object();
private String mDeviceAddress;
private String mDeviceAddressIncremented;
private String mBootloaderAddress;
private boolean mFound;

@Override
public String searchFor(final String deviceAddress) {
final String firstBytes = deviceAddress.substring(0, 15);
final String lastByte = deviceAddress.substring(15); // assuming that the device address is correct
final String lastByteIncremented = String.format(Locale.US, "%02X", (Integer.valueOf(lastByte, 16) + ADDRESS_DIFF) & 0xFF);

mDeviceAddress = deviceAddress;
mDeviceAddressIncremented = firstBytes + lastByteIncremented;
mBootloaderAddress = null;
mFound = false;

// Add timeout
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(BootloaderScanner.TIMEOUT);
} catch (final InterruptedException e) {
// do nothing
}

if (mFound)
return;

mBootloaderAddress = null;
mFound = true;

// Notify the waiting thread
synchronized (mLock) {
mLock.notifyAll();
}
}
}, "Scanner timer").start();

final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null || adapter.getState() != BluetoothAdapter.STATE_ON)
return null;
final BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
if (scanner == null)
return null;
/*
* Android 8.1 onwards, stops unfiltered BLE scanning on screen off. Therefore we must add a filter to
* get scan results in case the device screen is turned off as this may affect users wanting scan/connect to the device in background.
* See {@linktourl https://android.googlesource.com/platform/packages/apps/Bluetooth/+/319aeae6f4ebd13678b4f77375d1804978c4a1e1}
*/
final ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
if (adapter.isOffloadedFilteringSupported() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
final List<ScanFilter> filters = new ArrayList<>();
filters.add(new ScanFilter.Builder().setDeviceAddress(mDeviceAddress).build());
filters.add(new ScanFilter.Builder().setDeviceAddress(mDeviceAddressIncremented).build());
scanner.startScan(filters, settings, this);
} else {
/*
* Scanning with filters does not work on Nexus 9 (Android 5.1). No devices are found and scanner terminates on timeout.
* We will match the device address in the callback method instead. It's not like it should be, but at least it works.
*/
scanner.startScan(null, settings, this);
}

try {
synchronized (mLock) {
while (!mFound)
mLock.wait();
}
} catch (final InterruptedException e) {
// do nothing
}

scanner.stopScan(this);
return mBootloaderAddress;
}

@Override
public void onScanResult(final int callbackType, final ScanResult result) {
final String address = result.getDevice().getAddress();

if (mDeviceAddress.equals(address) || mDeviceAddressIncremented.equals(address)) {
mBootloaderAddress = address;
mFound = true;

// Notify the waiting thread
synchronized (mLock) {
mLock.notifyAll();
}
}
}
}
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.11.0
VERSION_NAME=1.11.1
GROUP=no.nordicsemi.android

POM_DESCRIPTION=Device Firmware Update library
Expand Down

0 comments on commit b5d587b

Please sign in to comment.