Android BLE НЕ подключается снова после тайм-аута устройства BLE [Использование RxAndroidBle]

Я работаю над Android BLE, используя библиотеку RxAndroidBle. Устройство BLE имеет тайм-аут 5 минут, если нет взаимодействия. т.е. устройство автоматически отключится, если в течение 5 минут не выполняются операции чтения / записи. Я получаю BleGattException, когда происходит отключение по таймауту.

     W/System.err: BleGattException{macAddress=24:71:89:FE:A0:88, status=19 (0x13 -> https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.1.0_r1/stack/include/gatt_api.h), bleGattOperationType=BleGattOperation{description='CONNECTION_STATE'}}
 W/System.err:     at com.polidea.rxandroidble.internal.connection.RxBleGattCallback.propagateStatusErrorIfGattErrorOccurred(RxBleGattCallback.java:233)
 W/System.err:     at com.polidea.rxandroidble.internal.connection.RxBleGattCallback.access$200(RxBleGattCallback.java:35)
 W/System.err:     at com.polidea.rxandroidble.internal.connection.RxBleGattCallback$3.onConnectionStateChange(RxBleGattCallback.java:86)
 W/System.err:     at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:228)
 W/System.err:     at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:70)
 W/System.err:     at android.os.Binder.execTransact(Binder.java:453)

 W/BluetoothGatt: Unhandled exception in callback
                                                                  rx.exceptions.OnErrorFailedException: Error occurred when trying to propagate error to Observer.onError
                                                                      at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:194)
                                                                      at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:115)
                                                                      at rx.observers.Subscribers$5.onError(Subscribers.java:230)
                                                                      at rx.observers.Subscribers$5.onError(Subscribers.java:230)
                                                                      at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87)
                                                                      at rx.observers.Subscribers$5.onError(Subscribers.java:230)
                                                                      at rx.observers.Subscribers$5.onError(Subscribers.java:230)
                                                                      at rx.observers.Subscribers$5.onError(Subscribers.java:230)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.reportError(OperatorMerge.java:266)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.checkTerminate(OperatorMerge.java:818)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:579)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568)
                                                                      at rx.internal.operators.OperatorMerge$InnerSubscriber.onError(OperatorMerge.java:852)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.reportError(OperatorMerge.java:266)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.checkTerminate(OperatorMerge.java:818)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:579)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568)
                                                                      at rx.internal.operators.OperatorMerge$InnerSubscriber.onError(OperatorMerge.java:852)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.reportError(OperatorMerge.java:266)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.checkTerminate(OperatorMerge.java:818)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.emitLoop(OperatorMerge.java:579)
                                                                      at rx.internal.operators.OperatorMerge$MergeSubscriber.emit(OperatorMerge.java:568)
                                                                      at rx.internal.operators.OperatorMerge$InnerSubscriber.onError(OperatorMerge.java:852)
                                                                      at rx.internal.operators.NotificationLite.accept(NotificationLite.java:132)
                                                                      at rx.subjects.SubjectSubscriptionManager$SubjectObserver.emitNext(SubjectSubscriptionManager.java:253)
                                                                      at rx.subjects.BehaviorSubject.onError(BehaviorSubject.java:141)
                                                                      at com.polidea.rxandroidble.internal.connection.RxBleGattCallback.propagateStatusError(RxBleGattCallback.java:241)
                                                                      at com.polidea.rxandroidble.internal.connection.RxBleGattCallback.propagateStatusErrorIfGattErrorOccurred(RxBleGattCallback.java:233)
                                                                      at com.polidea.rxandroidble.internal.connection.RxBleGattCallback.access$200(RxBleGattCallback.java:35)
                                                                      at com.polidea.rxandroidble.internal.connection.RxBleGattCallback$3.onConnectionStateChange(RxBleGattCallback.java:86)
                                                                      at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:228)
                                                                      at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:70)
                                                                      at android.os.Binder.execTransact(Binder.java:453)
                                                                   Caused by: rx.exceptions.OnErrorFailedException: Error occurred when trying to propagate error to Observer.onError
                                                                      at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:187)
                                                                      at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:115)
                                                                      at rx.exceptions.Exceptions.throwOrReport(Exceptions.java:216)
                                                                      at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:139)
                                                                      at rx.internal.operators.OperatorDistinctUntilChanged$1.onNext(OperatorDistinctUntilChanged.java:96)
                                                                      at rx.internal.operators.NotificationLite.accept(NotificationLite.java:135)
                                                                      at rx.subjects.SubjectSubscriptionManager$SubjectObserver.emitNext(SubjectSubscriptionManager.java:253)
                                                                      at rx.subjects.BehaviorSubject.onNext(BehaviorSubject.java:160)
                                                                      at com.polidea.rxandroidble.internal.RxBleDeviceImpl$1$1.call(RxBleDeviceImpl.java:77)
                                                                      at rx.subscriptions.BooleanSubscription.unsubscribe(BooleanSubscription.java:71)
                                                                      at rx.internal.util.SubscriptionList.unsubscribeFromAll(SubscriptionList.java:136)
                                                                      at rx.internal.util.SubscriptionList.unsubscribe(SubscriptionList.java:125)

Как только устройство отключается из-за тайм-аута, при повторном сканировании я мог найти устройство поблизости от доступных устройств, как и ожидалось. Но когда я пытаюсь подключиться к тому же устройству, он выдает сообщение об исключении, которое уже подключено.

 W/System.err: BleAlreadyConnectedException{macAddress=24:71:89:FE:99:E3}
 W/System.err:     at com.polidea.rxandroidble.internal.RxBleDeviceImpl.lambda$establishConnection$3(RxBleDeviceImpl.java:54)
 W/System.err:     at com.polidea.rxandroidble.internal.RxBleDeviceImpl$$Lambda$1.call(Unknown Source)
 W/System.err:     at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
 W/System.err:     at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
 W/System.err:     at rx.Observable.subscribe(Observable.java:10236)
 W/System.err:     at rx.Observable.subscribe(Observable.java:10203)
 W/System.err:     at rx.Observable.subscribe(Observable.java:10043)

Но я могу подключиться к устройству, если я выключу и включу bluetooth на своем мобильном телефоне или если я убью приложение и перезапущу его.

И повторное подключение работает, когда я вручную отключаю устройство и подключаюсь снова. Проблема возникает только тогда, когда происходит отключение по таймауту.

Кто-нибудь может сказать мне, почему это происходит?


person VishnuSP    schedule 21.04.2017    source источник


Ответы (1)


Судя по ошибке и реализации функции .establishConnection(), вы не отказываетесь от подписки на предыдущий возвращенный Observable.

@Override
public Observable<RxBleConnection> establishConnection(final boolean autoConnect) {
    return Observable.defer(new Func0<Observable<RxBleConnection>>() {
        @Override
        public Observable<RxBleConnection> call() {

            if (isConnected.compareAndSet(false, true)) {
                return connector.prepareConnection(autoConnect)
                        .doOnSubscribe(new Action0() {
                            @Override
                            public void call() {
                                connectionStateSubject.onNext(CONNECTING);
                            }
                        })
                        .doOnNext(new Action1<RxBleConnection>() {
                            @Override
                            public void call(RxBleConnection rxBleConnection) {
                                connectionStateSubject.onNext(CONNECTED);
                            }
                        })
                        .doOnUnsubscribe(new Action0() {
                            @Override
                            public void call() {
                                connectionStateSubject.onNext(DISCONNECTED);
                                isConnected.set(false);
                            }
                        });
            } else {
                return Observable.error(new BleAlreadyConnectedException(bluetoothDevice.getAddress()));
            }
        }
    });
}

После того, как вы откажетесь от подписки на предыдущую, вы сможете установить новое соединение.

person Dariusz Seweryn    schedule 21.04.2017
comment
Спасибо за информацию @s_noopy. Но я уже не подпишусь перед следующим подключением. И повторное подключение работает, когда я вручную отключаю устройство и подключаюсь снова. Проблема только в том, что происходит отключение по таймауту. - person VishnuSP; 21.04.2017
comment
Когда происходит отключение периферийного устройства - Observable из .establishConnection() должен выдать BleDisconnectedException - это происходит? - person Dariusz Seweryn; 21.04.2017
comment
Нет. Я не получаю BleDisconnectedException, но BleGattException 'W / System.err: BleGattException {status = 19, bleGattOperation = BleGattOperation {description =' CONNECTION_STATE '}} W / System.err: в com.polidea.rxandroidble.internal. connection.RxBleGattCallback.propagateStatusErrorIfGattErrorOccurred (RxBleGattCallback.java:248) ' - person VishnuSP; 24.04.2017
comment
Это другое исключение, чем из исходного сообщения. Обновите исходный, добавив новую информацию. Объект BleGattException при печати отправляет вас на сайт https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.1.0_r1/stack/include/gatt_api.h, где вы можете найти ответ о конкретной ошибке #define GATT_CONN_TERMINATE_PEER_USER HCI_ERR_PEER_USER /* 0x13 connection terminate by peer user */ - person Dariusz Seweryn; 24.04.2017
comment
да. Я проверил это, и это означает, что соединение разорвано. Так что, если я снова попытаюсь установить соединение, это должно произойти. Но этого не происходит. Это моя проблема. Есть идеи, почему это так? - person VishnuSP; 24.04.2017
comment
Ошибка указывает на то, что периферийное устройство, к которому вы подключаетесь, разрывает соединение. Повторное подключение не обязательно означает, что оно будет успешным. Партнер может снова сбросить его. - person Dariusz Seweryn; 24.04.2017
comment
Но я могу подключиться к одноранговому узлу, если я выключу и включу bluetooth на своем мобильном телефоне или если я убью приложение и перезапущу его. Так что я не думаю, что его снова бросят коллеги. - person VishnuSP; 24.04.2017
comment
Это может быть ошибка стека Android BLE: issueetracker.google.com/issues/37029019 К сожалению, я не могу сказать больше без более подробных журналов из вашего приложения. - person Dariusz Seweryn; 24.04.2017