33

I'm writing an Android app to connect to a BLE peripheral device. Android 4.4.2, Galaxy Nexus.

I have an LED on the device to indicate connection state.

The issue is the duration from connectGatt() call to the point of receiving onConnectionStateChange STATE_CONNECTED are so inconsistent. Some time it is very quick but most of the time it takes 5s or more. Turning Bluetooth off/on does not have any effect.

I tried TI BTool on PC with the TI BLE Dongle and it always establishes a connection very quickly.

I also tried with an iPhone 5S and it is fast too.

  1. Any one has experienced this issue too?
  2. Is there any chance we can improve this?
Chenmunka
  • 685
  • 4
  • 21
  • 25
user2810131
  • 331
  • 1
  • 3
  • 5
  • 4
    OK, I found the cause, I think I misused the APIs: Previously I call **connectGatt** with the 2nd param = true connectGatt(context, true, gattCallback); But now I change it to connectGatt(context, false, gattCallback); And the connecting time improved greatly – user2810131 Mar 06 '14 at 09:43
  • 4
    i already set connectGatt(context, false, gattCallback) but still taking 4-5 second to connect with ble device – Hitesh Gehlot Mar 18 '17 at 07:55

2 Answers2

62

Passing true to connectGatt() autoconnect argument requests a background connection, while passing false requests a direct connection. BluetoothGatt#connect() always requests a background connection.

Background connection (according to Bluedroid sources from 4.4.2 AOSP) has scan interval of 1280ms and a window of 11.25ms. This corresponds to about 0.9% duty cycle which explains why connections, when not scanning, can take a long time to complete.

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.

I have verified this behavior on Nexus5 but obviously YMMV.

I should mention that there is a race condition in BluetoothGatt.java that can cause a direct connection request even if autoconnect=true is passed into BluetoothDevice#connectGatt().

Juha Kuikka
  • 651
  • 5
  • 3
  • 26
    It would be amazing if Android's documentation actually mentioned any of this, at all. It's sort of important. – Glenn Maynard Jul 10 '15 at 21:52
  • 1
    Detailed description of the race condition that causes a direct connection instead of background: https://code.google.com/p/android/issues/detail?id=69834 – sergey.n Sep 07 '15 at 02:39
  • I've just noticed, that my Sony Xperia (D5803) running Android 5.0.2 doesn't call "onConnectionStateChange" with status=133 and newState=Connected but calls instead "onConnectionStateChange" with newState=Disconnected. – Linard Arquint Sep 15 '15 at 16:20
  • Til 2016-08-09 there is nothing close to this answer on the official documentation. Yet, the timeout now seems to receive a 'disconnected' signal. – March3April4 Aug 09 '16 at 01:29
  • 1
    This was super useful. Just changed this and drastically improved the connection speed. – Shamps Aug 01 '18 at 06:56
2

I've experimented slow connection but only when attempting to reconnecting the remote device, connecting device at first time gets no problem but reconnecting remains the connection in the onClientRegistered() method

J Sanchez
  • 140
  • 8