Android BluetoothGatt - статус 133 - регистрация обратного вызова
Прежде всего, я прочитал SOLVED: обратный вызов 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 Не удалось зарегистрировать обратный вызов. Я не уверен, почему я могу запустить его 6 раз успешно, а затем провалиться в 7-й раз.
Имейте в виду, что я делаю все вызовы BLE из основного потока, и это было подтверждено в журнале cat из нескольких мест.
Вот схема моего кода:
SERVICE.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
Если вы сделали это здесь, спасибо! Я не мог найти ЛЮБОЙ информации о том, что означает = 133 означает?! Это происходит только тогда, когда обратный вызов завершается с ошибкой. Каждый раз это статус = 0.
08-15 12:00:10.766: D/BluetoothGatt(32027): onClientRegistered() - status=133 clientIf=0
Если бы кто-нибудь мог ответить на это, это могло бы мне очень помочь. Или, если кто-нибудь скажет мне, почему он работает только 6 раз. Может быть полезно любое понимание или догадка!
Спасибо всем!
Ответы
Ответ 1
Хорошо, я понял это. Проблема заключалась в основном в контроле, когда я читал документацию BluetoothGatt
. Я звонил .disconnect()
, но не .close()
. Поскольку Galaxy s4 может обрабатывать только 6 подключений одновременно, моя служба работает только 6 раз. Добавление .close()
в мой код позволило ему правильно отключить соединение и освободить эти используемые соединения.
Источник, из-за которого я перечитал документы более внимательно!
Поэтому не забудьте использовать .close() на вашем объекте BluetoothGatt, если у вас есть повторяющееся соединение с одним и тем же устройством!
Ответ 2
После нескольких месяцев исследований и выдергивания волос я нашел решение, о котором обычно не говорят.
Ваш обычный запрос на подключение выглядит примерно так:
cGatt.connectGatt(this, false, gattCallback);
Существует еще одна версия команды connectGatt с 4-м параметром. Этот параметр указывает, к какому типу устройства Bluetooth вы подключаетесь. Я добавил "2", чтобы указать, что я подключаюсь через Bluetooth LE. (это называется "транспорт", простите, если мое объяснение неверно, но оно решило все мои проблемы)
Попробуй это:
cGatt.connectGatt(this, false, gattCallback, 2);
И БАМ, теперь мой кошмар # 133 закончен (я молюсь)!
Ответ 3
ОС Android <6.0 :
mBluetoothDevice.connectGatt(context, false, callback);
ОС Android> = 6.0 :
mBluetoothDevice.connectGatt(context, false, callback, BluetoothDevice.TRANSPORT_LE);
В конечном счете, аппаратное оборудование необходимо, чтобы полностью решить эту проблему.
Ответ 4
Попробуйте использовать следующий обходной путь:
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;
}
Ответ 5
На некоторых устройствах это исправлено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();