【问题标题】:RxAndroidBle - Auto connect issueRxAndroidBle - 自动连接问题
【发布时间】:2017-12-06 09:23:33
【问题描述】:

我正在使用 RxAndroidBle 库:

此代码按预期工作正常,单击 UI 上的连接按钮时,它会建立连接。

当我想要在设备恢复到范围时自动连接到设备时出现问题。我不想再次点击连接按钮。

有没有这样的功能? 'true' 标志在这里对我有帮助吗,如果是,如何实现它?请提出建议。 rxBleDevice.establishConnection(true);

如果我使用rxBleDevice.establishConnection(true),而不是“false”,则会出现以下错误,请帮助:

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)-

【问题讨论】:

  • 没有关于导致断开连接的信息。你可以在设置RxBleLog.setLogLevel(RxBleLog.VERBOSE) 时添加日志吗? autoConnect=true 应该和 vanilla API 一样好用。不幸的是,当autoConnect=true 时,它经常被窃听。在尝试连接之前也要停止scanSubscription——Android 有时不能同时处理好扫描和连接。
  • 用日志更新了原帖的真假,请检查。
  • 在日志中没有任何内容可以指出原因。可惜他们没有关于时间的信息。也许 HCI 日志会包含更多信息。您是否尝试在 .scanBleDevices() 之后添加 .take(1)
  • 是的,也试过了,更新了原帖,没有运气。
  • 什么是操作系统版本和手机型号?

标签: android bluetooth-lowenergy rx-android rxandroidble


【解决方案1】:

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

你基本上想要的是:

  1. 扫描单个设备
  2. 扫描设备时 - 连接到它
  3. 连接后 - 做你的事
  4. 如果发生错误 - 重试连接

如果由于适配器关闭而发生断开连接,则需要首先通过扫描设备来解决a bug in Android regarding connecting to a device after BluetoothAdapter being switched on。在这种情况下,我们将只完成流程的一部分,然后从头开始重复。

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
        );

其他构建块可能如下所示:

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()`
}

这是对您的用例的简单分解。如果需要,可以使流程进一步复杂化。

【讨论】:

  • toSingle() 无法在 scanSingleDevice 方法中解析
  • 这里的代码是针对 RxJava 1 版本的 lib。 RxJava 2 有.singleOrError() 函数。
猜你喜欢
  • 1970-01-01
  • 2012-04-26
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 2018-01-05
  • 1970-01-01
相关资源
最近更新 更多