rxandroidble: устройство отключено на длительное время: приложение переходит в режим сна

Я использую rxandroidble, используя autoconnect = true, чтобы непрерывно контролировать данные с датчика. Приложение постоянно сканирует датчики, к которым оно ранее подключено.

Мониторинг данных и сканирование датчиков должны продолжаться всю ночь, даже если телефон не подключен к источнику питания.

Если датчик подключен вечером, приложение будет оставаться подключенным всю ночь, даже если оно на мгновение отключится.

Однако, если датчик отключается на 6 часов в течение ночи (потому что я вытащил аккумулятор датчика), а затем я снова подключаю аккумулятор датчика утром, телефон не подключается к датчику.

Я постоянно сканирую каждые 8 ​​секунд на наличие новых датчиков в службе Android, но это не WakefulService и не запускается WakefulIntent. Должно ли это быть?

Есть идеи, что может происходить? Предназначен ли rxandroidble для сканирования в этой ситуации датчиков (устройство подключается, выходит из диапазона на 8 часов, затем возвращается в диапазон)? Или мне нужно вручную попытаться восстановить соединение после отключения, и тогда rxandroid будет постоянно пытаться восстановить соединение.

Вот мой код сканирования:

    public boolean scanForDevices(boolean on){


    if(on){
        if (!mBluetoothAdapter.isEnabled()) {
            Log.e(TAG, "scanForDevices: bluetooth not enabled, scan failed" );
            return false; // bluetooth disabled
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

            if (TheApplication.getInstance().checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                Log.e(TAG, "scanForDevices: ACCESS_COARSE_LOCATION permission not granted, scan failed" );
                return false; // App doesn't have permission granted
            }
        }

        if (isScanning()) {
            scanSubscription.unsubscribe();
        } else {

            scanSubscription = RxBleClientSingleton.getInstance().getRxBleClient().scanBleDevices()
                    .observeOn(AndroidSchedulers.mainThread())
                    .doOnError(this::onScanFailure)
                    .doOnUnsubscribe(this::clearSubscription)
                    .subscribe(this::onScanResult, this::onScanFailure);


            //Ensure we won't Scan forever (save battery)
            if (EnablePeriodicScan == true) {
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (isScanning())
                            scanForDevices(false);
                    }
                }, 4000);
            }

        }
    }else{
        //Turn scanning off
        if(isScanning()){
            scanSubscription.unsubscribe();
        }
    }
    return true;
}

и вот мой код подключения:

public void RxBleConnect() {



    autoConnectSetting = true;



    if (false == sensorConnectionState.equals(SensorConnectionState.Disconnected)) {
        Log.d(TAG, "RxBleConnect: cannot connect, #" + allowReconnect + " : " + macAddress + " isn't disconnected, currently in " + sensorConnectionState.toString() );

        if ((sensorConnectionState.equals(SensorConnectionState.Connected)) &&  (allowReconnect > 15)) { /// reached our limit even though we are connected?
            allowReconnect = 0; // reset count
            Disconnect(); // disconnect sensor.
            Log.d(TAG, "RxBleConnect: someone keeps knocking, appears that " + macAddress + " isn't as connected as we thought.");
        }
        allowReconnect ++;

        return; // dont reattempt connection if already attempting to connect
    }

    Log.d(TAG, "RxBleConnect: connecting to sensor....");

    SystemClock.sleep(400);


    connectionObservable  =
            bleDevice.establishConnection(TheApplication.getInstance(), autoConnectSetting)

            .compose(new ConnectionSharingAdapter())
            .observeOn(AndroidSchedulers.mainThread())


            .doOnUnsubscribe(this::RxBleDisconnect)
            .takeUntil(disconnectTriggerSubject)
            .doOnError(throwable -> {
                Log.d(TAG, "rxBleConnection doOnError: " + throwable);
                Disconnect(); // triggerDisconnect();
            });



    connectionSubscription = connectionObservable
            .flatMap(RxBleConnection::discoverServices)
            .subscribe(this::RxBleOnConnectionReceived, this::RxBleOnConnectionFailure);



}

Если состояние соединения меняется на отключение, я не пытаюсь восстановить соединение вручную; Сканирование или автоподключение должны решить эту проблему, верно?

Я отключил "Оптимизацию приложения", также известный как режим "Doze" для приложения, в настройках батареи Android, но я не знаю, если это что-то делает.

РЕДАКТИРОВАТЬ 1: Вот мои журналы.... мы подключаемся нормально в первый раз, затем мы пытаемся подключиться, затем мы немедленно отключаем:

>>> FIRST CONNECTION <<<
12-09 21:23:46.904 8992-8992/appName D/PeripheralManager: RxBleConnect: connecting to sensor...., auto connect = false
onConnectionStateChange newState=2 status=0
12-09 21:23:09.298 8992-8992/appName D/PeripheralManager: onConnectionStateChange: new state RxBleConnectionState{CONNECTED}
12-09 21:23:46.831 8992-9004/appName D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=5 device=E0:CF:8D:98:69:6A
12-09 21:23:46.832 8992-9004/appName D/RxBle#BluetoothGatt: onConnectionStateChange newState=0 status=8
12-09 21:23:46.897 8992-8992/appName D/PeripheralManager: onConnectionStateChange: new state RxBleConnectionState{DISCONNECTED}
12-09 21:23:46.897 8992-8992/appName D/Peripheral Manager: setConnectionState: Set e0:cf:8d:98:69:6a connection state to Disconnected
12-09 21:23:46.898 8992-8992/appName E/PeripheralManager: ### sendDisconnectNotification: mid = 2698601

>>> ATTEMPT RECONNECT HERE <<<<
12-09 21:23:46.904 8992-8992/appName D/PeripheralManager: RxBleConnect: connecting to sensor...., auto connect = true
12-09 21:23:46.915 8992-9004/appName D/RxBle#Radio:   QUEUED RxBleRadioOperationDisconnect(250971465)
12-09 21:23:46.916 8992-9070/appName D/RxBle#Radio:  STARTED RxBleRadioOperationDisconnect(250971465)
12-09 21:23:46.922 8992-9004/appName D/BluetoothGatt: setCharacteristicNotification() - uuid: f8c00003-159f-11e6-92f5-0002a5d5c51b enable: false
12-09 21:23:46.928 8992-9004/appName D/RxBle#Radio:   QUEUED RxBleRadioOperationDescriptorWrite(49261423)
12-09 21:23:47.306 8992-8992/appName D/RxBle#Radio:   QUEUED RxBleRadioOperationConnect(200794900)
12-09 21:23:47.316 8992-8992/appName D/PeripheralManager: onConnectionStateChange: new state RxBleConnectionState{CONNECTING}
12-09 21:23:47.316 8992-8992/appName D/Peripheral Manager: setConnectionState: Set e0:cf:8d:98:69:6a connection state to Connecting…
12-09 21:23:47.340 8992-8992/appName D/BluetoothManager: getConnectionState()
12-09 21:23:47.340 8992-8992/appName D/BluetoothManager: getConnectedDevices
12-09 21:23:47.347 8992-9070/appName D/RxBle#Radio: FINISHED RxBleRadioOperationDisconnect(250971465)
12-09 21:23:47.348 8992-9070/appName D/RxBle#Radio:  STARTED RxBleRadioOperationDescriptorWrite(49261423)
12-09 21:23:47.348 8992-8992/appName D/PeripheralManager: rxBleConnection doOnError: BleGattException{status=8, bleGattOperation=BleGattOperation{description='CONNECTION_STATE'}}
12-09 21:23:47.355 8992-8992/appName D/PeripheralManager: observeConnectionStateChanges FINISHED
12-09 21:23:47.355 8992-8992/appName D/PeripheralManager: rxBleConnection doOnError: BleGattException{status=8, bleGattOperation=BleGattOperation{description='CONNECTION_STATE'}}

Спасибо!

2-е РЕДАКТИРОВАНИЕ:

Код для потребления

private void RxBleOnConnectionReceived(службы RxBleDeviceServices) { // обнаружить службы

    connectionsCount ++;

    Log.d(TAG, "RxBleOnConnectionReceived: Discovered services");


    setConnectionState(SensorConnectionState.Connected);

    try {



    connectionSubscription = connectionObservable
            .flatMap(rxBleConnection -> rxBleConnection.setupNotification(BluetoothLeUart.RX_UUID))
            .doOnError(throwable -> {
                Log.d(TAG, "RxBleOnConnectionReceived setupNotification doOnError: " + throwable);
                Disconnect(); 
            })
            .doOnNext(notificationObservable -> {
                // Notification has been set up
            })
            .flatMap(notificationObservable -> notificationObservable) // <-- Notification has been set up, now observe value changes.
            .observeOn(AndroidSchedulers.mainThread())
            .doOnError(throwable -> {
                Log.d(TAG, "RxBleOnConnectionReceived doOnError: " + throwable);
            })
            .subscribe(
                    bytes -> {
                        // Given characteristic has been changes, here is the value.
                    processReceivedMessage(bytes);

                    },
                    throwable -> {
                        /*handle throwable*/

                        Log.e(TAG, "RxBleOnConnectionReceived: processReceivedMessage: " + throwable );
                    }
            );

1 ответ

Есть несколько вопросов, которые вы задали:

  • Какой сервис использовать, когда телефон переходит в режим ожидания?

Хороший вопрос о доступном стеке. Например, здесь: Как режим ожидания влияет на фоновые / передние службы, с / без частичных / полных пробуждений? На странице Github Cordova Plugin также есть проблема, связанная с использованием BLE во время сна: https://github.com/thaliproject/Thali_CordovaPlugin/issues/413

  • Является RxAndroidBle должен автоматически восстановить соединение, если устройство теряет связь?

Нет. После того, как соединение закончилось (было ли оно запущено с помощью autoconnect = true или false) это нужно восстановить, вызвав RxBleDevice.establishConnection снова. Из описания библиотеки:

Автоматическое подключение

(...)

Концепция автоматического подключения может вводить в заблуждение на первый взгляд. Если для параметра autoconnect установлено значение false, подключение завершится с ошибкой, если устройство BLE не будет оповещать при вызове метода RxBleDevice# createConnection. От платформы к платформе таймаут, после которого выдается ошибка, отличается, но в целом это скорее десятки секунд, чем отдельные секунды.

Установка флага автоподключения в значение true позволяет дождаться обнаружения устройства BLE. Экземпляр RxBleConnection не будет генерироваться, пока соединение не будет полностью установлено. Исходя из опыта, он также обрабатывает получение блокировок от пробуждения, поэтому можно с уверенностью предположить, что ваше устройство Android будет разбужено после установления соединения, но это не документированная функция и может измениться в будущих выпусках системы.

  • Будет ли сканирование или подключение с autoconnect = true позаботиться о воссоединении?

Трудно рассуждать о том, что вызывает scanForDevices() функция, но, похоже, она автоматически завершится через 4 секунды. Если сканирование включено и пользователь позвонит scanForDevices(true) сканирование все равно будет остановлено.

Другие вопросы по тегам