Anyone having issues on using the Nexus 4 to connect to a BLE Device? I am using a BLE module based off of the TI CC2540. I was able to connect to the BLE device, discover services, write to characteristics, and write to descriptors for notifications. Then all of a sudden I am not able to connect to the device anymore. I unpaired the device from the phone, did a factory reset as well, and nothing seems to work.
I also was following what others did in this post Android 4.3 Bluetooth Low Energy unstable
I disabled wifi, retstarted the Bluetooth module on the phone by disabling it and then enabling it. Like I said above this worked for a while, but now I cannot connect to the device using the connectGatt method. I also have the Samsung G4 that used the Samsung BLE SDK with Android 4.2.2 working with this same Bluetooth module which works still.
The main thing that I can see in the logcat is that a null pointer exception occurs when I do call the connectGatt(this, false, mBleGattCallback) is this:
10-07 16:29:04.745: DEBUG/BtGatt.GattService(1090): onConnected() - clientIf=4, connId=4, address=3C:2D:B7:84:F8:83
10-07 16:29:04.745: DEBUG/BluetoothGatt(13165): onClientConnectionState() - status=0 clientIf=4 device=3C:2D:B7:84:F8:83
10-07 16:29:04.745: WARN/BluetoothGatt(13165): Unhandled exception: java.lang.NullPointerException
I can see the code that is being called from the AOSP here: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/bluetooth/BluetoothGatt.java
Which seems strange since I hand the callback to the connect call which is not null. Anyone have any ideas?
See my reworked answer to Android 4.3 Bluetooth Low Energy unstable I added my experience with Samsng Galaxy S3 while connecting. Maybe that works for you.
If you have a different problem and you analyzed it well, you can write an email to the samsung engineers: blesdk (this is the at sign) samsung [dot c om )
Related
Currently testing the latest Android 7.1.1 developer preview (NPF26F) and running into this weird behavior with Bluetooth LE:
Open GattServer from device A
Establish Gatt connection from device B to device A (Connection is successfully established)
Force Stop app in device A (GattServer)
At this point, the expected behavior would be that The GattServer in device A would be closed and all connections to it would also be closed, however this doesn't seem to be happening as no disconnection event is thrown to the BluetoothGattCallback in device B.
It seems that the only way to cut the connections and stop the GattServer is to turn off the Bluetooth antenna.
I've already reported this issue here: https://code.google.com/p/android/issues/detail?id=228432 but only got a confusing reply on how to work aroud it (which by the way, doesn't work)
Is this working as intended? Or is there something i can do to properly report disconnection events?
Edit: It seems that this only happens with the Nexus 5x and Nexus 6p with the latest developer preview NPF26F. I've also tested with other devices with API 23 and they seem to be working correctly.
I'm working on an Android app that needs to connect to a Bluetooth Low Energy device.
The app is working correctly on most devices but i had troubles with some devices (One plus One with Cyanogene Android 4.4.4 and Sony C5303 with Android 4.3) using BluetoothAdapter.startLeScan().
With the One plus, the problem seems to be the same as related in this post: Android 4.3: BLE: Filtering behaviour of startLeScan() the Bluetooth device is only scanned once. If I connect then disconnect from the device, it is not scan it again.
After some test I tried using: BluetoothAdapter.startDiscovery() in addition to BluetoothAdapter.startLeScan().
It appears that my device is now correctly scanned multiple times and my LeScanCallback is correctly called. I can then connect/disconnect from my BLE device.
Question is:
How BluetoothAdapter.startDiscovery() can interact with BluetoothAdapter.startLeScan() to allow my device being detected multiple times ?
Thanks for you help !
You should calling 'stopLeScan()' correctly. After adding stopLeScan your device should be detected correctly.
I am creating an APP in which I need to sync the data from pedometer(Bluetooth 4.0). I took reference from Android sample BLE project.
It's working fine with most of the devices but in some model like XIAOMI MI5 and some samsung models like E7 I am facing issue where BluetoothGattCallback functions are not getting called.
Sometimes If I connect pedometer with other APP and then reconnect it with my APP it starts working.
I am unable to find where is the problem.What is the best way to make it work on all supported phones?
You can print some log in method onConnectionStateChange of BluetoothGattCallback so that you can confirm whether your bluetooth connection state is connecting.
I'm working on a BluetoothLE sensor device, for which I need to form a one-to-many broadcast of data. As per the spec, peripherals may only have a single master, and due to limitations of the chip and stack I'm designing on, a master can only have three slaves. From what I understand, Android cannot become a BLE slave anyway, so having my device as a master is not an option.
Both the BT4 spec and manufacturer documentation talk about another mode of operation, referred to as Broadcast mode. In broadcast mode, a connection is never made, and the application data is transmitted as part of the advertising packet. This will exactly fit my needs, as many Android/iOS phones can simultaneously scan down each packet. An advertising packet is transmitted multiple times in bursts, so I suspect reception of data to be mostly reliable. If a packet is lost here and there, it can be tolerated.
Where this gets interesting, is that I want these packets to carry live sensor data, that updates at a rate of 10-20Hz. From examples I've found on the web, BLE in this mode is mostly being used for "iBeacon" type implementations, where they are broadcasting static data. I cannot find any information on how advertising packets are filtered within the Android stack. It could be that they return one result per Bluetooth hardware address, or it could be the unique combination of address and data. The second option would work for this application. If starting and stopping the scan resets the filter, I can make something work as well.
The Android documentation mentions nothing about how device filtering in the scan method works. I've been able to find one post on the net attempting to solve this same problem, which has an unresolved response: BLE: Multiple discovery of the same peripheral during scan. In iOS, my colleague informs me that there is a parameter that can be passed to the scan function that makes this possible.
I've attempted to trace the code back from the startLeScan() call in the Android source, but the code is quite complex, and the use of abstraction has made it difficult to identify the implementation of the object that contains it. The farthest I've gotten is to an IBluetoothGatt object returned from the BluetoothManagerService class method getBluetoothGatt(). This object receives the request to start scanning. It is being instantiated around line 790 of BluetoothManagerService.java on the current revision live on github. The object is being cast from the result of a message, so I suspect maybe the result is phone/driver specific. It is beyond my expertise to be able to trace it any further.
Another question I would like to resolve is how rapidly the scanning can be switched on and off. Scanning is a power intensive operation, yet the broadcast of data will happen periodically on a fairly precise, real time timer. As a result, it would be a great optimization if the scan can be switched on and off, such that the broadcast and scan are synchronized, with the scanner shut down the other 90%+ of the time. This will likely need to be tested experimentally.
I'm still doing feasibility research to see if this is possible for our accessory for Android. My present phone cannot yet run version 4.3, so I have no way of testing/hacking this experimentally.
With Android 4.3 and 4.4 so far, it appears to be a mess: Some devices call
onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) multiple times for one device in one scan, some don't. There is no way to configure the filtering like in iOS (see answer of
Arkadiusz Konior). So, I now start a list, because I can't ask my users such a question about their device.
However, restarting scaning is also no problem on "not filtering" devices. So, I restart scaning on every device now.
Not filtering (Continuously calling onLeScan())
Samsung Galaxy S4 with 4.2.2 using Samsung BLE sdk (I owned that device)
Nexus 5 with 4.4 (added by [vegarwe]. The device will give scan records continuously for nearby devices while scanning)
Samsung Galaxy S3 with 4.3 (JSS15J.I9300XXUGMK6, I was testing on that device)
Samsung Galaxy S4 with 4.3 and 4.4.2 using Android SDK (added by arnaud.b, no build provided)
HTC One with 4.4.2 (added by arnaud.b, no build number provided)
Filtering devices (applies to Standard)
Nexus 4 with 4.3, 4.4 (I own that device)
Nexus 7 2013 4G with 4.4.2 (KOT49H, I was testing on that device)
Samsung Galaxy S4 mini with 4.2.2 (I was testing on this device)
Motorola Moto X (added by user1603602, no information about android version provided)
Motorola Moto G with 4.3 (falcon_umts, My testing device)
Sony Xperia Tablet Z Wifi with Android 4.3 (Build 10.4.B.0.577, Model SGP311, my testing device)
OnePlus One with 5.0.1 and 5.1.1 (Cyanogen 12.1)
Unknown filtering behavior (Please help to associate the device to a certain group)
Nexus 7 2013 (Different behavior is reported like here. But I have read more reports that it's belonging to first group.)
Other SAMSUNG, HTC, Motorola, ..., devices
The text in pages 2535-2536 in the Bluetooth specification (Core_v4.1.pdf) about duplicate advertising reports is somewhat unclear. However the text on page 1258 is clear. It specifies a Filter_Duplicates parameter to the HCI_LE_Set_Scan_Enable command. In Android version 4.4 (Kitkat) this parameter is 0x00 (Duplicate filtering disabled).
There is a simple way to find out if any filtering is done in the Bluetooth chip from Android versions 4.4 (Kitkat). Make the phone a developer phone, enter developer options and check “Enable Bluetooth HCI snoop log”. Then turn Bluetooth OFF and ON once to make the settings bite. From now on all HCI packets between the application processor and the Bluetooth chip will be stored on the phone in a file which is pulled by adb pull storage/emulated/legacy/btsnoop_hci.log . This is not a text file and you need a program from http://www.fte.com/products/default.aspx or wireshark to view btsnoop_hci.log. For wireshark you need a pretty recent version, because older versions does not support BLE. My experience is that there is never any filtering in the Bluetooth chip, i.e. the HCI Event “LE Advertising Report Event
” is sent for every ADV_IND
and ADV_NONCONN_IND
that the Bluetooth chip receives. This goes for phones with Bluetooth chips Qualcomm/Atheros WCN 3680 and Broadcom BCM 4339.
Correction: the path to btsnoop_hci.log can be different depending on the phone manufacturer. You can find the correct path by adb shell cat etc/bluetooth/bt_stack.conf | grep BtSnoopFileName
I'm developing the application for Android 4.3 (Nexus 4&7) using BLE and from my observations scanning returns the same device multiple times if there was no SCAN REQUEST send back to the peripheral.
Device may advertise in 2 ways: passive and active. In passive mode the peripheral device is just advertising all of it's data and doesn't listen after sending periodic packet. It's just sending, sleeping, sending, sleeping...
In active mode the sensor also advertises but the message is as short as possible. After sending it it switches to listening for some very short time. When scanned detects the short message, it immediately sends SCAN REQUEST command to the peripheral and gets response with more details. As far as I can see Android doesn't sent SCAN REQUEST multiple times during one scanning.
Let's assume that we have 2 devices in range. One is f.e. Nordic's nRF Temp sensor (passive advertising) and one other connectible device. I've received the following scan response:
11-10 21:32:54.281: D/BluetoothAdapter(13468): startLeScan(): null
11-10 21:32:54.281: D/BluetoothAdapter(13468): onClientRegistered() - status=0 clientIf=4
11-10 21:32:54.321: D/BluetoothAdapter(13468): onScanResult() - Device=CD:61:1A:A8:BC:BE RSSI=-94
11-10 21:32:55.122: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61
11-10 21:32:56.414: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62
11-10 21:32:57.715: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-61
11-10 21:32:59.016: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:01.609: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:02.901: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-63
11-10 21:33:04.212: D/BluetoothAdapter(13468): onScanResult() - Device=CB:32:81:CF:FD:00 RSSI=-62
11-10 21:33:04.282: D/BluetoothAdapter(13468): stopLeScan()
As you can see the connectible device showed up just once while the other one 7 times.
Another question I would like to resolve is how rapidly the scanning can be switched on and off. Scanning is a power intensive operation, yet the broadcast of data will happen periodically on a fairly precise, real time timer. As a result, it would be a great optimization if the scan can be switched on and off, such that the broadcast and scan are synchronized, with the scanner shut down the other 90%+ of the time. This will likely need to be tested experimentally.
Scanning frequency depends on the device. Furthermore advertising is usually done on 3 channels: 37, 38 and 39 to increase probability of being found. However this might be quite good idea to get advertising packets from 'active' devices multiple times.
The actual bluetooth spec says:
Duplicate advertising reports are not required to be sent to the Host.
A duplicate advertising report is an advertising report for the same
device address while the Link Layer stays in the Scanning State. The
advertising data may change; advertising data or scan response data is
not considered significant when determining duplicate advertising
reports.
According to the spec this applies within a scan period, which suggest that the correct way around this is to stop and restart scanning every time you receive an advertisement.
Based on my experience with BLE, it seems like sending variable data in advertisments is just not a very good idea. Almost everything assumes that the data from advertisements does not change. If you want to actually send variable data (e.g. thermometer readings) then it is much better to actually connect to the device and do it via a characteristic. It is more reliable and uses much less power. The downside is you can only connect to 8 devices at once.
Advertisements are meant for detecting the presence of devices and identifying them.
In iOS this flag is named CBCentralManagerScanOptionAllowDuplicatesKey. Passing it to scan function causes notification for every advertisement packet. I couldn't find similar flag in Android.
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.