Android BluetoothGatt - статус 133 - зарегистрировать обратный вызов

Прежде всего, я прочитал РЕШЕНО: обратный вызов GATT не регистрируется и предпринял шаги предложил в этом посте решить эту проблему, но безуспешно. Рекомендуемое исправление, если вы его не читали, состоит в том, чтобы выполнять все вызовы BLE из основного потока напрямую или с помощью обработчика.

Я работаю над приложением BLE, хочу запустить службу (вызываемую из активности каждые 10 секунд), которая выполняет следующие задачи:

1)Gets list of our products available to connect to (done, works)

2)For each available device:

          2a)connect to device
          2b)discover services
          2c)read 5 characteristics in this fashion:
             2c1)read characteristic
             2c2)onCharacteristicRead parse data
             2c3)when finished with data read next characteristic
             2c4)repeat until all are read (this is done using a state var and switch statement)
         2d)disconnect from device
         2e)connect to next device
         2f)repeat until all devices are read from
         2g)stopSelf()

Итак, проблема... Все отлично работает некоторое время. Я могу выполнить запуск всей службы {startService(...); в mainActivity} для завершения {stopSelf(); в Службе 6 раз.

На 7-й раз получаю BluetoothGatt Failed to register callback. Я не уверен, почему я могу успешно запустить его 6 раз, а затем потерпеть неудачу в 7-й раз.

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

Вот схема моего кода:

СЕРВИС.JAVA

private Handler handler = new Handler();
private BluetoothGatt cGatt = null;
private int unitIndex = 0; // keep track of currently connected unit
private int state = 0; //used to keep track of which characteristic to read next

public int onStartCommand(Intent intent, int flags, int startId) 
{
    Log.i(TAG, "Service Started...");
    //get ArrayList of units

    if(units.size > 0)
        handler.post(connectNextRunnable); //calls connectNextDevice()
    else
        stopSelf();   
}

private Runnable discoverServices = new Runnable()
{
    public void run()
    {
        cGatt.discoverServices();
    }
}

private Runnable readNextValue = new Runnable()
{
    public void run()
    {
        BluetoothGattCharacteristic c = null;
        switch(state)
        {
            //set c to appropriate characteristic
        default: // all characteristics read
            unitIndex++;
            handler.post(connectNextRunnable)
            return
        }

        cGatt.readCharacteristic(c);
    }
}

private void connectNextDevice()
{
    if(unitIndex == 0)
        store System.nanoTime in variable

    if(unitIndex >= units.size) //finished will all units
        stopSelf();

    if(unitIndex < units.size)
        cGatt.disconnect //if null
        cGatt.connectGatt(this, false, gattCallback)
}

private BluetoothGattCallback gattCallback = new BluetoothGattCallback() 
{
    public void onConnectionStateChange() 
    {
        handler.post(discoverServices);
    }

    public void onServicesDeiscovered() 
    {
        handler.post(readNextValue);
    }

    public void onCharacteristicRead() 
    {
        ParseData();
    }

    private void ParseData()
    {
        //do stuff with data
        handler.post(readNextValue);
    }
}

Итак, как я уже сказал, все вещи BLE вызываются из основного потока через обработчик. Служба успешно запускается 6 раз от начала до конца. На 7-й раз я получаю, что тупица не смогла зарегистрировать обратный вызов.

Я могу предоставить больше информации о logcat, если вы считаете, что это уместно. Я не сделал этого в исходном сообщении, потому что я вывожу в него много информации для проверки полученных данных и т. Д.

Приведенная ниже информация представляет собой информацию logcat для 7-го запуска моей службы от начала до конца.

08-15 12:00:10.746: I/PMIQ BTS(32027): Service Started...
08-15 12:00:10.746: I/PMIQ BTS(32027): Units: 1
08-15 12:00:10.746: D/AbsListView(32027): unregisterIRListener() is called 
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to next device...
08-15 12:00:10.766: I/PMIQ BTS(32027): Unit index = 0
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to pmIQ-IQ130_D93A
08-15 12:00:10.766: I/System.out(32027): main
08-15 12:00:10.766: D/BluetoothGatt(32027): connect() - device: 00:1E:C0:19:D9:3A, auto: false
08-15 12:00:10.766: D/BluetoothGatt(32027): registerApp()
08-15 12:00:10.766: D/BluetoothGatt(32027): registerApp() - UUID=e9d10870-4b09-451c-a9fa-c6b5f3594a77
08-15 12:00:10.766: I/BluetoothGatt(32027): Client registered, waiting for callback
08-15 12:00:10.766: D/BluetoothGatt(32027): onClientRegistered() - status=133 clientIf=0
08-15 12:00:10.766: I/PMIQ BTS(32027): CONECTION STATE CHANGED...Binder_2
**08-15 12:00:10.766: E/BluetoothGatt(32027): Failed to register callback**
08-15 12:00:10.766: I/PMIQ BTS(32027): Could not connect to null ... 257
08-15 12:00:10.766: I/PMIQ BTS(32027): Connecting to next device...
08-15 12:00:10.766: I/PMIQ BTS(32027): Unit index = 1
08-15 12:00:10.766: I/PMIQ BTS(32027): ******************************
08-15 12:00:10.766: I/PMIQ BTS(32027): Start Time: 4360642409647
08-15 12:00:10.766: I/PMIQ BTS(32027): End Time: 4360648970925
08-15 12:00:10.766: I/PMIQ BTS(32027): Difference: 6561278
08-15 12:00:10.766: I/PMIQ BTS(32027): Time to complete: 6
08-15 12:00:10.766: I/PMIQ BTS(32027): ******************************
08-15 12:00:10.876: I/PMIQ BTS(32027): ...Service Destroyed

Если вы сделали это здесь, спасибо! Я не смог найти НИКАКОЙ информации о том, что означает status=133?! Это происходит только тогда, когда обратный вызов терпит неудачу. Каждый раз это статус = 0.

08-15 12:00:10.766: D/BluetoothGatt(32027): onClientRegistered() - status=133 clientIf=0

Если бы кто-нибудь мог даже ответить на это ... это может мне очень помочь. Или, если кто-нибудь может сказать мне, почему он работает только 6 раз. Любое понимание или догадка может быть полезной!

Спасибо всем!


person ck1221    schedule 15.08.2014    source источник
comment
Возможный ответ на этот вопрос есть здесь code.google.com/p/ android/issues/detail?id=68538 Однако я не смогу протестировать его до понедельника, похоже, я неправильно отключаюсь от устройства.   -  person ck1221    schedule 16.08.2014
comment
это работает для меня, я все еще получаю ошибку 133 после вызова закрытия в Android   -  person prasanthMurugan    schedule 25.10.2017


Ответы (6)


Хорошо, я понял это. Проблема была в основном из-за недосмотра, когда я читал документацию BluetoothGatt. Я звонил .disconnect(), но не .close(). Поскольку Galaxy s4 может одновременно обрабатывать только 6 подключений, мой сервис запускался только 6 раз. Добавление .close() к моему коду позволило правильно закрыть соединение и освободить те используемые соединения.

Источник, который заставил меня перечитать документы более внимательно!

Так что не забудьте использовать .close() в вашем объекте BluetoothGatt, если у вас есть повторяющееся подключение к одному и тому же устройству (устройствам)!!

person ck1221    schedule 18.08.2014
comment
133 — это GATT_ERROR (источник: android.googlesource.com/platform/external/bluetooth/bluedroid/) - person PaulT; 03.06.2015
comment
если я сделаю .close(), то он закроет BT устройства... :| Я что-то пропустил!! - person CoDe; 29.10.2015
comment
@shubh убедитесь, что вы отключили и закрыли Bluetoothgatt - person Deko; 06.11.2015
comment
Да, Вы правы. Но это тоже не помогает, после некоторой последовательности возникает Gatt_Error (Код ошибки: 133). Любое предложение! - person CoDe; 06.11.2015
comment
какая разница между disconnect() и close() ? я должен использовать разъединение () + закрыть () или только один из них? Который из? - person 4ntoine; 12.02.2016
comment
@4ntoine это может помочь вам stackoverflow.com/questions/23110295/ - person Marian Paździoch; 30.06.2016
comment
Ответ правильный, но он не устраняет все возможные случаи ошибок ... по крайней мере, для того опыта, который у меня был с любимым 133. - person andrea.rinaldi; 19.07.2016
comment
@andrea.rinaldi При ошибке 133 единственное, что вы можете сделать, это повторить попытку несколько раз. Это единственное известное решение. - person IgorGanapolsky; 01.05.2017
comment
@ ck1221 Где документация, в которой говорится, что S4 поддерживает только 6 устройств? Должно быть 7, верно? - person Bryan Bryce; 25.05.2017
comment
это работает для меня, я все еще получаю ошибку 133 после вызова закрытия в Android - person prasanthMurugan; 24.10.2017

После месяцев исследований и выдергивания волос я нашел решение, о котором обычно не говорят.

Ваш обычный запрос на подключение выглядит примерно так:

cGatt.connectGatt(this, false, gattCallback);

Существует еще одна версия команды connectGatt с четвертым параметром. Этот параметр указывает, к какому типу Bluetooth-устройства вы подключаетесь. Я добавил «2», чтобы указать, что я подключаюсь через Bluetooth LE. (это называется "транспорт", простите меня, если мое объяснение неверно, но это решило все мои проблемы)

Попробуй это:

cGatt.connectGatt(this, false, gattCallback, 2);

И БАМ, теперь мой кошмар № 133 закончился (я молюсь)!

person btmcmahan    schedule 30.01.2018
comment
Будьте осторожны, метод connectGatt с параметром transport требует уровня API 23. И вы можете использовать константу BluetoothDevice.TRANSPORT_LE вместо жестко заданного значения 2. - person Bubu; 06.02.2018

ОС Android ‹ 6.0:

mBluetoothDevice.connectGatt(context, false, callback);

ОС Android> = 6,0:

mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);

В конечном счете, для полного решения этой проблемы необходимо аппаратное оборудование.

person 郑松岚    schedule 29.06.2018
comment
Спасибо за такой ценный ответ. Это проснулось для меня. Но будет очень полезно, если вы предоставите больше документации об этой логике. - person vinay shetty; 18.02.2021

  • На некоторых устройствах это было исправлено с помощью mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);.

  • на некоторых устройствах, таких как Samsung S7, A8, была проблема со ScanSettings.Builder().setReportDelay(400) // или 500 мс. это не должно быть 0 или больше, например 1000 мс. ScanSettings settings = new ScanSettings.Builder() .setScanMode(ScanSettings.SCAN_MODE_BALANCED) .setReportDelay(400) .build();

person user1278366    schedule 08.08.2019

Попробуйте использовать следующий обходной путь:

private static boolean gatt_status_133 = false;

final Handler handler = new Handler();

public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

    if (newState == BluetoothProfile.STATE_CONNECTED) {
        mConnectionState = STATE_CONNECTED;
        Log.i(TAG, "Connected to GATT server.");
        // Attempts to discover services after successful connection.
        Log.i(TAG, "Attempting to start service discovery:" +
                mBluetoothGatt.discoverServices());

    } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
        if(status == 133)
        {
            gatt_status_133=true;
        }
        else{
            mConnectionState = STATE_DISCONNECTED;
            Log.i(TAG, "Disconnected from GATT server."); 
        }
    }
}


@RequiresApi(api = Build.VERSION_CODES.M)
public boolean connect(final String address) {
    if (mBluetoothAdapter == null || address == null) {
        Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
        return false;
    }

    // Previously connected device.  Try to reconnect.
    if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
            && mBluetoothGatt != null) {
        Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
        if (mBluetoothGatt.connect()) {
            mConnectionState = STATE_CONNECTING;
            return true;
        } else {
            return false;
        }
    }

    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
    if (device == null) {
        Log.w(TAG, "Device not found.  Unable to connect.");
        return false;
    }

    mBluetoothGatt= device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
    Log.d(TAG, "Trying to create a new connection.");
    mBluetoothDeviceAddress = address;
    mConnectionState = STATE_CONNECTING;

    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            if(gatt_status_133)
            {
                Log.d(TAG, "Catch issue");
                connect(address);
                gatt_status_133=false;
            }
        }
    }, 4000);

    return true;
}
person Artem Kabakov    schedule 29.04.2019

Как-то BluetoothLeScanner.startScan() помогает

private final Handler mMainHandler = new Handler(Looper.getMainLooper());
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
    if (newState == BluetoothProfile.STATE_CONNECTED) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mBluetoothAdapter.isEnabled() && mBleScanner != null) {
            mBleScanner.stopScan(mLeScanCallback);
        }
    } else if (status == 133 && newState == BluetoothProfile.STATE_DISCONNECTED) {
        if (D) Log.e(TAG, "connectGatt status == 133");
        mMainHandler.post(mDisconnectRunnable);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mBluetoothAdapter.isEnabled()) {
            mBleScanner = mBluetoothAdapter.getBluetoothLeScanner();
            mBleScanner.startScan(null, new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build(),
                    mLeScanCallback);
        }
        mMainHandler.postDelayed(mConnectRunnable, 10000);
    }
}

private ScanCallback mLeScanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);
        if (result.getDevice().getAddress().equals(mBluetoothDeviceAddress)) {
            mMainHandler.post(mConnectRunnable);
            if (mBleScanner != null) {
                mBleScanner.stopScan(mLeScanCallback);
                mBleScanner = null;
            }
        }
    }
};
person Alexandr    schedule 08.06.2020