@Override
        public void onCharacteristicChanged(
            BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
          Log.d("characteristic=" + characteristic.getUuid());
          int format;
          int flag = characteristic.getProperties();
          if ((flag & 0x01) != 0) {
            format = BluetoothGattCharacteristic.FORMAT_UINT16;
          } else {
            format = BluetoothGattCharacteristic.FORMAT_UINT8;
          }
          int previousValue = mLastValue;

          int value = characteristic.getIntValue(format, 1);
          if (value < 50) {
            // This is probably a false measurement, consider this as a disconnect
            if (mStatus == Status.CONNECTED) {
              // Disconnect
              onDisconnect();
            }

            return;
          }

          mLastValue = value;
          Log.d("heartRate=" + mLastValue);

          if (mStatus != Status.CONNECTED) {
            mStatus = Status.CONNECTED;

            // Inform listeners
            mListeners.dispatch(
                new Dispatcher<HeartRateListener>() {
                  @Override
                  public void dispatch(HeartRateListener listener) {
                    listener.onConnected();
                  }
                });
          }

          if (previousValue != mLastValue) {
            // Inform listeners
            mListeners.dispatch(
                new Dispatcher<HeartRateListener>() {
                  @Override
                  public void dispatch(HeartRateListener listener) {
                    listener.onHeartRateChange(mLastValue);
                  }
                });
          }
        }
 private void onClientCharacteristicConfigurationDescriptorFound(
     BluetoothGattCharacteristic characteristic, BluetoothGattDescriptor descriptor) {
   Log.d();
   mBluetoothGatt.setCharacteristicNotification(characteristic, true);
   descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
   mBluetoothGatt.writeDescriptor(descriptor);
 }
 protected Uri getRideUri() {
   if (getCallbacks() == null) {
     Log.w("null callbacks");
     return null;
   }
   return getCallbacks().getRideUri();
 }
 private void onHeartRateMeasurementCharacteristicFound(
     BluetoothGattCharacteristic characteristic) {
   Log.d();
   boolean found = false;
   for (BluetoothGattDescriptor descriptor : characteristic.getDescriptors()) {
     Log.d("descriptor=" + descriptor.getUuid());
     if (getAssignedNumber(descriptor.getUuid())
         == GATT_DESCRIPTOR_CLIENT_CHARACTERISTIC_CONFIGURATION) {
       onClientCharacteristicConfigurationDescriptorFound(characteristic, descriptor);
       found = true;
       break;
     }
   }
   if (!found) {
     onClientCharacteristicConfigurationDescriptorNotFound();
   }
 }
 protected void onHeartRateServiceFound(BluetoothGattService service) {
   Log.d();
   for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
     Log.d("characteristic=" + characteristic.getUuid());
     boolean found = false;
     if (getAssignedNumber(characteristic.getUuid())
         == GATT_CHARACTERISTIC_HEART_RATE_MEASUREMENT) {
       // Found heart read measurement characteristic
       onHeartRateMeasurementCharacteristicFound(characteristic);
       found = true;
       break;
     }
     if (!found) {
       onHeartRateMeasurementCharacteristicNotFound();
     }
   }
 }
 @Override
 public void onServicesDiscovered(BluetoothGatt gatt, int status) {
   Log.d("status=" + LogUtil.getConstantName(BluetoothGatt.class, status, "GATT_"));
   List<BluetoothGattService> services = gatt.getServices();
   boolean found = false;
   for (BluetoothGattService service : services) {
     Log.d(service.getUuid().toString());
     if (getAssignedNumber(service.getUuid()) == GATT_SERVICE_HEART_RATE) {
       // Found heart rate service
       onHeartRateServiceFound(service);
       found = true;
       break;
     }
   }
   if (!found) {
     onHeartRateServiceNotFound();
   }
 }
 @Override
 public void disconnect() {
   Log.d();
   if (mBluetoothGatt != null) {
     mBluetoothGatt.close();
     mBluetoothGatt.disconnect();
     mBluetoothGatt = null;
   }
   mBluetoothDevice = null;
   onDisconnect();
 }
  @Override
  public void setBluetoothDevice(BluetoothDevice bluetoothDevice) {
    Log.d();
    mStatus = Status.CONNECTING;
    // Inform listeners
    mListeners.dispatch(
        new Dispatcher<HeartRateListener>() {
          @Override
          public void dispatch(HeartRateListener listener) {
            listener.onConnecting();
          }
        });

    mBluetoothDevice = bluetoothDevice;
    mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, true, mBluetoothGattCallback);
  }
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
          Log.d(
              "status="
                  + LogUtil.getConstantName(BluetoothGatt.class, status, "GATT_")
                  + " newState="
                  + LogUtil.getConstantName(BluetoothProfile.class, newState, "STATE_"));
          switch (newState) {
            case BluetoothProfile.STATE_CONNECTED:
              mBluetoothGatt.discoverServices();
              break;

            case BluetoothProfile.STATE_DISCONNECTED:
              onDisconnect();
              break;
          }
        }
 private void onClientCharacteristicConfigurationDescriptorNotFound() {
   Log.d();
   onError();
 }
 private void onHeartRateMeasurementCharacteristicNotFound() {
   Log.d();
   onError();
 }
 protected void onHeartRateServiceNotFound() {
   Log.d();
   onError();
 }