Nearables on Android scan interval

Please correct me if I’m wrong, just to be sure.

It is not possible to change scan interval for Nearables on Android.

We have only following methods to change the scan interval:

setBackgroundScanPeriod() and setForegroundScanPeriod()

but it wil only work if we do monitoring or ranging:

startMonitoring() and startRanging()

but for nearalbes we have to do a discovery:

startNearableDiscovery()

Nearables and Eddystone discovery are equivalent to ranging, and thus use the foreground scan period. Probably worth documenting this better on our side, thanks for the feedback!

1 Like

What is the lowest scan interval?

If i set the interval e.g. to 7929 ms, I see it also in the logs:

ScanPeriodData{scanPeriodMillis=7929, waitTimeMillis=0}
02-29 23:41:30.306 16834-17719/com.sirris.wear.myapplication V/EstimoteSDK: com.estimote.sdk.service.BeaconService.startNearableScanning:395 Starting Nearable scanning
02-29 23:41:30.396 16834-17719/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:41:30.421 16834-16846/com.sirris.wear.myapplication D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=4
02-29 23:41:38.295 16834-17719/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:41:38.300 16834-17719/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:41:38.672 16834-17719/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:41:38.734 16834-16845/com.sirris.wear.myapplication D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=4
02-29 23:41:46.327 16834-17719/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:41:46.331 16834-17719/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:41:46.369 16834-17719/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:41:46.394 16834-17845/com.sirris.wear.myapplication D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=4
02-29 23:41:46.652 16834-16840/com.sirris.wear.myapplication W/art: Suspending all threads took: 155.072ms
02-29 23:41:54.306 16834-17719/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON

If set interval lower than 5000ms, e.g. 2773ms or any other low value, the real interval is about 5s, see logs below:

ScanPeriodData{scanPeriodMillis=2773, waitTimeMillis=0}
02-29 23:44:36.523 16834-20319/com.sirris.wear.myapplication V/EstimoteSDK: com.estimote.sdk.service.BeaconService.startNearableScanning:395 Starting Nearable scanning
02-29 23:44:36.599 16834-20319/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:44:36.624 16834-17845/com.sirris.wear.myapplication D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=4
02-29 23:44:41.606 16834-20319/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:44:41.615 16834-20319/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:44:41.782 16834-20319/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON
02-29 23:44:41.808 16834-17845/com.sirris.wear.myapplication D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=4
02-29 23:44:41.919 16834-16840/com.sirris.wear.myapplication W/art: Suspending all threads took: 84.113ms
02-29 23:44:46.735 16834-20319/com.sirris.wear.myapplication D/BluetoothAdapter: STATE_ON

On Android 5.0 (and later) devices capable of hardware-accelerated BLE scanning, the scan period is more of a hint, rather than hard limitation—the chip itself decides when to return scanning results to the phone. Most chips are pretty smart about that, and e.g. will return results less often if the results don’t change too much. On the other hand, they can also return results immediately, rather than wait for the scan to end, if they encounter a new beacon. So it’s both much more energy/CPU efficient, and can actually be more responsive than fully software defined scanning.

You can disable this feature by adding:

<meta-data android:name="disable_batch_scanning" android:value="true" />

inside the <application> section in your AndroidManifest.xml.

1 Like

Great! Thanks!

I tried it on Nexus 5 => it works. It strives to the value I set up, twice higher but already lower than 5s.
On LG Urbane W150 it doesn’t work. I don’t see any difference, it is still about 5s.

Where can I read more about BLE scanning for Android with such nuances as you described (disable_batch_scanning)?

You could also try force_old_scanning_api, this forces the use of the Android 4 API.

I got most of my knowledge about the Android 5.0 BLE API from this talk:

1 Like

Thanks for the link!

The force_old_scanning_api did not work. I used it alone and together with disable_batch_scanning, no difference on the watch.

Huh, weird. Maybe something about the Urbane’s Bluetooth stack? (It being a smart watch and all.)

Another question.

As I understood correctly, the estimote SDK returns only the last packet from the nearable after a scan is done, right?

Is it possible to write my own implementation of the scan for nearables where I collect all packets received during the scan? As I am missing some packets with moving=true flag.

You could drop down to the BluetoothLeScanner level and detect all the unprocessed Nearable packets. Gonna be quite some extra work though. And chance is, if our SDK can’t detect some of the “moving = true” packets, it’s because the device itself drops them.

1 Like

Now, it works.
Most likely, due to upgrading to a newer estimote sdk version.

Yup, we’ve made some improvements to the responsiveness of ranging. Glad it works for you! (:

To clarify some things:

  • disable_batch_scanning - have no effect on Nexus 5 - it does not have batch scanning anyway
  • force_old_scanning_api - enabling it would ignore disable_batch_scanning because old API did not support it.

When you dig down to Android source code you will find out that on Android 5.0 and higher old Bluetooth scanning API (first present in 4.3) is implemented internally using new API (BluetoothLeScanner).

Remember that these are internal undocumented flags, used for diagnostics and should not be used in production.

2 Likes