RxAndroidBle-自动连接问题 [英] RxAndroidBle - Auto connect issue

查看:526
本文介绍了RxAndroidBle-自动连接问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用RxAndroidBle库:

I am using RxAndroidBle library:

此代码按预期工作正常,单击UI上的连接"按钮,即可建立连接.

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 to the device when the device comes back to range. I don’t want to click on Connect button again.

是否存在类似的功能? "true"标志对我有帮助吗(如果是的话)如何实现?请提出建议. rxBleDevice.establishConnection(true);

is there any functionality exists like that ? does ’true’ flag helps me here, if yes, how to implement it ? Suggestion please. rxBleDevice.establishConnection(true);

如果我使用rxBleDevice.establishConnection(true)而不是"false",那么我将得到以下错误提示,请帮助:

If I use rxBleDevice.establishConnection(true), instead of ‘false’, I am getting below error, please help:

RxBleLog.setLogLevel(RxBleLog.VERBOSE);
scanSubscription = rxBleClient.scanBleDevices(
        new ScanSettings.Builder()
                .setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
                .setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
                .build(),
        new ScanFilter.Builder().setDeviceName("mydevice").build()
).take(1).subscribe(
        scanResult -> {
                final RxBleDevice rxBleDevice = scanResult.getBleDevice();
                // connect to device
                final Observable<RxBleConnection> connection = rxBleDevice.establishConnection(false);
                connection
                        .subscribe(rxBleConnection -> {
                                    DeviceInformation deviceInformation = new DeviceInformation();
                                    deviceInformation.setName(rxBleDevice.getName());
                                    scanSubscription.unsubscribe();
                                },
                                throwable -> {
                                    throwable.printStackTrace();
                                    System.out.println(throwable);
                                }

                        );
        }
);


false
------

D/RxBle#ClientOperationQueue:   QUEUED ScanOperationApi21(226148850)
D/RxBle#ClientOperationQueue:  STARTED ScanOperationApi21(226148850)
I/Choreographer: Skipped 240 frames!  The application may be doing too much work on its main thread.
I/RxBle#QueueOperation: Scan operation is requested to start.
D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=6
D/RxBle#ClientOperationQueue: FINISHED ScanOperationApi21(226148850)
D/BluetoothLeScanner: onScanResult() - ScanResult{mDevice=6F:AE:DE:3E:2E:C3, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=[00001805], mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=101-1], mRssi=-92, mTimestampNanos=1043849718860030}
D/RxBle#ClientOperationQueue:   QUEUED ConnectOperation(890174706)
D/RxBle#ClientOperationQueue:  STARTED ConnectOperation(890174706)
V/RxBle#BleConnectionCompat: Connecting without reflection
D/BluetoothGatt: connect() - device: 6F:AE:DE:3E:2E:C3, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=542bd417
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=7 device=6F:AE:DE:3E:2E:C3
D/RxBle#BluetoothGatt: onConnectionStateChange newState=2 status=0
D/RxBle#ClientOperationQueue: FINISHED ConnectOperation(890174706)
I/RxBle#CancellableSubscription: Scan operation is requested to stop.
D/RxBle#ConnectionOperationQueue:   QUEUED ServiceDiscoveryOperation(888759094)
D/RxBle#ConnectionOperationQueue:  STARTED ServiceDiscoveryOperation(888759094)
D/BluetoothGatt: discoverServices() - device: 6F:AE:DE:3E:2E:C3
D/BluetoothGatt: onSearchComplete() = Device=6F:AE:DE:3E:2E:C3 Status=0
D/RxBle#BluetoothGatt: onServicesDiscovered status=0
D/BluetoothGatt: setCharacteristicNotification() - uuid: b31e89de enable: true
D/RxBle#ConnectionOperationQueue: FINISHED ServiceDiscoveryOperation(888759094)


true
------
D/RxBle#ClientOperationQueue:   QUEUED ScanOperationApi21(226148850)
D/RxBle#ClientOperationQueue:  STARTED ScanOperationApi21(226148850)
I/Choreographer: Skipped 207 frames!  The application may be doing too much work on its main thread.
I/RxBle#QueueOperation: Scan operation is requested to start.
D/BluetoothLeScanner: onClientRegistered() - status=0 clientIf=6
D/RxBle#ClientOperationQueue: FINISHED ScanOperationApi21(226148850)
D/BluetoothLeScanner: onScanResult() - ScanResult{mDevice=6F:AE:DE:3E:2E:C3, mScanRecord=ScanRecord [mAdvertiseFlags=26, mServiceUuids=[00001805], mManufacturerSpecificData={}, mServiceData={}, mTxPowerLevel=-2147483648, mDeviceName=101-1], mRssi=-81, mTimestampNanos=1043935540628438}
D/RxBle#ClientOperationQueue:   QUEUED ConnectOperation(890174706)
D/RxBle#ClientOperationQueue:  STARTED ConnectOperation(890174706)
V/RxBle#ConnectOperation: Trying to connectGatt using reflection.
V/RxBle#BleConnectionCompat: Found constructor with args count = 4
V/RxBle#BleConnectionCompat: Connecting using reflection
D/BluetoothGatt: connect() - device: 6F:AE:DE:3E:2E:C3, auto: true
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=125a849aa38e
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=7
D/BluetoothGatt: onClientConnectionState() - status=6 clientIf=7 device=6F:AE:DE:3E:2E:C3
D/RxBle#BluetoothGatt: onConnectionStateChange newState=0 status=6
W/System.err: BleDisconnectedException{bluetoothDeviceAddress='6F:AE:DE:3E:2E:C3'}
W/System.err:     at com.polidea.rxandroidble.internal.connection.RxBleGattCallback$2.onConnectionStateChange(RxBleGattCallback.java:76)
W/System.err:     at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:181)
W/System.err:     at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:70)
W/System.err:     at android.os.Binder.execTransact(Binder.java:446)
I/System.out: BleDisconnectedException{bluetoothDeviceAddress='6F:AE:DE:3E:2E:C3'}
I/RxBle#ConnectionOperationQueue: Connection operations queue to be terminated (6F:AE:DE:3E:2E:C3)
D/RxBle#Executors$RunnableAdapter: Terminated.
D/RxBle#ClientOperationQueue:   QUEUED DisconnectOperation(550952755)
D/RxBle#ClientOperationQueue: FINISHED ConnectOperation(890174706)
D/RxBle#ClientOperationQueue:  STARTED DisconnectOperation(550952755)
D/BluetoothManager: getConnectionState()
D/BluetoothManager: getConnectedDevices
D/BluetoothGatt: close()
D/BluetoothGatt: unregisterApp() - mClientIf=7
D/RxBle#ClientOperationQueue: FINISHED DisconnectOperation(550952755)-

推荐答案

有多种可能的解决方案可以实现预期的行为,因此,该操作将在第一次单击Connect按钮时开始,并且如果连接断开将丢失无需用户交互.

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.

您基本上想要的是:

  1. 扫描单个设备
  2. 扫描设备后-连接到设备
  3. 连接后-完成您的工作
  4. 如果会发生错误,请重试连接

Android中的错误在BluetoothAdapter开启后连接到设备,如果由于适配器已关闭而发生断开连接,则需要通过首先扫描该设备来解决该问题.在这种情况下,我们将仅完成部分流程,并从头开始重复.

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.

这篇关于RxAndroidBle-自动连接问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆