Android BLE не может получать уведомления Gatt с устройства

Я пытаюсь получить уведомление от устройства, когда пишу значение на характеристике, но я ничего не получаю. Я включаю уведомление о характеристике, а затем пишу значение. Я видел, что характеристика устройства изменила его значение, но я не могу получить уведомление. Вот мой код:

DeviceActivity:

public class DevicesActivity extends Activity { private BLEService mBluetoothLeService; private String mDeviceAddress; private boolean mConnected = false; private BluetoothGattCharacteristic mNotifyCharacteristic; private final ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName componentName, IBinder service) { mBluetoothLeService = ((BLEService.LocalBinder) service).getService(); if (!mBluetoothLeService.initialize()) { finish(); } mBluetoothLeService.context = DevicesActivity.this; mBluetoothLeService.connect(mDeviceAddress); } @Override public void onServiceDisconnected(ComponentName componentName) { mBluetoothLeService = null; } }; private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BLEService.ACTION_GATT_CONNECTED.equals(action)) { mConnected = true; invalidateOptionsMenu(); } else if (BLEService.ACTION_GATT_DISCONNECTED.equals(action)) { mConnected = false; invalidateOptionsMenu(); } else if (BLEService.ACTION_GATT_SERVICES_DISCOVERED.equals(action)) { List<BluetoothGattService> servicesList; servicesList = mBluetoothLeService.getSupportedGattServices(); Iterator<BluetoothGattService> iter = servicesList.iterator(); while (iter.hasNext()) { BluetoothGattService bService = (BluetoothGattService) iter.next(); if (bService.getUuid().toString().equals(BLEUUID.SERVICE)){ mService = bService; } } } else if (BLEService.ACTION_DATA_AVAILABLE.equals(action)) { displayData(intent.getStringExtra(BLEService.EXTRA_DATA)); } } }; private static final String TAG = "BLEDevice"; public static final String EXTRA_BLUETOOTH_DEVICE = "BT_DEVICE"; private BluetoothAdapter mBTAdapter; private BluetoothDevice mDevice; private BluetoothGatt mConnGatt; private int mStatus; BluetoothGattService mService; private EditText pinTxt; private Button cancelBtn; private Button unlockBtn; private Button changePinBtn; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS); setContentView(R.layout.activity_devices); pinTxt = (EditText) findViewById(R.id.pin_txt); cancelBtn = (Button) findViewById(R.id.cancel_btn); unlockBtn = (Button) findViewById(R.id.unlock_btn); changePinBtn = (Button) findViewById(R.id.change_pin_btn); unlockBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { String aux = pinTxt.getText().toString(); mBluetoothLeService.sendCharacteristic(aux, getBTDeviceExtra()); } }); mDevice = getBTDeviceExtra(); mDeviceAddress = mDevice.getAddress(); if (mServiceConnection == null){ Log.v("NULL", "mServiceConnection NULL"); } Intent gattServiceIntent = new Intent(this, BLEService.class); if (gattServiceIntent==null){ Log.v("NULL", "mServiceConnection NULL"); } bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE); mStatus = BluetoothProfile.STATE_DISCONNECTED; } private void displayData(String data) { if (data != null) { Toast.makeText(DevicesActivity.this, data, Toast.LENGTH_LONG); } } @Override protected void onDestroy() { super.onDestroy(); unbindService(mServiceConnection); mBluetoothLeService = null; } @Override protected void onPause() { super.onPause(); unregisterReceiver(mGattUpdateReceiver); } private static IntentFilter makeGattUpdateIntentFilter() { final IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(BLEService.ACTION_GATT_CONNECTED); intentFilter.addAction(BLEService.ACTION_GATT_DISCONNECTED); intentFilter.addAction(BLEService.ACTION_GATT_SERVICES_DISCOVERED); intentFilter.addAction(BLEService.ACTION_DATA_AVAILABLE); return intentFilter; } @Override protected void onResume() { super.onResume(); registerReceiver(mGattUpdateReceiver, makeGattUpdateIntentFilter()); if (mBluetoothLeService != null) { final boolean result = mBluetoothLeService.connect(mDeviceAddress); } } private BluetoothDevice getBTDeviceExtra() { Intent intent = getIntent(); if (intent == null) { return null; } Bundle extras = intent.getExtras(); if (extras == null) { return null; } BluetoothDevice aux = extras.getParcelable(EXTRA_BLUETOOTH_DEVICE); return aux; } 

BLEService:

  private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { String intentAction; if (newState == BluetoothProfile.STATE_CONNECTED) { intentAction = ACTION_GATT_CONNECTED; mConnectionState = STATE_CONNECTED; broadcastUpdate(intentAction); 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) { intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server."); broadcastUpdate(intentAction); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { for (BluetoothGattService service : gatt.getServices()) { if ((service == null) || (service.getUuid() == null)) { continue; } if (BLEUUID.SERVICE.equalsIgnoreCase(service.getUuid().toString())) { mService = service; } } broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } @Override public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); broadcastUpdate(EXTRA_DATA, characteristic); Log.i("CARAC","CARACTERISTICA LEIDA onCharacteristicRead()"); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic) { readCharacteristic(characteristic); broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); Log.i("CARAC","CAMBIO EN CARACTERISTICA"); } }; private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2) private void broadcastUpdate(final String action,final BluetoothGattCharacteristic characteristic) { final Intent intent = new Intent(action); if (PIN_CHARACTERISTIC.equals(characteristic.getUuid())) { final String pin = characteristic.getStringValue(0); intent.putExtra(EXTRA_DATA, String.valueOf(pin)); } else { // For all other profiles, writes the data formatted in HEX. final byte[] data = characteristic.getValue(); if (data != null && data.length > 0) { final StringBuilder stringBuilder = new StringBuilder(data.length); for(byte byteChar : data) stringBuilder.append(String.format("%02X ", byteChar)); Log.i("RECIBIDO", "RECIBIDOS DATOS"); intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString()); } } sendBroadcast(intent); } public class LocalBinder extends Binder { BLEService getService() { return BLEService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public boolean onUnbind(Intent intent) { // After using a given device, you should make sure that BluetoothGatt.close() is called // such that resources are cleaned up properly. In this particular example, close() is // invoked when the UI is disconnected from the Service. close(); return super.onUnbind(intent); } private final IBinder mBinder = new LocalBinder(); public boolean initialize() { if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { return false; } return true; } public boolean connect(final String address) { if (mBluetoothAdapter == null || address == null) { return false; } // Previously connected device. Try to reconnect. if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) { if (mBluetoothGatt.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); if (device == null) { return false; } mBluetoothGatt = device.connectGatt(this, false, mGattCallback); mBluetoothDeviceAddress = address; mConnectionState = STATE_CONNECTING; return true; } public void disconnect() { if (mBluetoothAdapter == null || mBluetoothGatt == null) { return; } mBluetoothGatt.disconnect(); } public void close() { if (mBluetoothGatt == null) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; Log.e("CIERRE", "CONEXION CERRADA"); } public void readCharacteristic(BluetoothGattCharacteristic characteristic) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { return; } mBluetoothGatt.readCharacteristic(characteristic); Log.i("READ", "CARACTERISTICA LEIDA"); } public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { return; } mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); if (PIN_CHARACTERISTIC.equals(characteristic.getUuid())){ BluetoothGattDescriptor descriptor = new BluetoothGattDescriptor(UUID.nameUUIDFromBytes(BLEUUID.PIN_CHARACTERISTIC_CONFIG_DESCRIPTOR.getBytes()), BluetoothGattDescriptor.PERMISSION_WRITE_SIGNED); descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } } public List<BluetoothGattService> getSupportedGattServices() { if (mBluetoothGatt == null) return null; return mBluetoothGatt.getServices(); } public void sendCharacteristic(String pin, BluetoothDevice device){ byte[] pinByte = pin.getBytes(); int pinInt = Integer.valueOf(pin); BluetoothGattCharacteristic ch = (BluetoothGattCharacteristic) mService.getCharacteristic(UUID .fromString(BLEUUID.PIN_CHARACTERISTIC_UUID)); ch.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); ch.setValue(pin); Toast.makeText(context, "CARACTERISTICA ASIGNADA", Toast.LENGTH_SHORT).show(); connect(device.getAddress()); mBluetoothGatt = device.connectGatt(this, false, mGattCallback); setCharacteristicNotification(ch, true); if (mBluetoothGatt.writeCharacteristic(ch)) { Toast.makeText(context, "CARACTERISTICA ESCRITA", Toast.LENGTH_SHORT).show(); } } 

}

BLEUUID

 public class BLEUUID { // CARACTERISTICA PIN public static final String SERVICE ="0000fff0-0000-1000-8000-00805f9b34fb"; public static final String PIN_CHARACTERISTIC_UUID="0000fff9-0000-1000-8000-00805f9b34fb"; public static final String PIN_CHARACTERISTIC_CONFIG_DESCRIPTOR="0x2902"; private static HashMap<String, String> attributes = new HashMap(); static { attributes.put(SERVICE, "Service"); attributes.put(PIN_CHARACTERISTIC_UUID, "Pin"); } 

Когда я отлаживаю, onCharacteristicChange () никогда не выполняется.

Кто-нибудь знает, где проблема

Вот общий пример того, как нужно работать с BLE на Android:

  1. Вы пытаетесь подключиться
  2. Вы получаете обратный вызов, указывающий, что он подключен
  3. Вы открываете услуги
  4. Вы сказали, что службы обнаружены
  5. Вы получаете характеристики
  6. Для каждой характеристики вы получаете дескрипторы
  7. Для дескриптора вы устанавливаете его для включения уведомления / индикации с помощью BluetoothGattDescriptor.setValue ()
  8. Вы пишете дескриптор с помощью BluetoothGatt.writeDescriptor ()
  9. Вы включаете уведомления для характеристики локально с помощью BluetoothGatt.setCharacteristicNotification (). Без этого вам не будет позволено.
  10. Вы получаете уведомление о том, что дескриптор был написан
  11. Теперь вы можете записать данные в характеристику. Все характерные и дескрипторные конфигурации выполняются до того, как все будет записано на любой признак.
Intereting Posts
Я не могу подключить actionbarsherlock к проекту Почему Views теряет дополнение при установке xml backgroundResource? Настройка настраиваемого ключа при нажатии новых данных в базу данных firebase Разница OpenGL ES для iOS и Android Можно ли вставить столбец в listview во время выполнения? Почему мы устанавливаем контентное представление в onCreate (), а не в onStart () или onResume ()? Как отображать карты Google в режиме 2D? Android ObjectAnimation запускается только один раз Сбой сертификата ssl от Charles не удалось из-за сбоев сети Android: Odd NameNotFoundException после выхода приложения Приложение приложения Google I / O для Android Семантический материал (RDF, OWL) на мобильных телефонах – это возможно? Прозрачная / Прозрачная строка состояния + КоординаторLayout + Панель инструментов + Фрагмент Как управлять датами в базе данных Android sqlite, когда меня интересует только дата (которая должна быть уникальной), а не время? Декодирование звука через Android с помощью FFMpeg