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) внутри службы привязки, а для дальнейшей связи используйте широковещательный приемник.
Как только вы получите событие или данные в обратном вызове, просто сделайте то же самое и получите его от получателя (который должен быть записан в приложении как отдельное или внутреннее основное действие, если вы используете только одно действие, а все остальные фрагменты).