Как предотвратить многократное выполнение BluetoothGattCallback

У меня есть служба, в которой есть один экземпляр BluetoothGattCallback

public class MyService extends Service {

    private BluetoothGattCallback callback;

    @Override
    public void onCreate() {
            super.onCreate();

            callback = new BluetoothGattCallback() {
                      @Override
                      public synchronized void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                              Log.i("onConnectionStateChanged", "Status " + status);                
                              Log.i("onConnectionStateChanged", "New State " + newState);                
                      }
            };
    }

    // registration of bluetooth adapter and blah blah blah


}

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

Образцы журналов

10-22 13:29:18.731 26944-26961/redacted.lollipop I/onConnectionStateChange: Status 0
10-22 13:29:18.731 26944-26961/redacted.lollipop I/onConnectionStateChange: New State 2
10-22 13:29:18.731 26944-26961/redacted.lollipop I/onConnectionStateChange: Status 0
10-22 13:29:18.731 26944-26961/redacted.lollipop I/onConnectionStateChange: New State 2

Еще образцы журналов

10-22 13:29:48.836 26944-26961/redacted.lollipop I/onConnectionStateChange: Status 8
10-22 13:29:48.836 26944-26961/redacted.lollipop I/onConnectionStateChange: New State 0
10-22 13:29:48.850 26944-30763/redacted.lollipop I/onConnectionStateChange: Status 8
10-22 13:29:48.850 26944-30763/redacted.lollipop I/onConnectionStateChange: New State 0

И чем дольше приложение остается активным, тем чаще его вызывают. Как мне предотвратить это?


person Kevin D.    schedule 22.10.2015    source источник
comment
Просто поместите журнал в свой метод onCreate и посмотрите, прежде чем вызывается обратный вызов, сколько раз вызывается метод. Думаю, проблема в концепции услуг.   -  person Saeed Entezari    schedule 22.10.2015
comment
Или проверьте и посмотрите, сколько раз вы регистрируете того получателя, который вы упомянули в комментарии ниже onCreate ()   -  person Saeed Entezari    schedule 22.10.2015
comment
Он вызывается только один раз. Я вызываю метод connectGatt, который синхронизируется и блокируется самим обратным вызовом, например. синхронизированный (обратный вызов) {device.connectGatt (getBaseContext (), истина, обратный вызов, 2); }   -  person Kevin D.    schedule 22.10.2015
comment
@KevinD. У меня такая же проблема с Android OS 8.0 и более ранними версиями. Я закрываю Gatt-соединение всякий раз, когда получаю обратный вызов BLE disconnect / Bluetooth off / onDestroy для ForegroundService. Сможете ли вы решить эту проблему на своей стороне? Если возможно, вы можете проверить ссылку Google Issue Tracker для получения дополнительных сведений Issueetracker.google.com/issues/135215253   -  person Ganesh Tikone    schedule 14.06.2019
comment
@GaneshTikone, посмотрите на принятый ответ - к сожалению, в последнее время я мало занимался нативной разработкой.   -  person Kevin D.    schedule 18.06.2019


Ответы (1)


Следует иметь в виду, что каждый раз, когда вы звоните

bluetoothDevice.connectGatt(context, true, callback);

Он создает новый экземпляр объекта bluetoothGatt. проверьте источник для этого, вы увидите:

         BluetoothGatt gatt = new BluetoothGatt(context, iGatt, this, transport);
         gatt.connect(autoConnect, callback);

Так что одна хитрость заключается в том, что если ваше устройство отключается, а вы снова подключаетесь к нему с помощью. connectGatt (контекст, истина, обратный вызов); вместо вызова connect () в предыдущем экземпляре bluetoothGatt вы получите 2 экземпляра bluetoothGatt, оба из которых имеют дескриптор обратного вызова gatt.

Первоначально я пытался решить проблему, пытаясь закрыть и отключить bluetoothGatt перед повторным подключением.

   if (service.bluetoothGatt!=null){
        Log.i("Rides","Closeing bluetooth gatt on disconnect");
        service.bluetoothGatt.close();
        service.bluetoothGatt.disconnect();
        service.bluetoothGatt=null;
    } 

Но это не сработало, как-то я получал несколько обратных вызовов onConnectionStateChanged.

Мне удалось решить эту проблему, проверив, есть ли у меня действующий объект bluetoothGatt, и убедившись, что он вызывает connect (), если это повторное подключение.

---- Обновленный ответ ----

Я обнаружил, что лучше вызывать bluetoothGatt.close () внутри обратный вызов onConnectionStateChanged. Когда вы вызываете отключение, он отправляет сообщение на устройство Bluetooth с просьбой отключить. Затем, как только он ответит, вы получите обратный вызов и закроете соединение bluetooth gatt. Ожидая обратного вызова и не открывая другое соединение gatt до его полного закрытия, кажется, что несколько объектов gatt не могут подключиться к приложению.

person Marc    schedule 08.07.2016
comment
Как вы проверили действительный объект bluetoothGatt. - person Galya; 03.05.2017
comment
В основном, если у меня все еще есть указатель на него и это то же самое устройство Bluetooth. В итоге мне пришлось написать код, чтобы попытаться использовать последний, но если это не поможет, используйте новый. - person Marc; 04.05.2017
comment
Извини, дружище - долгое время отсутствовал в родном мире. Я приму это как лучший ответ, поскольку это теоретически разумно. К сожалению, проверить не могу, так как давно ушел из компании. - person Kevin D.; 04.03.2018
comment
Ты так прав !! Я был так сбит с толку, почему функция обратного вызова onConnectionStateChanged вызывалась несколько раз. - person Kaveri; 27.07.2020
comment
Вы легенда. Большое спасибо! - person Sangwon Choi; 05.03.2021