title: Android BLE API: GATT callback not received
body: <p>I working on an app that connects to a BLE device on a bike. The app works fine on Android 4.x but on Android 5 we don't get any callback on the writeCharacterstic() call. Any help is very appreciated since we are stuck at the moment! </p>
  
  <p>All calls to the gatt seems to return true. I have made sure that the calls are in the correct order so the GATT server won't return status busy:</p>
  
  <pre><code>device.connectGatt()
  onConnectionStateChange() -&gt; gatt.discoverServices()
  onServicesDiscovered() -&gt; gatt.writeDescriptor()
  onDescriptorWrite() -&gt; sendRequest()
  sendRequest() -&gt; gatt.writeCharacteristic()
  </code></pre>
  
  <p>I've been testing on the following devices:</p>
  
  <ul>
  <li>Samsung Galaxy S4 with Android 4.4.2 (working)</li>
  <li>Samsung Galaxy S3 with Android 4.3 (working)</li>
  <li>LG Nexus 4 with Android 5.0.1 (<strong>not working, no callback on writeCharacteristic()</strong>)</li>
  </ul>
  
  <p>Code:</p>
  
  <pre><code>private BluetoothGattCallback callback = new BluetoothGattCallback() {
      @Override
      public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
          super.onConnectionStateChange(gatt, status, newState);
  
          if (newState == BluetoothGatt.STATE_CONNECTED) {
              Log.i(TAG, "onConnectionStateChange() - STATE_CONNECTED");
              boolean discoverServicesOk = gatt.discoverServices();
          } else if (newState == BluetoothGatt.STATE_DISCONNECTED) {
              Log.i(TAG, "onConnectionStateChange() - STATE_DISCONNECTED");
          }
      }
  
      @Override
      public void onServicesDiscovered(BluetoothGatt gatt, int status) {
          super.onServicesDiscovered(gatt, status);
          Log.i(TAG, "onServicesDiscovered()");
  
          BluetoothGattService service = gatt.getService(UART_UUID);
          characteristic = service.getCharacteristic(TX_UUID);
  
          boolean result = gatt.setCharacteristicNotification(characteristic, true);
          Log.i(TAG, "onServicesDiscovered() - setCharacteristicNotification " + result);
  
          if (characteristic.getDescriptor(CLIENT_UUID) != null) {
              BluetoothGattDescriptor desc = characteristic.getDescriptor(CLIENT_UUID);
              result = desc.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
              Log.i(TAG, "onServicesDiscovered() - ENABLE_NOTIFICATION_VALUE " + result);
              result = desc.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
              Log.i(TAG, "onServicesDiscovered() - ENABLE_INDICATION_VALUE " + result);
              result = gatt.writeDescriptor(desc);
              Log.i(TAG, "onServicesDiscovered() - writeDescriptor " + result);
          }
  
          connectionState = STATE_CONNECTED;
      }
  
      @Override
      public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
          super.onDescriptorWrite(gatt, descriptor, status);
          mCurrentRequest = getNextRequest();
          Log.i(TAG, "onDescriptorWrite() - sending request, type: " + mCurrentRequest.getType());
          sendRequest(mCurrentRequest);
      }
  
      @Override
      public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
          super.onCharacteristicChanged(gatt, characteristic);
  
          // DON'T GET HERE ON LOLLIPOP
          Log.d(TAG, "onCharacteristicChanged() - size: " + characteristic.getValue().length + ", type: " + mCurrentRequest.getType());
      }
  }
  
  public void sendRequest(AsciiRequest asciiRequest) {
      start = System.currentTimeMillis();
      if (characteristic != null &amp;&amp; connectionState == STATE_CONNECTED) {
          Log.i(TAG, "sendRequest() - sending request, type: " + mCurrentRequest.getType());
          characteristic.setValue(asciiRequest.getData());
          characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
          boolean result = gatt.writeCharacteristic(characteristic);
          Log.i(TAG, "sendRequest() - result writeCharacteristic: " + result);
      } else {
          Log.e(TAG, "sendRequest() - not connected");
      }
  }
  </code></pre>
  
  <p>Logs:</p>
  
  <pre><code>03-31 14:08:28.614: I/BikeActivity(30045): onResume() - not connected yet, trying to connect
  03-31 14:08:28.616: I/BikeActivity(30045): doConnect() - connecting to device Bike 2
  03-31 14:08:28.634: I/BikeActivity(30045): doConnect() - connected to device Bike 2
  03-31 14:08:29.137: I/BikeActivity(30045): onConnectionStateChange() - STATE_CONNECTED
  03-31 14:08:29.151: I/BikeActivity(30045): onConnectionStateChange() - connected to device Bike 2
  03-31 14:08:29.164: I/BikeActivity(30045): onServicesDiscovered()
  03-31 14:08:29.170: I/BikeActivity(30045): onServicesDiscovered() - setCharacteristicNotification true
  03-31 14:08:29.170: I/BikeActivity(30045): onServicesDiscovered() - ENABLE_NOTIFICATION_VALUE true
  03-31 14:08:29.170: I/BikeActivity(30045): onServicesDiscovered() - ENABLE_INDICATION_VALUE true
  03-31 14:08:29.172: I/BikeActivity(30045): onServicesDiscovered() - writeDescriptor true
  03-31 14:08:29.173: I/BikeActivity(30045): onDescriptorWrite() - sending request, type: 25
  03-31 14:08:29.182: I/BikeActivity(30045): sendRequest() - sending request, type: 25
  03-31 14:08:29.186: I/BikeActivity(30045): sendRequest() - result writeCharacteristic: true
  03-31 14:08:34.182: I/BikeActivity(30045): doDisconnect() - disconnecting from device Bike 2
  03-31 14:08:34.233: I/BikeActivity(30045): onConnectionStateChange() - STATE_DISCONNECTED
  03-31 14:08:34.233: I/BikeActivity(30045): onConnectionStateChange() - disconnected
  03-31 14:08:34.263: I/BikeActivity(30045): doDisconnect() - toastText: No response from bike.
  03-31 14:08:34.318: I/BikeActivity(30045): onPause()
  03-31 14:08:34.712: I/BikeActivity(30045): onDestroy()
  </code></pre>