Skip to content Skip to sidebar Skip to footer

Rxandroidble - Auto Connect Issue

I am using RxAndroidBle library: This code is working fine as expected, on click of Connect button on UI, it establishes connection. Issue coming up when I wanted the auto-connect

Solution 1:

There are multiple possible solutions to achieve the expected behaviour so the action will start on the first click on Connect button and if the connection will be lost to reconnect without user interaction.

What you basically want is to:

  1. Scan a single device
  2. When device is scanned—connect to it
  3. When connected—do your stuff
  4. If an error will happen—retry connection

There is a bug in Android regarding connecting to a device after BluetoothAdapter being switched on that needs to be addressed by scanning the device first if the disconnection happened because adapter was switched off. We will just complete a part of the flow in this situation and repeat from the beginning.

Observable<Boolean> canUseBleObservable = canUseBle();
subscription = scanSingleDevice() // first scan the device
        .flatMapObservable(this::connectAndDoStuff) // when scanned connect and do your stuff
        .takeUntil(canUseBleObservable.takeFirst(isReady -> !isReady)) // if the BLE will be not ready (off) then unsubscribe from scanning and connecting
        .delaySubscription(canUseBleObservable.takeFirst(isReady -> isReady)) // delay subscription to scanning and connecting till BLE is ready (subscribing goes from bottom to top)
        .retry() // if scan will emit an error (connection should not as it has `.retry()`) just resubscribe to the upstream
        .repeatWhen(observable -> observable) // if the upstream will complete (due to `.takeUntil()` as `connectAndDoStuff` does not complete on it's own)—resubscribe to the upstream
        .subscribe(
                aVoid -> { /* consume */ } // `aVoid` should be changed to your model/events emitted by `.connectAndDoStuff`// throwable -> {  } => should not happen since there is `retry()` in the upstream
        );

Other building blocks could look like this:

private Observable<Boolean> canUseBle() {
    return rxBleClient.observeStateChanges()
            .share() // share observing state changes.startWith(Observable.fromCallable(() -> rxBleClient.getState())) // on each subscription emit the current state.map(state -> state == RxBleClient.State.READY); // map to `true` when ready
}

private Single<RxBleDevice> scanSingleDevice() {
    return rxBleClient.scanBleDevices( // scan the device
            new ScanSettings.Builder().build(),
            new ScanFilter.Builder().setDeviceName("mydevice").build()
    )
            .map(ScanResult::getBleDevice)
            .take(1) // after the first device being scanned stop the scan.toSingle();
}

private Observable<Void> connectAndDoStuff(RxBleDevice rxBleDevice) {
    return rxBleDevice.establishConnection(false)
            .flatMap(rxBleConnection -> {
                // do your stuff
                return Observable.<Void>empty();
            })
            .repeat(); // if any error (going out of range) will happen then resubscribe from `.establishConnection()`
}

This is a simple decomposition of your use case. One could further complicate the flow if needed.

Post a Comment for "Rxandroidble - Auto Connect Issue"