34

I am using pixel with latest android 8.1.0 update.

I am facing issue related to BLE advertisement scanning. Whenever I turned off the screen(i.e power button press) my scanning will stop. it will restart immediately after turn on the screen.

I have checked latest code for BLE. google newly introduce this feature (Reference Link).

Is there any way to skip this part, I mean scan should not stop regardless of the screen on or off.

Tim
  • 41,901
  • 18
  • 127
  • 145
Parth
  • 1,908
  • 1
  • 19
  • 37

4 Answers4

53

As of Android 8.1, unfiltered bluetooth scans are blocked when the screen is turned off. While it is surprising for such a dramatic change to be made in a minor release of Android, this is certainly an intended change based on the comments in the commit: Stop unfiltered BLE scans when the screen goes off.

The workaround is to use a ScanFilter with all scans. The new 8.1 operating system code simply verifies that any scans active when the screen is off have at least one scan filter. If those conditions are met the scan results are delivered as in Android 8.0.x and earlier.

In order to set up such a scan, you must use the APIs introduced in Android 5.0 and create a ScanFilter with each scan. Below is a filter that will find manufacturer advertisements for any device from Apple with manufacturer ID 0x004c (this will include iBeacons):

ScanFilter.Builder builder = new ScanFilter.Builder();
builder.setManufacturerData(0x004c, new byte[] {});
ScanFilter filter = builder.build();

Similarly, if you are interested in GATT Service advertisements (like the kind used with Eddystone beacons) you can search for a GATT Service UUID with a filter like this:

ScanFilter.Builder builder = new ScanFilter.Builder();
String serviceUuidString = "0000feaa-0000-1000-8000-00805f9b34fb";
String serviceUuidMaskString = "FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF";
ParcelUuid parcelUuid = ParcelUuid.fromString(serviceUuidString);
ParcelUuid parcelUuidMask = ParcelUuid.fromString(serviceUuidMaskString);
builder.setServiceUuid(parcelUuid, parcelUuidMask);
ScanFilter filter = builder.build();

If needed, you can add multiple filters to a single scan, and any that match will return results. The only real limitation here is that you must know all of the manufacturer codes or all of the GATT Service UUIDs that you might match up front, at least when scanning with the screen off.

You start your scan with code like this:

bluetoothAdapter.getBluetoothLeScanner().startScan(filters, settings, scanCallback);

EDIT: It is also possible to do this with an empty ScanFilter that looks like this:

ScanFilter.Builder builder = new ScanFilter.Builder();
ScanFilter filter = builder.build();

If you use such a scan filter, it will match any advertising packet, and still allow detections with the screen off on Android 8.1, effectively giving you the same behavior on Android 8.0.x and earlier.

EDIT 2: On the Galaxy Note 9 with Android 8.1 and perhaps other Samsung devices with 8.1, scans are blocked with the screen off even with an empty scan filter. Scans are allowed with the screen off with a non-empty scan filter as described above.

davidgyoung
  • 63,876
  • 14
  • 121
  • 204
  • 1
    Thank you very much! The only thing, the filter should be wrapped into the list, like - `final List filters = Collections.singletonList(new Builder().build());` – Vagif Mar 14 '18 at 05:24
  • I tried this on the galaxy S9+ with android 9, it scans when the phone is locked when I add the mac in the scanfilters but not with serviceuuid and service uuidmask, is it necessary to do this via mac? – Divye Shah Feb 10 '19 at 09:18
  • 1
    Hey, I'm having the issue of no scans on the background, while I have a scanfilter set. I also haven't seen the message that it will stop scanning because no filter is set. `BluetoothLeScanFilter [mDeviceName=null, mDeviceAddress=null, mUuid=null, mUuidMask=null, mServiceDataUuid=null, mServiceData=null, mServiceDataMask=null, mManufacturerId=4c, mManufacturerData=02 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00, mManufacturerDataMask=FF FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00]` – vliedel Mar 25 '19 at 11:44
  • 1
    Update: it only seems to stop giving results because i also added some other filters, while i do get results when screen is on. Do they act different when screen is off? – vliedel Mar 25 '19 at 11:55
  • @vliedel, I'd suggest opening a new question showing all the info above, your code, and also including logs showing the advertisement bytes scanned in the foreground. That way we can validate your scan filter is correct for what you are expecting to see. Please also include your device model and os version. – davidgyoung Mar 25 '19 at 18:56
  • @davidgyoung Thanks for the answer, the Edit 2 was exactly my problem on the Samsung Galaxy J7! – Nylsoo Apr 23 '19 at 11:48
  • @davidgyoung I am facing issues in Samsung Note 8 with Android 9. I used proper scan filters for iBeacon and Eddystone(As mentioned in the latest beacon library). In this case, my advertisements are not detecting with that filter(advertisement is non iBeacon and non-Eddystone formate). Can you please help in this case? – Parth Oct 09 '19 at 07:26
  • @Parth, please create a new question. Since you say "advertisement is non iBeacon and non-Eddystone format" please include the format in your question and note whether you can detect in the foreground (where filters are not required) – davidgyoung Oct 09 '19 at 17:12
2

I faced the same issue. I had Scan filters in order to scan BLE devices even if the screen were locked. But on Samsung devices it didn't work, so I search on Samsung forum and I discovered Knox SDK (https://seap.samsung.com/sdk/knox-android).

And it was the solution of my problem. All you have to do is add it to your app, create a license and activate it and finally use this method addPackageToBatteryOptimizationWhiteList to unlock the scan when the Samsung device screen is lock.

yozzy
  • 344
  • 2
  • 15
  • Is this true even for **non-Enterprise** phones? This could make sense, but Knox is Samsung's Enterprise Management feature, so I am skeptical that this would work for non-Enterprise simple consumer phones. – swooby Dec 19 '19 at 21:49
  • I tried this and I observed that it made no difference. :/ – swooby Jan 04 '20 at 01:30
  • I also tried to add Knox SDK, but NO difference made...! – Muhamed Riyas M Oct 15 '20 at 06:05
0

Obviously not, unless they missed something. But it will still work in the background if you have scan filters, which you should have anyway. So is it really an issue?

Emil
  • 16,784
  • 2
  • 41
  • 52
  • In Android 8.0.0 all things are working fine, background update also.I don't think so it is related to scanning method or filter. – Parth Jan 03 '18 at 14:16
0

in android 11 scanFilter can't being null you need to set something then will working like:

List<ScanFilter> filterList = new ArrayList<>();
        filterList.add(new ScanFilter.Builder().setDeviceAddress(address).build());
BluetoothAdapter.getBluetoothLeScanner().startScan(filterList, scanSettings, scanCallback);
nobody
  • 1