Android 4.3 Bluetooth Low Energy unstable
Asked Answered
R

5

193

I am currently developing an application that will use Bluetooth Low Energy (testing on the Nexus 4). After getting started with the official BLE APIs in Android 4.3, I have noticed that after I connect a device for the first time I am rarely able to successfully connect to / communicate with that device or any other device again.

Following the guide here, I can successfully connect to a device, scan services and characteristics, and read/write/receive notifications without any issues. However, after disconnecting and re-connecting, I am often unable to either scan services/characteristics or unable to complete a read/write. I can't find anything in the logs to indicate why this is happening.

Once this happens I have to uninstall the application, disable Bluetooth, and restart the phone before it will start working again.

Whenever a device is disconnected I make sure to call close() on the BluetoothGatt object and set it to null. Any insights?


EDIT:
Log dumps: For these logs I rooted my phone and upped the trace levels of related items in /etc/bluetooth/bt_stack.conf

Successful connection - First attempt after rebooting the phone and installing the app. I am able to connect, discover all services/characteristics, and read/write.

Failed Attempt 1 - This is the next attempt after disconnecting from the successful connection above. It seems I was able to discover characteristics, but the first attempt to read returned a null value and disconnected soon thereafter.

Failed Attempt 2 - An example where I am not even able to discover services/characteristics.


EDIT 2:
The device to which I am trying to connect is based on TI's CC2541 chip. I obtained a TI SensorTag (also based on the CC2541) to play around with and discovered that TI released an android app for the SensorTag yesterday. However, this app has the same problem. I tested this on two other Nexus 4s with the same result: Connection to the SensorTag is successful the first or second time, but (according to the logs) fails to discover services thereafter, causing all sorts of crashes. I'm starting to wonder if it's an issue with this specific chip?

Rheinland answered 25/7, 2013 at 22:59 Comment(21)
Please post complete logs of your phone from boot-up till you facing the issue.Hemisphere
@Hemisphere I've just added related log dumps.Rheinland
Can you add a code snippet or pseudo code of what you're doing so that we can try our best to repro on other devices running 4.3? ThanksArletha
I have gone through the logs completely, and there seems no reason to get disconnected. have you tried testing with other remote device?Hemisphere
Don't know how helpful this is, but I am using a Nexus 4 connecting to a CC2541 and not having any problems.Fennelly
@Hemisphere I recently tested connectivity with a board from another manufacturer and it seems to work perfectly. However, as soon as I switch back to the CC2541 device or the SensorTag the problem starts - I can't even connect to the other board again.Rheinland
It looks like some other Nexus 4 and Nexus 7 (2012) users in the TI E2E forums are seeing the same issue with the SensorTag. We've caught the attention of one of TI's developers and hopefully he'll be able to give us more insight.Rheinland
it may be a remote device issue then.Hemisphere
I've noticed the same behavior (can connect only once, then need to reboot) with Polar's H7 heart rate monitor on the Nexus 4 with Android 4.3.Togo
I also get the 129 (GATT_INTERNAL_ERROR) and especially 133 (GATT_ERROR) a lot. The Samsung BLE SDK guys told me those codes. There are more: img-developer.samsung.com/onlinedocs/samsung_ble_docs_200/… They seem to be the same since their whole API is very similar.Mariselamarish
Could you be so kind a release the source of your app to the public (or me ;) ) since I also bought a SensorKit but I have no clue where to start. I managed to get the Google example to work and I can see the SensorKit but I'm not able to read any of the sensors.Hindorff
And additionally: The Google Bluetooth example neves fails to connect. Maybe this can help youHindorff
I spotted in your "failed"-log the line L2CA_EnableUpdateBleConnParams - unknown BD_ADDR <your device address> which doesn't occour in your "success"-log. Same applies to my testing experiences. However, this is just a consequence of the disconnect, which is stated some lines earlier at 124 with GATT ATT protocol channel with BDA: 9059af043336 is disconnected I have a BlueGiga chip by the way.Mariselamarish
I also get Unknown conn ID: as you got in pastebin.com/AhZq17bU I get this soon after registerApp(). At the 10th time I get Unknown conn ID: 10 D/BtGatt.btif(1077): btgattc_handle_event: Event 1000 E/bt-btif(1077): Register with GATT stack failed. failed. (about 20 times) D/BtGatt.btif(1077): btif_gattc_upstreams_evt: Event 0 E/BtGatt.btif(1077): bta_to_btif_uuid: Unknown UUID length 10! D/BtGatt.GattService(1077): onClientRegistered() - UUID=00000000-408a-6f08-ffff-fe58b0e98d19, clientIf=0 E/BtGatt.ContextMap(1077): Context not found for UUID 00000000-408a-6f08-ffff-fe58b0e98d19Mariselamarish
@Hindorff Google Bluetooth example also fails to connect after several connections to several BLE devices. Exactly the same behavior and log entries. I'm talking about the project in sdk\samples\android-18\legacy\BluetoothLeGatt which you can download via the Android SDK ManagerMariselamarish
I am using Samsung Galaxy S4 with leaked Google edition Android 4.3 installed; after numerous time of connecting/disconnecting,when I discover services I will randomly get 129(GATT_INTERNAL_ERROR) and get a onConnectionStateChange with status 133 (GATT_ERROR),state = BluetoothProfile.DEVICE_DISCONNECTED.Pamalapamela
For once or twice I got multiple status 129 and 133 callbacks in a short period of time and I could never receive any callback in BluetoothGattCallback until I reboot my device (but scanning is fine).Pamalapamela
Forget to say that I am testing with around ten devices using TI chips (sorry I don't know their models) and one device with Nordic chips. The device with Nordic chips never report error.(Not enough to prove the problem is TI specific,though)Pamalapamela
@Mariselamarish I worked alot on the Keyfob and the Sensorkit with TI chips and if BluetoothLeGatt fails to connect it connects the next attempt. I use a galaxy nexus. On the other hand: The official TI Sensorkit app acts like you describe.Hindorff
@Hindorff I want to know how many device are you connecting? In my case if I only connect/disconnect a few devices there is no outstanding problem. However when I connect to more devices, say, 10 or 15, it is easy to get errors and sometimes the BluetoothGattCallback just respond to nothing. Of course I maybe handling multiple connection badly, just want to know if anyone can do it successfully.Pamalapamela
I can confirm that this issue is still exist on Samsung Galaxy S5 (Both G900VVRU2BOG5 and G900VVRU2BOA8 build version). If I clear data from Settings>Application Manager>>All>>Bluetooth , it works for a time being.Boschvark
M
189

Important implementation hints

(Perhaps some of those hints aren't necessary anymore due to Android OS updates.)

  1. Some devices like Nexus 4 with Android 4.3 take 45+ seconds to connect using an existing gatt instance. Work around: Always close gatt instances on disconnect and create a fresh instance of gatt on each connect.
  2. Don't forget to call android.bluetooth.BluetoothGatt#close()
  3. Start a new thread inside onLeScan(..) and then connect. Reason: BluetoothDevice#connectGatt(Context context, boolean autoConnect, BluetoothGattCallback callback) always fails, if called inside LeScanCallback() {...}.onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) in the same thread on Samsung Galaxy S3 with Android 4.3 (at least for build JSS15J.I9300XXUGMK6)
  4. Most devices filter advertising
  5. Better not use android.bluetooth.BluetoothAdapter#startLeScan(UUID[] serviceUuids, LeScanCallback callback) with the parameter to filter for certain service UUIDs because this is broken completely in Samsung Galaxy S3 with Android 4.3 and doesn't work for 128bit UUIDs in general.
  6. Gatt always can process one command at a time. If several commands get called short after another, the first one gets cancelled due to the synchronous nature of the gatt implementation.
  7. I often see even on modern devices with Android 5, that Wifi interferes withs bluetooth and vice versa. As a last resort, turn off wifi to stabilize bluetooth.

Tutorial for beginners

A pretty OK entry point for newcomers could be this video tutorial: Developing Bluetooth Smart Applications for Android http://youtu.be/x1y4tEHDwk0

The issue and work around described below is probably fixed now by OS updates

Work around: I could "stabilize" my app doing that...

  1. I provide the user a setting "Restart Bluetooth". If that setting is enabled, I restart Bluetooth at some points that indicate the begin of BLE stack becoming unstable. E.g. if startScan returns false. A good point may also be if serviceDiscovery failes. I just turn Bluetooth off and on.
  2. I provide another setting "Turn off WiFi". If that setting is enabled, my app turns off Wifi when the app is running (and turns it back on afterwards)

This work around is based on follwoing experiences...

  • Restarting Bluetooth helps to fix problems with BLE in most cases
  • If you turn off Wifi, the BLE stack gets much more stable. However, it also works fine on most devices with wifi turned on.
  • If you turn off Wifi, restarting Bluetooth fully recovers the BLE stack without the need to reboot the device in most cases.
Mariselamarish answered 19/9, 2013 at 8:16 Comment(19)
Google, you got to fix this now. This work around (I did plus it because it does work) is ridiculous.Adey
Sometimes, service discovery will succeed with a status 0 (assuming no problems), yet characteristic reads will yield NULL values because it's essentially not really connected or the characteristics were not discovered (I see this in the log: 11-01 18:37:32.131: WARN/BluetoothGatt(20119): Unhandled exception: java.lang.NullPointerException)Sejm
@Sejm I always check after service discovery, if my expected service is included. You also can never be sure, if the service discovery gives any result. Sometimes I receive no callback. So I applied a timeout for service discovery.Mariselamarish
My experience is: Samsung S3 (4.3) successfully reconnected after closing a Gatt client as described in paragraph 2 above; using Nexus 4 & 7 (4.4.2) I could not reconnect after connection dropped, even by restarting BL adapter, but it can be reconnected automatically after 2 minHerrin
@konopko My experience: Samsung S3 (I9300, 4.3, Build JSS15J.I9300XXUGMK6) is one of the few devices that can reconnect using an existing gatt instance with no problem and no delay. Pls share your build number because BLE behavior may differ from build to build. I had not so much issues with Nexus 4 and Nexus 7 (2013) by connecting using a new gatt instance.Mariselamarish
@Mariselamarish my build the same as yoursHerrin
My Problem is over the Samsung Tab Pro.Trotter
As u mention "Always close gatt instances on disconnect and create a fresh instance of gatt on each connect." Then what will be purpose of BluetoothGatt.connect() ? Any suggestion ?Russelrussell
@Shubh The API of course suggests to use BluetoothGatt.connect() as u mention it. However, in the early days of BLE android implementations BluetoothGatt.connect() was broken in some smartphones. OS Updates might have fixed now the issues. Back than using my implementation hints was the only way to get a pretty stable BLE enabled app.Mariselamarish
true.,and it still same. After using device.connectGatt(..) if use BluetoothGatt.connect() then it's not working. Have u tried it again ?Russelrussell
@Shubh I haven't been working with BLE for months. Things have changed a little bit in API and on devices since then. Bugs (if they are real bugs, not your implementation mistakes) mostly depend on devices and their OS build version. Open another question on SO or contact the manufacturer. Good luck!Mariselamarish
Setting autoConnect to false in BluetoothDevice#connectGatt(...) speeds up the connect at least on the Nexus 7 as described in this answer: https://mcmap.net/q/136681/-android-ble-connect-slowlyCurarize
Zenfone 2, Note 3 have same problem. I think Google need fix this unstable issue. Since firmware device already turned off, why Mobile side still can scan & find out it. It totally be wrong. BLE unstable. In my case is scan beacon, so use basic BLE way work but get this unstable issue. I need change to use Android Beacon Library to do it & completed now.Flash
Can anyone confirm if android.bluetooth.BluetoothGatt can only handle one pending GATT operation PER DEVICE, PER PROCESS, or PERIOD (ie: across all processes). I presume it is PER DEVICE, but this problem is so mucked up that it wouldn't surprise me if it was otherwise. If the limitation is only PER DEVICE, then the OS/Device able to handle multiple simultaneous operations is smoking gun proof that this problem is purely due to some weak naive implementation in the BluetoothAdapter instance that the OS hands each process (that I had assumed was a singleton across all processes).Lax
in 6. the second command is ignored, not the first one. The first command is in execution, so you can't execute the second command. Happens in Lollipop.Retro
@Retro please add a reference to your findings, e.g. Documentation or source code. The docs I shared tell a different story. However, you have to avoid several commands at the time anyway.Mariselamarish
For example source code for android-23 (version M): public boolean readCharacteristic(BluetoothGattCharacteristic characteristic) { ... synchronized(mDeviceBusy) { if (mDeviceBusy) return false; mDeviceBusy = true; } ...Retro
Nexus 4 is the first device to exclude from anything BLE related!Garfield
In my experience, with some device, wifi breaks the bluetooth connection but only when wifi is 'on' AND 'disconnected'.Fitful
P
19

Turning WIFI OFF:

I can confirm too, that turning WIFI OFF makes Bluetooth 4.0 more stable especially on Google Nexus (I have a Nexus 7).

The problem

is that the application I am developing needs both WIFI and continous Bluetooth LE scanning. So turning WIFI OFF was no option for me.

Moreover I have realised is that continous Bluetooth LE scanning can actually kill WIFI connection and make the WIFI adapter unable to re-connect to any WIFI network until BLE scan is ON. (I'm not sure about mobile networks and mobile internet).
This definitely happened on the following devices:

  • Nexus 7
  • Motorola Moto G

However BLE scanning with WIFI on seemed pretty stable on:

  • Samsung S4
  • HTC One

My workaround

I scan BLE for a short period of time 3-4 seconds then I turn scan OFF for 3-4 seconds. Then ON again.

  • Obviously I always turn BLE scan OFF when I'm connecting to a BLE device.
  • When I disconnect from a device I restart BLE (turn adapter OFF and then ON) to reset the stack before starting scan again.
  • I also reset BLE when discovering services or characteristics fails.
  • When I get advertisement data from a device that the app should connect to (lets say 500 times without being able to connect - thats about 5-10 seconds of advertising) I reset BLE again.
Pasteurism answered 12/2, 2014 at 14:54 Comment(4)
You said I restart BLE after a device is disconnected. Suppose, If the user was transfering the file over bluetooth connection. Then, You will cause that bluetooth transfer to be failed at any time.Gumm
what do you mean by "turn adapter OFF and then ON"?Earful
I agree, Wifi and Bluetooth together is killing the app performance in Moto G.Va
@MarianPaździoch , by "turn adapter OFF and then ON" @ benka means BluetoothAdapterLiquidation
P
10

Make sure your Nexus is paired to the device. I can't verify whether or not the communication works properly, but you will be able to connect more than once without a reboot. It seems the first connect is not requiring pairing but all subsequent attempts do.

I will update this answer in a couple of days when I test service discovery and gatt read and write requests without a reboot.

EDIT: It turns out I was testing on a development firmware version (our sensor) that was causing issues if not paired. Our latest production firmware build works fine on the 2540s and 2541s.

EDIT: I did notice that on the Nexus 7 2013, connections are more stable when WiFi is turned off. I'd like to know if this helps anyone else.

EDIT: I seem to have had it backwards with pairing. Everything works fine when not paired. After pairing, I am experiencing the exact same symptoms as the OP. It's just not known yet if this is related to our firmware or the Android BLE API. Be careful if testing this because once paired, you may not be able to unpair due to a bug explained in 3b of this post.

Provincetown answered 2/8, 2013 at 0:32 Comment(8)
I am consistently connecting and reconnecting to a CC2541 device without any sort of manual pairing or reboot.Fennelly
For my opinion, there is no pairing necessary. The official docs don't comment pairing also. I also could perform write, read, characteristic changed notification without any pairing. However, just for a short time. Now it's shaky again... The SAMSUNG BLE SKD v2.0 also didn't require pairing and worked quite good.Mariselamarish
I can confirm, it's more stable after turning off Wifi. Everybody should try that.Mariselamarish
@Mariselamarish Are you using the new Nexus 7 as well?Provincetown
@Provincetown I have a Nexus 4.Mariselamarish
Whether pairing is required or not is dependent up the device implementation. nrf8002 devices require pairing and the Samsung 2.0 and 1.2 API's both supported this. It seems like the official api support is having problems with the pairing aspect as after I pair a ble device, it seems impossible to unpair!Adey
I have a work around for being unable to unpair. 1) go to your bt menu, select unpair, remove the ble device from the area or depower it, select the ble device in the bt menu and it'll try to pair and fail, then reset bluetooth. Upon reset the device will be unpaired.Adey
OK. I got a Nexus 7 (2013) today, run my app, the first impression is smooth and stable. Connect/disconnect/discover services without problem until this point. I was encountering those problems regularly on Samsung Galaxy S4, FYI.Pamalapamela
B
8

In some models there is a defect: https://code.google.com/p/android/issues/detail?id=180440

On the other hand in my case the problem was, that my connection was not properly closed in onDestroy method. After correct closing, problem for me is not existing, not matter that wifi is turned on or off.

btGatt.disconnect();
btGatt.close();
Bracy answered 13/2, 2016 at 19:7 Comment(2)
Why is close necessary?Prosperus
Correct closing procedure is Key when you want to connect Bluetooth multiple times. In my experience it works best if you run your Ble connection in a seperate UNBOUND service so you can start and stop it by hand. And that you call mConnectedGatt.disconnect(); ble_device=null; in your inDestroy(). In my case this pattern works stable without a problem.Azole
T
5

I was facing a similar issue. My fix was

if (Build.VERSION.SDK_INT >= 23) {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE);
} else {
  mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
}

& calling close after disconnect.

Thin answered 5/4, 2019 at 14:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.