Android Bluetooth LE ошибка: не удалось зарегистрировать обратный вызов

Я нахожусь в процессе написания приложения для Android, которое будет подключаться к устройству работоспособности через Bluetooth LE. Однако, похоже, что я не подключаюсь к его серверу GATT должным образом. Каждые несколько секунд мой файл журнала показывает это:

03-27 11:33:39.821: D/BluetoothAdapter(26644): onScanResult() - Device=0C:F3:EE:AA:33:35 RSSI=-53
03-27 11:33:39.821: I/BluetoothGattActivity(26644): New LE Device: BT-001 @ -53
03-27 11:33:39.821: I/BluetoothGattActivity(26644): New LE Device matches !!!
03-27 11:33:39.831: I/BluetoothGattActivity(26644): In the fish function.
03-27 11:33:39.831: D/BluetoothGatt(26644): connect() - device: 0C:F3:EE:AA:33:35, auto:  false
03-27 11:33:39.831: D/BluetoothGatt(26644): registerApp()
03-27 11:33:39.831: D/BluetoothGatt(26644): registerApp() - UUID=7155a6e0-5432-42cc-8b05-a080c86aaccb
03-27 11:33:39.841: I/BluetoothGatt(26644): Client registered, waiting for callback
03-27 11:33:49.840: E/BluetoothGatt(26644): Failed to register callback
03-27 11:33:49.840: I/BluetoothGattActivity(26644): myBluetoothGatt is null

Если бы кто-то мог помочь мне увидеть, где моя проблема и что происходит, это было бы очень ценно. Я использую Galaxy S4. Я считаю, что весь мой соответствующий код ниже:

private void broadcastUpdate(final String action) {
   final Intent intent = new Intent(action);
   sendBroadcast(intent);
}

private void fish(final BluetoothDevice device) {      
   Log.i(TAG, "In the fish function.");
   myBluetoothGatt = device.connectGatt(this, false, myGattCallback);
   Log.i(TAG, "myBluetoothGatt is " + myBluetoothGatt);
}

private BluetoothAdapter.LeScanCallback callbackFunction = new BluetoothAdapter.LeScanCallback() {
   @Override
   public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
       Log.i(TAG, "New LE Device: " + device.getName() + " @ " + rssi);
       if (DEVICE_NAME.equals(device.getName())) {
           Log.i(TAG, "New LE Device matches !!!");
           fish (device);
           }
   }
};

private final BluetoothGattCallback myGattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        String intentAction;
        Log.i(TAG, "We are in the ConnectionStateChanged().");
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            intentAction = ACTION_GATT_CONNECTED;
            mConnectionState = STATE_CONNECTED;
            broadcastUpdate(intentAction);
            Log.i(TAG, "Connected to GATT server.");
            Log.i(TAG, "Attempting to start service discovery:" +
                    myBluetoothGatt.discoverServices());

        } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
            intentAction = ACTION_GATT_DISCONNECTED;
            mConnectionState = STATE_DISCONNECTED;
            Log.i(TAG, "Disconnected from GATT server.");
            broadcastUpdate(intentAction);
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        Log.i(TAG, "In area 1");
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            System.out.println("--onServicesDiscovered");
        } else {
            Log.w(TAG, "onServicesDiscovered received: " + status);
        }
    }

    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {
        Log.i(TAG, "In area 2");
        if (status == BluetoothGatt.GATT_SUCCESS) {
            broadcastUpdate(ACTION_DATA_AVAILABLE);
            Log.i(TAG, "--onCharacteristicRead GATT_SUCCESS");
        }
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,
                                        BluetoothGattCharacteristic characteristic) {
        Log.i(TAG, "In area 3");
        broadcastUpdate(ACTION_DATA_AVAILABLE);
        System.out.println("--onCharacteristicChanged");
    }
};

3 ответа

Вызов device.connectGatt(this, false, myGattCallback) должен быть выполнен в основном UIThread. Так и должно быть примерно так:

private void fish(final BluetoothDevice device) {
        Log.i(TAG, "In the fish function.");
        runOnUiThread(new Runnable() {
          @Override
          public void run() {
              myBluetoothGatt = device.connectGatt(this, false, myGattCallback);
          }
        });
}

У меня есть частичное исправление этой конкретной формы ошибки. В этом вопросе я видел, что обратному вызову GATT не удается зарегистрировать, что устройства Samsung требуют попыток обнаружения Gatt в потоке пользовательского интерфейса.

Самым сложным для меня было осознать, что я не в теме, о которой думал. Обратный вызов onLeScan возвращался не в потоке пользовательского интерфейса, а в потоке Binder (по крайней мере, в соответствии с отладчиком). Я вынужден был использовать обработчик для публикации Runnable, который запустил мой код обнаружения службы.

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

04-04 14:21:15.115    9616-9616/BluetoothApp I/BluetoothGatt﹕ Client registered, waiting for callback
04-04 14:21:15.115    9616-9627/BluetoothApp D/BluetoothGatt﹕ onClientRegistered() - status=0 clientIf=5

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

Зарегистрируйте callback и device.connectGatt(this, false, myGattCallback) внутри службы привязки, а для дальнейшей связи используйте широковещательный приемник.

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

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