title: BLE Android - onConnectionStateChange not being called
body: <p>I have a problem trying to connect to a peripheral. Sometimes the callback <code>onConnectionStateChange(...)</code> is not called after <code>BluetoothDevice#connectGatt(...)</code>. What I'm trying to achieve is fast and short connections triggered by user action.</p>
  
  <p>This situation occurs about 1 every 10 times without specific prior action. It lasts about 20 to 30 seconds or until the application is killed and reopened. The normal sequence of steps I follow is:</p>
  
  <ol>
  <li>Scan devices to find the peripheral.</li>
  <li>Call <code>BluetoothDevice#connectGatt(...)</code>. If it takes longer than 1 second to connect, it means that the connection is "stuck" and therefore it won't connect, so <code>BluetoothDevice#connectGatt(...)</code> is called again. This is done with a limit of 5 attempts.</li>
  <li><code>onConnectionStateChange(...)</code> is called with <code>newState</code> CONNECTED and begins the services discovery.</li>
  <li>The rest of the operations are performed without problems.</li>
  <li>After disconnection <code>BluetoothGatt#close()</code> is called.</li>
  </ol>
  
  <p>The problem occurs at point 3. Sometimes <code>onConnectionStateChange(...)</code>is not called. I have noticed that most of the times the problem starts with a specific behavior. After calling <code>BluetoothDevice#connectGatt(...)</code>, <code>onConnectionStateChange(...)</code> is called with <code>newState</code> CONNECTED, but almost immediately afterwards (~40 milliseconds) is called again with <code>newStatus</code> DISCONNECTED. Due to the short time of the status change, I can deduce that the device does not even tried to make the connection and changed the state to DISCONNECTED.
  The problem ends when:</p>
  
  <ol>
  <li>20-30 seconds have passed. During this time <code>onConnectionStateChange(...)</code> is never called. When the problem ends, <code>onConnectionStateChange(...)</code> is called the number of times that the app tried to connect. For example, if <code>BluetoothDevice#connectGatt(...)</code> is called 15 times, <code>onConnectionStateChange(...)</code> is called 15 times with <code>newState</code> equal to DISCONNECTED. This is curious because never in any of those connection attempts the status changed to CONNECTED. </li>
  <li>The app is killed and started again.</li>
  </ol>
  
  <p>This error occurs in SDK18 and SDK 21.</p>
  
  
  
  <pre><code>@Override
  public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
      String deviceName = device.getName();
      if (deviceName == null) return;
      Log.d("BLUETOOTH CONNECTION", "Device found: " + device.getName());
      if (mMode == SCAN_MODE) {
          mListener.deviceFound(device, rssi, scanRecord);
      }
      else {
          mDevices.put(device.hashCode(), device);
          stopScan();
          // Samsung devices with SDK 18 or 19 requires that connectGatt is called in main thread.
          mHandler.post(new Runnable() {
              @Override
              public void run() {
                  Log.d("BLUETOOTH CONNECTION", "Executing first device.connectGatt()");
                  BluetoothGatt gatt = device.connectGatt(mContext, false, mGattCallback);
                  retryIfNecessary(device, gatt);
                  mTryingToConnect = true;
              }
          });
      }
  }
  </code></pre>
  
  
  
  <pre><code>private void retryIfNecessary(final BluetoothDevice device, final BluetoothGatt gatt) {
      if (isRetryLimitReached()) {
          Log.d("BLUETOOTH CONNECTION", "Try count limit reached");
          finishConnection(gatt);
          mRetryCount = 0;
          mListener.error(TIMEOUT);
          return;
      }
      mRetryCount++;
      mHandler.postDelayed(new Runnable() {
          @Override
          public void run() {
              Log.d("BLUETOOTH CONNECTION", "Check if it is frozen.");
              if (isWorking()) {
                  Log.d("BLUETOOTH CONNECTION", "Frozen, create new connection.");
                  BluetoothGatt gatt = device.connectGatt(mContext, false, mGattCallback);
                  retryIfNecessary(device, gatt);
              }
          }
      }, RETRY_INTERVAL_MS);
  }
  </code></pre>
  
  
  
  <pre><code>    @Override
      public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
          Log.d("BLUETOOTH CONNECTION", "On connection state changed. Device: "+ gatt.getDevice().getAddress());
          if (!mConnected &amp;&amp; BluetoothGatt.STATE_CONNECTED == newState) {
              Log.d("BLUETOOTH CONNECTION", "Connected");
              mTryingToConnect = false;
              mTryingToDiscoverServices = true;
              mConnected = true;
              gatt.discoverServices();
          }
          else if(BluetoothGatt.STATE_DISCONNECTED == newState) {
              Log.d("BLUETOOTH CONNECTION", "Disconnected and closing gatt.");
              mConnected = false;
              gatt.close();
              if (!mConnectionFinished &amp;&amp; mRetryCount == 0) {
                  finishConnection(gatt);
              }
          }
      }
  </code></pre>
  
  <p>I think that the peripheral is not relevant, because the iOS app can always connect without this problem.</p>
  
  <p>Any ideas? Thanks in advance.</p>
  
  <p><strong>Edit!</strong></p>
  
  <p><a href="https://stackoverflow.com/questions/22214254/android-ble-connect-slowly/23749770#23749770">This</a> answer say that:</p>
  
  <blockquote>
    <p>Direct connection has interval of 60ms and window of 30ms so
    connections complete much faster. Additionally there can only be one
    direct connection request pending at a time and it times out after 30
    seconds. onConnectionStateChange() gets called with state=2,
    status=133 to indicate this timeout.</p>
  </blockquote>
  
  <p>So in this 30 seconds interval there is a pending connection request and times out at the second 30. It's unlikely but, is there anything I can do to make this time shorter? Or maybe there is an explanation for the connection failure that I am not seeing. Thanks.</p>
  
  <p><strong>EDIT 02/03/2016</strong></p>
  
  <p>A new information that may help. When the problem starts (when <code>onConnectionStateChange(...)</code> is called with <code>newState=DISCONNECTED</code> after ~40ms of being called with <code>newState=CONNECTED</code>), the status is 62 = 0x03E. Looking <a href="https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/11ade82/stack/include/gatt_api.h" rel="nofollow noreferrer">here</a> that status code means GATT_CONN_FAIL_ESTABLISH. When I detect this status I'm closing the gatt connection, but the problem persists. I also tried disconnecting and closing. Ideas? Thanks.</p>