Bluetooth GATT onConnectionState Изменение не работает на Lollipop

В настоящее время у меня есть метод, который записывает устройства BLE, чтобы подавать звуковой сигнал. Мой обратный вызов Bluetooth выглядит следующим образом:

public class ReadWriteCharacteristic extends BluetoothGattCallback { public ReadWriteCharacteristic(Context context, String macAddress, UUID service, UUID characteristic, Object tag, Activity activity) { mMacAddress = macAddress; mService = service; mCharacteristic = characteristic; mTag = tag; mContext = context; this.activity =activity; final BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); mBluetoothAdapter = bluetoothManager.getAdapter(); } final private static String TAG = "ReadCharacteristic"; private Object mTag; private String mMacAddress; private UUID mService; private BluetoothManager mBluetoothManager = null; private BluetoothAdapter mBtAdapter = null; private BluetoothGatt mBluetoothGatt = null; private String mBluetoothDeviceAddress =""; private UUID mCharacteristic; BluetoothDevice device; private Activity activity; private BluetoothAdapter mBluetoothAdapter; private Context mContext; ReadWriteCharacteristic rc; private int retry = 5; public String getMacAddress() { return mMacAddress; } public UUID getService() { return mService; } public UUID getCharacteristic() { return mCharacteristic; } public byte[] getValue() { return mValue; } public void onError() { Log.w(TAG, "onError"); } public void readCharacteristic(){ if (retry == 0) { onError(); return; } retry--; device = mBluetoothAdapter.getRemoteDevice(getMacAddress()); mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); int connectionState = mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT); if (device != null) { if (connectionState == BluetoothProfile.STATE_DISCONNECTED) { // Previously connected device. Try to reconnect. if (mBluetoothDeviceAddress != null && getMacAddress().equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) { Log.w(TAG, "Re-use GATT connection"); if (mBluetoothGatt.connect()) { Log.w(TAG, "Already connected, discovering services"); mBluetoothGatt.discoverServices(); //return ; } else { Log.w(TAG, "GATT re-connect failed."); return; } } if (device == null) { Log.w(TAG, "Device not found. Unable to connect."); return; } Log.w(TAG, "Create a new GATT connection."); rc= ReadWriteCharacteristic.this; Log.w(TAG, "Starting Read [" + getService() + "|" + getCharacteristic() + "]"); mBluetoothGatt = device.connectGatt(mContext, false, rc); refreshDeviceCache(mBluetoothGatt); mBluetoothDeviceAddress = getMacAddress(); } else { Log.w(TAG, "Attempt to connect in state: " + connectionState); if(mBluetoothGatt!=null) mBluetoothGatt.close(); readCharacteristic(); } } } @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); Log.w(TAG,"onConnectionStateChange [" + status + "|" + newState + "]"); if ((newState == 2)&&(status ==0)) { gatt.discoverServices(); } else if(status == 133 ) { //gatt.disconnect(); gatt.close(); mBluetoothGatt = null; try { Thread.sleep(2000); } catch(Exception e) { } readCharacteristic(); } else{ if(mBluetoothGatt!=null) mBluetoothGatt.close(); // gatt.close(); Log.w(TAG, "[" + status + "]"); //gatt.disconnect(); try { Thread.sleep(2000); } catch(Exception e) { } mBluetoothGatt = null; readCharacteristic(); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { Log.w(TAG,"onServicesDiscovered [" + status + "]"); BluetoothGattService bgs = gatt.getService(getService()); if (bgs != null) { BluetoothGattCharacteristic bgc = bgs.getCharacteristic(getCharacteristic()); gatt.readCharacteristic(bgc); } } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.w(TAG,"onCharacteristicWrite [" + status + "]"); if (status == BluetoothGatt.GATT_SUCCESS) { Log.w(TAG,"onCharacteristicWrite [" + getDataHex(characteristic.getValue()) + "]"); // gatt.disconnect(); if(mBluetoothGatt!=null) mBluetoothGatt.close(); // gatt.close(); // mBluetoothGatt=null; } else if(status ==133) { gatt.close(); try { Thread.sleep(2000); } catch(Exception e) { } readCharacteristic(); } else{ //gatt.disconnect(); gatt.close(); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { Log.w(TAG,"onCharacteristicRead [" + status + "]"); if (status == BluetoothGatt.GATT_SUCCESS) { mValue = characteristic.getValue(); // Perform write operations gatt.writeCharacteristic(bgc); } else if(status ==133) { gatt.close(); try { Thread.sleep(2000); } catch(Exception e) { } readCharacteristic(); } else { // gatt.disconnect(); gatt.close(); } } } 

Этот код отлично работает на устройстве под управлением Kitkat и ниже. Но на устройствах, работающих с Lollipop, этот код отлично работает для первого экземпляра. Но из следующего экземпляра, независимо от того, отключить или закрыть соединение и повторить попытку, он просто не работает. Он продолжает давать мне код состояния 257 в методе onConnectionStateChange. Насколько я знаю, методы Bluetooth GATT одинаковы для устройств kitkat и Lollipop.

Меня удивляет, что этот код отлично работает на устройствах Lollipop, когда я использую старый BLE API, т.е. startLeScan (например, – mBluetoothAdapter.startLeScan(mLeScanCallback); ). Эта проблема возникает только тогда, когда я использую новый BLE API, т.е. BluetoothLeScanner ( scanner.startScan(filters, settings, new scancallback()); ). Скорость сканирования очень медленная для устройств Lollipop, использующих старый BLE API, поэтому я не могу ее использовать. Я просто не понимаю, как решить эту проблему. Кто-нибудь столкнулся с той же проблемой и нашел решение? Любая помощь будет глубоко оценена.

Несколько вещей я бы изменил здесь. Создайте переменную класса для данных, которые вы хотите прочитать из характеристики, например private string heartRate;

1) Вам не нужен метод readCharacteristic (). Вместо этого в onConnectionStateChange после правильного подключения устройства вызовите mBluetoothGatt.discoverServices (). Затем в методе onServicesDiscovered () я бы назвал gatt.getServices (). Затем используйте цикл foreach и прокрутите возвращаемые службы и сравните UUID службы, пока не найдете тот, который вам нужен. Затем, если heartRate == null, вызовите service.getCharacteristic (HeartRateUUID), а затем прочитайте характеристику. В onCharacteristicRead () проверьте, соответствует ли UUID характеристике сердечного ритма. Если это так, присвойте значение признака переменной heartRate. Если вас это интересует, я могу ввести методы или предоставить псевдокод.

2) Я бы не назвал gatt.connect (), а затем gatt.discoverServices (). Gatt.connect () снова подключится к текущему устройству, как только он увидит рекламный пакет с устройства. Я бы назвал gatt.connect (), а затем вызовом gatt.discoverServices () в методе onConnectedStateChange ().

3) В методе onConnectedStateChange не используйте переменную gatt. Вместо этого используйте mBluetoothGatt. MBluetoothGatt.disconnect () отключается от текущего подключенного устройства. MBluetoothGatt.close () завершает экземпляр gatt. Вы не можете вызвать mBluetoothGatt.connect () после вызова mBluetoothGatt.Close (). Это может быть не нужно, но если устройство подключено, я вызываю mBluetoothGatt.disconnect (), а затем mBluetoothGatt.close ().

4) Вы также можете соединить показания характеристик вместе. В onCharacteristicRead (), после того, как вы получите значение heartRate, вы можете сразу вызвать character.getService (). GetCharacteristic (UUIDTemperature), а затем прочитать эту характеристику. Он снова вызовет метод OnCharacteristicRead.

Дайте мне знать, если вы хотите, чтобы я прояснил все; Я печатаю на дрянной клавиатуре Surface Pro 3. 🙂

Intereting Posts
Android Facebook SDK 4.X, как получить адрес электронной почты и токен доступа Facebook, чтобы передать его веб-службе Недопустимая ошибка родительской папки для AppFolder в драйвере API Добавить программный продукт для recyclerview? Определение размера текста для Canvas.drawText () в res / values ​​/ dimens.xml Как улучшить качество отладочных данных, когда мое приложение аварийно завершает работу? Как запустить активность из класса потоков в android? InvalidKeyException: длина ключа не 128/192/256 бит Facebook shareDialog ничего не показывает Как открыть Gmail Compose при нажатии кнопки в приложении Android? Как захватить сетевой пакет в Android без использования каких-либо прав root ORMLite – CallBatchTasks () индивидуально или один раз для всех обновлений? GoogleApiClient: не запускается onConnected или onConnectionFailed Почему не постоянно демонстрируют ошибки во время выполнения андроид-студии? Открыть онлайн-файл в формате pdf через намерение андроида? Android Keystore: «Keystore был взломан, или пароль был неправильным».