Skip to content

Commit b68884c

Browse files
committed
Merge branch 'release' of github.com:NordicSemiconductor/Android-DFU-Library into release
2 parents 5c37b4a + b5d587b commit b68884c

File tree

4 files changed

+106
-87
lines changed

4 files changed

+106
-87
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ If your device is using the Nordic Buttonless Service for switching from app mod
2929
DFU bootloader mode, this library will handle switching automatically. In case your bootloader is
3030
configured to advertise with incremented MAC address (that is you use Secure DFU and the device
3131
is not bonded) this library will need to scan for the new `BluetoothDevice`. Starting from Android
32-
Marshmallow, **location permission** is required and has to be granted in runtime before DFU is started.
32+
Marshmallow, **location permission** is required and has to be granted in runtime before DFU is started.
33+
34+
Starting from Android 8.1.0, all scans done without a scan filter whilst the screen is turned off
35+
will not return any scan results.
36+
37+
>Note: "ACCESS_BACKGROUND_LOCATION" permission would also be required to trigger a successful DFU
38+
whilst the device screen is turned off, mainly to receive the scan results when scanning and connecting to the
39+
peripheral in bootloader mode while the device screen is turned off.
3340

3441
#### Retrying
3542
Starting from version 1.9.0 the library is able to retry a DFU update in case of an unwanted

dfu/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ android {
66
defaultConfig {
77
minSdkVersion 18
88
targetSdkVersion 29
9-
versionCode 24
9+
versionCode 25
1010
versionName VERSION_NAME
1111
}
1212

@@ -19,7 +19,7 @@ android {
1919
}
2020

2121
dependencies {
22-
implementation 'androidx.core:core:1.5.0-alpha01'
22+
implementation 'androidx.core:core:1.5.0-alpha05'
2323
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
2424
implementation 'androidx.annotation:annotation:1.1.0'
2525
implementation 'com.google.code.gson:gson:2.8.6'

dfu/src/main/java/no/nordicsemi/android/dfu/internal/scanner/BootloaderScannerLollipop.java

Lines changed: 95 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -26,98 +26,110 @@
2626
import android.bluetooth.BluetoothAdapter;
2727
import android.bluetooth.le.BluetoothLeScanner;
2828
import android.bluetooth.le.ScanCallback;
29+
import android.bluetooth.le.ScanFilter;
2930
import android.bluetooth.le.ScanResult;
3031
import android.bluetooth.le.ScanSettings;
3132
import android.os.Build;
3233

34+
import java.util.ArrayList;
35+
import java.util.List;
3336
import java.util.Locale;
3437

3538
/**
3639
* @see BootloaderScanner
3740
*/
3841
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
3942
public class BootloaderScannerLollipop extends ScanCallback implements BootloaderScanner {
40-
private final Object mLock = new Object();
41-
private String mDeviceAddress;
42-
private String mDeviceAddressIncremented;
43-
private String mBootloaderAddress;
44-
private boolean mFound;
45-
46-
@Override
47-
public String searchFor(final String deviceAddress) {
48-
final String firstBytes = deviceAddress.substring(0, 15);
49-
final String lastByte = deviceAddress.substring(15); // assuming that the device address is correct
50-
final String lastByteIncremented = String.format(Locale.US, "%02X", (Integer.valueOf(lastByte, 16) + ADDRESS_DIFF) & 0xFF);
51-
52-
mDeviceAddress = deviceAddress;
53-
mDeviceAddressIncremented = firstBytes + lastByteIncremented;
54-
mBootloaderAddress = null;
55-
mFound = false;
56-
57-
// Add timeout
58-
new Thread(new Runnable() {
59-
@Override
60-
public void run() {
61-
try {
62-
Thread.sleep(BootloaderScanner.TIMEOUT);
63-
} catch (final InterruptedException e) {
64-
// do nothing
65-
}
66-
67-
if (mFound)
68-
return;
69-
70-
mBootloaderAddress = null;
71-
mFound = true;
72-
73-
// Notify the waiting thread
74-
synchronized (mLock) {
75-
mLock.notifyAll();
76-
}
77-
}
78-
}, "Scanner timer").start();
79-
80-
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
81-
if (adapter == null || adapter.getState() != BluetoothAdapter.STATE_ON)
82-
return null;
83-
final BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
84-
if (scanner == null)
85-
return null;
86-
/*
87-
* Scanning with filters does not work on Nexus 9 (Android 5.1). No devices are found and scanner terminates on timeout.
88-
* We will match the device address in the callback method instead. It's not like it should be, but at least it works.
89-
*/
90-
//final List<ScanFilter> filters = new ArrayList<>();
91-
//filters.add(new ScanFilter.Builder().setDeviceAddress(mDeviceAddress).build());
92-
//filters.add(new ScanFilter.Builder().setDeviceAddress(mDeviceAddressIncremented).build());
93-
final ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
94-
scanner.startScan(/*filters*/ null, settings, this);
95-
96-
try {
97-
synchronized (mLock) {
98-
while (!mFound)
99-
mLock.wait();
100-
}
101-
} catch (final InterruptedException e) {
102-
// do nothing
103-
}
104-
105-
scanner.stopScan(this);
106-
return mBootloaderAddress;
107-
}
108-
109-
@Override
110-
public void onScanResult(final int callbackType, final ScanResult result) {
111-
final String address = result.getDevice().getAddress();
112-
113-
if (mDeviceAddress.equals(address) || mDeviceAddressIncremented.equals(address)) {
114-
mBootloaderAddress = address;
115-
mFound = true;
116-
117-
// Notify the waiting thread
118-
synchronized (mLock) {
119-
mLock.notifyAll();
120-
}
121-
}
122-
}
43+
private final Object mLock = new Object();
44+
private String mDeviceAddress;
45+
private String mDeviceAddressIncremented;
46+
private String mBootloaderAddress;
47+
private boolean mFound;
48+
49+
@Override
50+
public String searchFor(final String deviceAddress) {
51+
final String firstBytes = deviceAddress.substring(0, 15);
52+
final String lastByte = deviceAddress.substring(15); // assuming that the device address is correct
53+
final String lastByteIncremented = String.format(Locale.US, "%02X", (Integer.valueOf(lastByte, 16) + ADDRESS_DIFF) & 0xFF);
54+
55+
mDeviceAddress = deviceAddress;
56+
mDeviceAddressIncremented = firstBytes + lastByteIncremented;
57+
mBootloaderAddress = null;
58+
mFound = false;
59+
60+
// Add timeout
61+
new Thread(new Runnable() {
62+
@Override
63+
public void run() {
64+
try {
65+
Thread.sleep(BootloaderScanner.TIMEOUT);
66+
} catch (final InterruptedException e) {
67+
// do nothing
68+
}
69+
70+
if (mFound)
71+
return;
72+
73+
mBootloaderAddress = null;
74+
mFound = true;
75+
76+
// Notify the waiting thread
77+
synchronized (mLock) {
78+
mLock.notifyAll();
79+
}
80+
}
81+
}, "Scanner timer").start();
82+
83+
final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
84+
if (adapter == null || adapter.getState() != BluetoothAdapter.STATE_ON)
85+
return null;
86+
final BluetoothLeScanner scanner = adapter.getBluetoothLeScanner();
87+
if (scanner == null)
88+
return null;
89+
/*
90+
* Android 8.1 onwards, stops unfiltered BLE scanning on screen off. Therefore we must add a filter to
91+
* get scan results in case the device screen is turned off as this may affect users wanting scan/connect to the device in background.
92+
* See {@linktourl https://android.googlesource.com/platform/packages/apps/Bluetooth/+/319aeae6f4ebd13678b4f77375d1804978c4a1e1}
93+
*/
94+
final ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
95+
if (adapter.isOffloadedFilteringSupported() && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
96+
final List<ScanFilter> filters = new ArrayList<>();
97+
filters.add(new ScanFilter.Builder().setDeviceAddress(mDeviceAddress).build());
98+
filters.add(new ScanFilter.Builder().setDeviceAddress(mDeviceAddressIncremented).build());
99+
scanner.startScan(filters, settings, this);
100+
} else {
101+
/*
102+
* Scanning with filters does not work on Nexus 9 (Android 5.1). No devices are found and scanner terminates on timeout.
103+
* We will match the device address in the callback method instead. It's not like it should be, but at least it works.
104+
*/
105+
scanner.startScan(null, settings, this);
106+
}
107+
108+
try {
109+
synchronized (mLock) {
110+
while (!mFound)
111+
mLock.wait();
112+
}
113+
} catch (final InterruptedException e) {
114+
// do nothing
115+
}
116+
117+
scanner.stopScan(this);
118+
return mBootloaderAddress;
119+
}
120+
121+
@Override
122+
public void onScanResult(final int callbackType, final ScanResult result) {
123+
final String address = result.getDevice().getAddress();
124+
125+
if (mDeviceAddress.equals(address) || mDeviceAddressIncremented.equals(address)) {
126+
mBootloaderAddress = address;
127+
mFound = true;
128+
129+
// Notify the waiting thread
130+
synchronized (mLock) {
131+
mLock.notifyAll();
132+
}
133+
}
134+
}
123135
}

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# org.gradle.parallel=true
1919
android.useAndroidX=true
2020

21-
VERSION_NAME=1.11.0
21+
VERSION_NAME=1.11.1
2222
GROUP=no.nordicsemi.android
2323

2424
POM_DESCRIPTION=Device Firmware Update library

0 commit comments

Comments
 (0)