title: Automatic connecting to a BLE device [Android]
body: <p>I am working on an Android application that should automatically connect to the BLE device with a specified MAC-address.
  Basically a scan should be running 24/7, and as soon as the device is discovered, the service should connect to it, and ideally stop scanning.</p>
  
  <p>What I managed to do is the following:</p>
  
  <pre><code>public void startBluetoothScan() {
      if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
              == PackageManager.PERMISSION_GRANTED &amp;&amp; checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
          if (!scanning) {
              service.startScan();
          }
      }
  }
  </code></pre>
  
  <p>with this being the overall method:</p>
  
  <pre><code>private void configBluetooth() {
      BluetoothConfiguration config = new BluetoothConfiguration();
      config.context = getApplicationContext();
      config.bluetoothServiceClass = BluetoothLeService.class; // BluetoothClassicService.class or BluetoothLeService.class
      config.bufferSize = 1024;
      config.characterDelimiter = '\n';
      config.deviceName = "Your App Name";
      config.callListenersInMainThread = true;
  
      // Bluetooth Classic
      config.uuid = null; // Set null to find all devices on scan.
  
      // Bluetooth LE
      config.uuidService = UUID_HRS;
      config.uuidCharacteristic = UUID_HRD;
      config.transport = BluetoothDevice.TRANSPORT_LE; // Only for dual-mode devices
  
      BluetoothLeService.init(config);
      service = (BluetoothLeService) BluetoothLeService.getDefaultInstance();
  
      service.setOnScanCallback(new BluetoothLeService.OnBluetoothScanCallback() {
          @Override
          public void onDeviceDiscovered(BluetoothDevice device, int rssi) {
              Log.d("Found device address", device.getAddress());
              if (device.getAddress().equals(UserHRMAddress)){
                  if (!deviceList.contains(device)) {
                      Log.d("Connecting to", device.getAddress());
                      connectDevice(device);
                      deviceList.add(device);
                  }
              }
          }
  
          @Override
          public void onStartScan() {
              Log.d("Started Scan", "now");
              scanning = true;
          }
  
          @Override
          public void onStopScan() {
              Log.d("Stopped Scan", "now");
              scanning = false;
              startBluetoothScan();
          }
      });
  
      service.startScan();
  }
  </code></pre>
  
  <p>The method above is the usage of <a href="https://github.com/douglasjunior/AndroidBluetoothLibrary" rel="nofollow noreferrer">this</a> library that should make BLE easier (I tried it raw and liked it equally little) Basically the scan returns the same device about a thousand times in a few seconds, without having the chance to connect to it first. Is there a possibility to let every device only be discovered once while scanning? Is there a more appropriate way to implement a 24/7 search with automated connecting?</p>
  
  <p>What I also found out is, that the BluetoothGattCallback onConnectionStateChange method does e.g. not get called when you simply turn the BLE device off, or if you enter flight mode. If it did that, it would make my life a lot easier.</p>
  
  <p>The relevant parts of my BluetoothGattCallback method look like this:</p>
  
  <pre><code>@Override
          public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
              if (newState == BluetoothProfile.STATE_CONNECTED) {
                  Log.d("onConnectionStateChange", gatt.getDevice().getName());
                  mBluetoothGatt.discoverServices();
              } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                  //mBluetoothAdapter.startLeScan(mLeScanCallback);
              }
          }
  
          @Override
          public void onServicesDiscovered(BluetoothGatt gatt, int status) {
              if (status == BluetoothGatt.GATT_SUCCESS) {
                  Log.d("Status", "success");
                  heartRateService = gatt.getService(UUID_HRS);
                  batteryLevelService = gatt.getService(Battery_Service_UUID);
  
                  if (batteryLevelService != null) {
                      batteryLevelCharacteristic =
                              batteryLevelService.getCharacteristic(Battery_Level_UUID);
                  }
  
  
                  if (heartRateService != null) {
  
                      heartRateCharacteristic = heartRateService.getCharacteristic(UUID_HRD);
                      boolean res = gatt.requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER);
                      gatt.setCharacteristicNotification(heartRateCharacteristic, true);
  
                      try {
                          BluetoothGattDescriptor descriptor = heartRateCharacteristic.getDescriptor(
                                  UUID.fromString(CLIENT_CHARACTERISTIC_CONFIG));
  
                          descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
  
                          mBluetoothGatt.writeDescriptor(descriptor);
                      } catch (Exception ex) {
                          Log.e(TAG, "wuuuuut?");
  
                      }
  
  
                  }
  
              } else {
                  Log.w(TAG, "onServicesDiscovered received: " + status);
              }
          }
  </code></pre>