RxAndroidBle - 如何断开所有连接的设备?

RxAndroidBle - How to disconnect all connected devices?

我正在使用很棒的 rxandroidble 库进行 BLE 控制。
我保持活动之间的联系。 在开始扫描之前,我想先断开所有连接的设备。 如果有很多连接,有时它不起作用。 这是我正在使用的解决方案:

public void doScan() {

    if (isScanning()) return;

    // disconnect all connected devices first:
    while(BleController.getDefault().getDisconnectTriggerSubject().hasObservers()){
        BleController.getDefault().getDisconnectTriggerSubject().onNext(null);
    }

    scanSubscription = rxBleClient.scanBleDevices(
            new ScanSettings.Builder()
                    .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                    .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
                    .build(),
            new ScanFilter.Builder()
                    // add custom filters if needed
                    .build()
    )
            .filter(rxBleScanResult -> !TextUtils.isEmpty(rxBleScanResult.getBleDevice().getName()))
            .observeOn(AndroidSchedulers.mainThread())
            .doOnUnsubscribe(this::clearSubscription)
            .subscribe(resultsAdapter::addScanResult, this::onScanFailure);

    updateButtonUIState();

}

BleController 使用主应用程序的上下文进行初始化,并保留 connectionObservabledisconnectTriggerSubjectrxBleClient.

有什么更好的解决方案? 如有任何帮助,我们将不胜感激!

从您的 post 我可以看出您将 BLE scanning/connection 逻辑与 UI/Activity 逻辑混合在一起。这可能是正确管理连接的问题。

你可以做的是将所有 BLE 逻辑放入你的 BleController 中,它已经有了一个好名字,但在你的情况下似乎是一个 BleObjectsContainer.

例如,您只能从 BleController 公开以 Activities 不需要处理的方式满足您的特定用例的可观察对象。即您的 BleController 可以处理扫描:

private final BehaviorRelay<Boolean> isScanningPublishRelay = BehaviorRelay.create(false); // a relay (that cannot emit an error) that emits when a scan is ongoing

private Observable<ScanResult> scanDevicesWithNonNullNameObs = rxBleClient.scanBleDevices(new ScanSettings.Builder().build())
        .filter(scanResult -> !TextUtils.isEmpty(scanResult.getBleDevice().getName()))
        .doOnSubscribe(() -> isScanningPublishRelay.call(true)) // when scan is subscribed/started emit true
        .doOnUnsubscribe(() -> isScanningPublishRelay.call(false)) // when scan is stopped emit false
        .subscribeOn(AndroidSchedulers.mainThread()) // the above emissions will happen on the same thread. should be serialized
        .unsubscribeOn(AndroidSchedulers.mainThread()) // the above emissions will happen on the same thread. should be serialized
        .share(); // share this observable so no matter how many places in the code will subscribe the scan is started once and `isScanningPublishRelay` is called once

public Observable<ScanResult> scanDevicesWithNonNullName() { // getter for the scan observable
    return scanDevicesWithNonNullNameObs;
}

除了扫描之外,它还会为每个需要它的 Activity 处理您的特定用例:

class ScanInProgress extends Throwable {
    // ...
}

public Observable<YourActivityUseCaseModel> doYourSpecificStuff(Observable<RxBleConnection> connectionObservable) {
    return Observable.merge(
            connectionObservable,
            isScanningPublishRelay
                    .takeFirst(aBoolean -> aBoolean)
                    .flatMap(ignored -> Observable.error(new ScanInProgress())) // this will only emit an error when a scan is ongoing
    )
            .flatMap(...); // do the rest of your stuff
}

通过这种方式,在您的活动中,您只需订阅他们需要的任何模型,并在一个专门用于它的地方处理 BLE (BleController)。

在上面的示例中,您需要提供 Observable<RxBleConnection>,但它可以通过许多不同的方式实现,并且也可以在 BleController 中进行管理,因此它不会在界面中公开。