I'm making an application which has to talk to a BLE devices on Android.
I am running into issues establishing the connection to the BLE device.
Case 1) Scan:
During a scan after a device has been discovered and reported via
BluetoothLEScanCallback.onScanResult(...)
I am attempting the connect via:
result.getDevice().connectGatt(...)
Problem is on some devices I test this (namely HTC One M8 running Android 5.0.1 and HTC Desire 516 running Android 4.3) the connection process seems to fail, i.e. the callback
BluetoothGattCallback.onConnectionStateChange(....)
is simply not called most of the time.
Now this is not a consistent behavior, sometimes it is sometimes it is not.
The second problem is that often if the connection is established
the
BluetoothGatt.discoverServices()
call fails, i.e. the
BluetoothGattCallback.onServicesDiscovered(...)
is also not called. I tried retrying the call a couple of times spaced by X number of milliseconds but it seems to consistently fail regardless of the number of attempts or spacing between them.
Case 2 Listening
The pretty much same thing happens when I attempt to simply "listen" for a device, again calling
BluetoothDevice device = BluetoothManager.getAdapter().getRemoteDevice(macAddress);
device.connectGatt(...)
results often in the same situation.
In both cases I am having issue with Android most of the time, I have a Nexus 5 device on which that same code seems to work for the most part (sometimes the BT stack seems to fail to do its job)
A bit more disturbing that the iOS application we have has none of these problems.
Has anyone encountered these issues?
Any ideas how to address them?
EDIT:
We did "solve" this one. Just in case somebody stumbles on such situation, the issue in my case is that ymmv a lot from device to device or even from connection to connection.
Sometimes the process happens in a second or so other times it takes 5, in my tests it can climb up to like 15 on the devices I test with.
As for why this is I can't tell.
I encounter the same problem. I connect to a Bluegigga BLE113 bluetooth 4.0 module. My app is based on the BluetoothLeGatt Sample source. My Samsung phone connects great, with no problems. My LG V10 can't connect. Except sometimes, when it will connect. Mostly, it won't connect. onConnectionStateChange never gets called. It is very frustrating, and I haven't been able to figure out the problem.
But I can connect my LG phone if I use NRF Connect, which seems to prove there is a programming solution. But they don't release the source for NRF-Connect.
If anyone can expand of how to fix this, I would appreciate it.
Related
I'm developing a Android Application to control a small device over BLE. The app is more or less finished, but during testing we noticed some weird behaviour. On most phones there are no issues, but on Android 7.1.2 the app keeps disconnecting after notifications are enabled.
The App works perfectly on most phones we tested on, but on Android 7.1.2 the phones disconnect with status 8 (connection timeout) once notifications are enabled.
We are using the RN4870 michrochip module, which might have some issues with it, seeing as when we wrote a simulated peripheral app to run on another phone, the problem phone connected and remained connected after notifications were enabled.
From further reading, the primary issue seems to be with the connection parameters being set to 20 seconds for supervision timeout on the problem phones, which appeared to cause issues for other developers and has appeared in various bug reports for google.
-- edit --
A link to the hci snoop file,
https://drive.google.com/open?id=1XzzwfhVGoZ__sP7R4BkMwnU-ahOgR8-a
Thanks for advance for any help, and if anyone requires anything to be edited feel free to let me know (my first forum post).
Bluetooth error code 0x08 (Connection Timeout) simply means that the two Bluetooth chips lost each other. It has nothing to do with the Android software since Android runs on the main CPU (in another chip). Having notifications enabled or not should also not make any difference, other than the fact that some data is being sent over the link to set that up.
The timeout of 20 seconds has been reduced to 5 seconds in newer Android versions since as you noticed 20 seconds are too much for most cases. It is however not a bug, just a feature.
If you get a BLE sniffer you should be able to figure out which device you should blame.
I'm having issues with random disconnects caused by the Android BLE stack.
Right after calling device.connectGatt I receive a disconnect with status 133 in my onConnectionStateChange method.
I've tested this on multiple devices running all kinds of Android versions and it happens on most of them. (More or less frequently)
I read about other cases where this behaviour seems to be caused by too many requests or faulty registered indications, but in my case there isn't even an active connection before the disconnect happens. Also I made sure nothing else but the connect request was sent to the device before this happens.
Hope someone can help me with this.
BLE support on "old" Android version can be quite hazardous, and BLE mechanisms are not easy to grasp.
I had the same issue as you did. I'm currently using RxAndroidBle, but it's basically a wrapper for the OS APIs, and highly facilitate the work, so I recommend it.
There are some things that you must remember when dealing with BLE:
- One command at a time
- Always close connections
On older version, you have to (quite mystically) set the boolean autoConnect parameter to true when trying to connect to a device while you are not scanning.
I just wasn't able to connect on my BLE device with Android < 6, set this parameter, and voilĂ , the magic happened.
I am working on a fitness app that is to supports two BLE sensors (heart rate, stride). I ended up with two bounded services (one for each sensor) called and bounded by my main activity. This is running on Nexus 7 II, with KitKat. I have spent days trying to get the app to stable state. The Gatt connections, and notifications work perfectly right after a clean reboot. The problem I am having is getting things back to a working state after one or both of the devices get disconnected and needs to be reconnected. Since similar issues have been reported by others, I have developed and tested various scenarios which included keeping the service and the connections going when the activity is restarted, closing the connections and the server and then starting fresh, closing only and not disconnecting, waiting before reconnecting, etc. Currently, with one sensor, I can get the app to reconnect most of the time. With two sensors, the connections do not get re-established most of the time. It is such a shame that android BLE API is so fragile considering that there are many new BLE devices every week. I am wondering if anyone else has had much luck with multiple BLE sensors and if they would share their approach to get it working.
This isn't a very question-y question but your comment indicates knowing what 0x85 means would help. The Android BLE API was taken from Samsung's second BLE API, but not all of the constants Samsung had defined made it over.
0x85 = 133 (which you also see in the logs) is GATT_ERROR. Basically this means that something went wrong, it could be the peripheral went out of range of the device, or the Bluetooth chip just messed up. I've found calling connect() on the BluetoothGatt in onConnectionStateChange is a decent solution since that will wait for things to get sorted out and connect when it can.
0x8D = 141 GATT_ALREADY_OPEN This one is pretty self-explanatory.
The other thing to watch out for is making sure anything happening to Bluetooth happens sequentially. Multiple threads sending commands to a BluetoothGatt before the result of the previous action happens tends to not be a good thing.
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?
Important implementation hints
(Perhaps some of those hints aren't necessary anymore due to Android OS updates.)
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.
Don't forget to call android.bluetooth.BluetoothGatt#close()
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)
Most devices filter advertising
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.
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.
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...
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.
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.
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.
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.
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();
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.
I have an Android app which, as part of its core functionality, makes ASP.NET WebService calls. I have authored the app successfully using ksoap2 to make the calls and it does what I need it to.
Our client reports that they have found some phones where the app does not work. Namely, during some of the WebService calls it appears to time out. This befuddled me because it works perfectly on the handful of phones we've tested it with here in my office.
One of the phones the client reported having an issue with was the Samsung Galaxy S2 on Sprint (the other phone they reported was either a Samsung Galaxy S or a Samsung Galaxy S3 - real similar phone, in other words). As luck would have it I was able to hunt down an employee in the company who had a Samsung Galaxy S2 on Sprint and was willing to let me borrow it. And I was able to re-create the issue. Attached to Eclipse it appears to be getting a SocketTimeoutException. Not every time, but more often than not.
As part of my testing, I connected the phone to a MiFi on Verizon. So, essentially I was taking it off of Sprint's network and putting it on Verizon's. When I did this, the app worked as expected, no timeouts.
At first I thought maybe Sprint's network was just bad but that seemed unlikely seeing as how my client is on the other side of the country from me so unless their network is consistently bad I doubt that's the case.
But what I noticed is - in the status bar of the phone, when connected to Sprint, I saw 3G and 4G icons, and they appeared to be switching back and forth (the way they're laid out, they both appear, just turned off/on right next to each other). When I was connected to the MiFi, as far as the phone knows or cares I'm connected to a Wi-Fi point.
So what I wonder is - could it be that the phone is "switching" back and forth between the 3G and 4G networks and the response to the webservice call is getting lost? On the iPhone if you make a request for a webpage in Safari with your phone on the 3G network (for example) and the phone then finds a Wi-Fi point to connect to and switches over, you still get the webpage on your device even after it connects to Wi-Fi. I presume that the OS is allowing the 3G calls to finish out before switching that network off.
Could something that Samsung has done with the OS for the Galaxy S* line be causing my responses to be getting lost? And if so, is there something I can do about it to prevent this from happening? Is there a way to figure out what network connections are still alive?
UPDATE: See my answer below, this question's premise turned out not to be the reason, although it does occur to me that I forgot to point out that the particular calls that fail or timeout contain base64-encoded images and so they're larger than normal webservice calls.
For what it's worth, the answer appears to be "no"
I used the code from this blog entry which allows me to monitor when a network connection change occurs and I was able to verify that the behavior occurs even when the network connection doesn't change.
So it does appear that for whatever reason this particular combination (Sprint/Samsung Galaxy S or S2) doesn't like what I'm doing.
One thing I forgot to mention is that I'm sending a Base64-encoded image across the web service call so the size may have some relation to it but I can't figure out what the issue is exactly.