I need to scan ble
advertising permanently while i am not connected to my device to find it and know when connect to it (specific product). This scan is realized in foreground service to match 8.0 prerequisite.
To preserve a few battery, i want scan periodically (while respect the Android 7 limit of start amount/time). I see 2 differents implementations :
I want to do it with Rx style and not with the simple timer (i am not an RX expert). I don't know what solution is better/easier to be developed.
This must be transparent to the client and must keep the original RxAndroidBle
working, subscribe = start the process and unsubscribe = stop the process.
I suppose I have to use Obersable.interval
but i don't see how to manage this
Any snippet/ example?
The original Android BLE API has BluetoothLeScanner
class which allows to start a scan using one of four modes:
SCAN_MODE_LOW_LATENCY
—the scan is continuousSCAN_MODE_BALANCED
—the scan is working for 2 seconds every 5 secondsSCAN_MODE_LOW_POWER
—the scan is working for 0.5 second every 5 secondsSCAN_MODE_OPPORTUNISTIC
—the scan is working only when a different application starts itThe time measurements were performed by Nordic Semiconductors employee and released in a form of a comprehensive guide for Android BLE developers.
The RxAndroidBle
library also has a function RxBleClient.scanBleDevices(ScanSettings, ScanFilter...)
which accepts the same modes inside a ScanSettings
object.
If one would need to achieve different parameters of scanning it is possible to simply use a combintaion of Observable.takeUntil()
and Observable.repeatWhen()
:
Observable<ScanResult> lowLatencyScanObservable = rxBleClient.scanBleDevices(
new ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY) // make sure that the scanning will be always on by default
.build()
);
Observable<ScanResult> periodicalScan = lowLatencyScanObservable
.takeUntil(Observable.timer(SCAN_TIME, SCAN_TIMEUNIT)) // scan for a specific amount of time and then unsubscribe to the upstream
.repeatWhen(completionObservable -> completionObservable.delay(PAUSE_TIME, PAUSE_TIMEUNIT)); // when the upstream will complete because of `takeUntil()` wait for the pause time and resubscribe to the upstream
One would still need to remember about the undocumented "feature" of API 24+ which prevents starting more than 5 scans during a 30 seconds period.