title: Using BLE - Read GATT characteristics
body: <p>I'm trying to read GATT characteristic values from a Bluetooth LE device (a Heart Rate bracelet). Its specs are:</p>
  
  <p><a href="https://developer.bluetooth.org/gatt/services/Pages/ServiceViewer.aspx?u=org.bluetooth.service.heart_rate.xml" rel="nofollow">Services</a></p>
  
  <p><a href="https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml" rel="nofollow">Characteristics</a></p>
  
  <p>I have not yet figured out how to "<em>read</em>" the specifications and "<em>translate</em>" them into code.</p>
  
  <p><strong>I need to show on my app the heartbeats detected by the device.</strong> What is the way to read the GATT values? A code example would be much appreciated :)</p>
  
  <p>Follow my actual source code.</p>
  
  <hr>
  
  <p><strong>SETUP THE BLUETOOT CONNECTION</strong></p>
  
  <pre><code>    private BluetoothAdapter mBluetoothAdapter;
      private BluetoothGatt mBluetoothGatt;
      private Handler mHandler;
  
      private static final int REQUEST_ENABLE_BT = 1;
      private static final long SCAN_PERIOD = 10000;
  
      // ...
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_bluetooth);
          mHandler = new Handler();
  
          // BLE is supported?
          if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
              Toast.makeText(this, "Bluetooth Low Energy non supportato", Toast.LENGTH_SHORT).show();
              finish();
          }
  
          final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
          mBluetoothAdapter = bluetoothManager.getAdapter();
  
          // Bluetooth is supported?
          if (mBluetoothAdapter == null) {
              Toast.makeText(this, "Bluetooth non supportato", Toast.LENGTH_SHORT).show();
              finish();
          }
      }
  
      @Override
      protected void onResume() {
          super.onResume();
  
          // Bluetooth is enabled?
          if (!mBluetoothAdapter.isEnabled()) {
              Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
              startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
          }
  
          scanLeDevice(true);
      }
  
      @Override
      protected void onPause() {
          super.onPause();
          if (mBluetoothAdapter != null &amp;&amp; mBluetoothAdapter.isEnabled()) {
              scanLeDevice(false);
          }
      }
  </code></pre>
  
  <hr>
  
  <p><strong>DISCOVER BLE DEVICES AND CONNECT WITH HEART RATE MONITOR</strong></p>
  
  <pre><code>    // Device scan callback.
      private BluetoothAdapter.LeScanCallback mLeScanCallback =
              new BluetoothAdapter.LeScanCallback() {
                  @Override
                  public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
                      runOnUiThread(new Runnable() {
                          @Override
                          public void run() {
                              Log.i(TAG, "Name: " + device.getName() + " (" + device.getAddress() + ")");
                              String deviceAddress = device.getAddress();
                              if (deviceAddress.equals("C0:19:37:54:9F:30")) {
                                  connectToDevice(device);
                              }
                          }
                      });
                  }
              };
  
      public void connectToDevice(BluetoothDevice device) {
          if (mBluetoothGatt == null) {
              Log.i(TAG, "Attempting to connect to device " + device.getName() + " (" + device.getAddress() + ")");
              mBluetoothGatt = device.connectGatt(this, true, gattCallback);
              scanLeDevice(false);// will stop after first device detection
          }
      }
  
      private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
          @Override
          public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
              Log.i(TAG, "Status: " + status);
              switch (newState) {
                  case BluetoothProfile.STATE_CONNECTED:
                      Log.i(TAG, "STATE_CONNECTED");
                      //BluetoothDevice device = gatt.getDevice(); // Get device
                      gatt.discoverServices();
                      break;
                  case BluetoothProfile.STATE_DISCONNECTED:
                      Log.e(TAG, "STATE_DISCONNECTED");
                      break;
                  default:
                      Log.e(TAG, "STATE_OTHER");
              }
          }
  
          @Override
          public void onServicesDiscovered(BluetoothGatt gatt, int status) {
              List&lt;BluetoothGattService&gt; services = gatt.getServices();
              Log.i(TAG, "Services: " + services.toString());
  
              BluetoothGattCharacteristic bpm = services.get(2).getCharacteristics().get(0);
              gatt.readCharacteristic(services.get(0).getCharacteristics().get(0));
          }
  
          @Override
          public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
              // my attempt to read and print characteristics
              byte[] charValue = characteristic.getValue();
              byte flag = charValue[0];
              Log.i(TAG, "Characteristic: " + flag);
              //gatt.disconnect();
          }
      };
  </code></pre>