BluetoothAdapter.startScan() vs BluetoothAdapter.startLeScan() - android

my goal is to find nearby Bluetooth devices(LE devices and "Classic"), in order to associate between current visible nearby devices to some functionality my app doing with it. (not a specific device/devices, but all of them!!!)
what I know:
startLeScan() would callback only with BLE devices
the two methods working in different way - while startBLeScan() managed by my code with callbacks while classic scan is managed by the system process, and returns the BluetoothDevice found via broadcasts.
what I don't know for sure:
assuming current device API level is 18+ startScan() will find always both discoverable BLE and classic devices.
BluetoothDevice.connectGatt() added with the new BLE API's, but should work also with classic bluetooth(return GATT Services...).
what I would like to know:
if indeed startScan() returns both types (Classic and BLE), what would be better to use in terms of battery consumption, performances, good practices and other aspects?
my application will perform background scans periodically, so I would like to minimize the battery consumption impact as possible.

You have to start a scan for Classic Bluetooth devices with startDiscovery() and a scan for Bluetooth LE devices with startLeScan(). Caution: Performing device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources.
Edit:
On LG Nexus 4 with Android 4.4.2 startDiscovery() finds Bluetooth LE devices.
On Samsung Galaxy S3 with Android 4.3 startDiscovery() doesn't find Bluetooth LE devices.

I have an off-market Chinese tablet that has BLE support, however, it always return a BLE equipped device with its name as "null" when I call startLeScan. The issue was resolved by calling startDiscovery. Remember that if your app targets 23 or above, you will need to have location permissions for startDiscovery to work correctly. Hope it helps.

Related

Bluetooth connection like wearable devices

I am searching for some way that can connect to Bluetooth devices without pairing. Or at least make a connection first and then it does not need to be established all the time. Like how wearable devices work (i.e. mi band 6 or Huawei band 6). Can someone please guide me towards some helpful demo or documentation for this somewhere?
Also, I was wondering how was the security managed since my Bluetooth is always on to communicate to the wearable device. Though, turning off discoverability does not seem to create any issues in order to communicate with the device.
Most wearables nowadays use Bluetooth Low Energy (BLE), and with BLE you don't need to pair in order to exchange data - i.e. only a connection is needed. That being said, it is recommended to pair as the data exchanged between the wearable device and the phone will be encrypted, in addition to some other benefits in terms of privacy and security, Have a look at the links below that will go over connection/pairing in more detail:-
Should one create a bond with BLE device
The Ultimate Guide to Android Bluetooth Low Energy
Making Android BLE work

Android - What API can I use to see if a device supports BLE central mode?

https://developer.android.com/guide/topics/connectivity/bluetooth-le#roles
Central vs. peripheral. This applies to the BLE connection itself. The
device in the central role scans, looking for advertisement, and the
device in the peripheral role makes the advertisement.
To check if a device supports "peripheral"/advertisement mode it looks as though I can use getBluetoothLeAdvertiser()
getBluetoothLeAdvertiser
added in API level 21 public
BluetoothLeAdvertiser getBluetoothLeAdvertiser () Returns a
BluetoothLeAdvertiser object for Bluetooth LE Advertising operations.
Will return null if Bluetooth is turned off or if Bluetooth LE
Advertising is not supported on this device.
Use isMultipleAdvertisementSupported() to check whether LE Advertising
is supported on this device before calling this method.
Now I've heard some rumors that some devices can actually give you a BluetoothLeAdvertiser, but return false on isMultipleAdvertisementSupported() which is another issue in itself, but on the central side of things, the docs don't say anything!
Am I missing something? https://developer.android.com/reference/android/bluetooth/BluetoothAdapter doesn't say anything about central mode. Am I missing something basic here? Thanks for any help. I have heard bluetooth is a pain on Android and it is my first day exploring these APIs.
Short Answer
As DigitalNinja pointed out, an Android phone will always support Central role functionality by default, so if your phone supports BLE, then it can definitely operate in the central Role
Long Answer
You're right, the API might not be straight-forward but this is down to how Bluetooth Low Energy (BLE) API was added to Android and even down to the history of BLE technology itself.
When BLE was first introduced, it was aimed to be for sensors only (e.g. thermometer, heart rate, proximity, etc) and devices that talk to these sensors. The sensors were the peripherals in this case, and the devices that talk to these sensors are the centrals. The peripherals were the true Low Energy (LE) devices, as they would just advertise and send data once in a while. Centrals on the other hand would not be very power efficient as they would have to continuously scan for devices, connect to these devices, and remain in charge of maintaining and monitoring that connection, meaning the radio would be on for a much longer time when compared to the peripheral.
When Bluetooth Low Energy (BLE) API was added to Android, it supported Central role only. In other words, you could write an Android app to scan and connect to peripherals (sensors), but the Android device itself could not act as a peripheral (Because the assumption was that you wouldn't need an Android device to act as a sensor). This was done in Android 4.3 (API 18).
As people started to use BLE more often and the technology matured, it started being used for all sorts of different applications (e.g. virtual serial port, data transfer, beacons, etc). Moreover, standalone central devices started appearing in the market and there was a need to use them with phones or at least test them out against phones/tablets during the development stages. As such, the distinction between central and peripheral started becoming fuzzier and fuzzier, and there was a demand for Android to start supporting peripheral role. This is when the BLE API was updated to introduce peripheral role functionality, which happened in Android 5.0 (API 21).
So to answer your question, if BLE is supported on an Android device then it is safe to state that it will by default support central role as this is the foundation of the BLE functionality for Android. However, API was introduced later to support the peripheral role, which is why not all Android devices that support BLE will support peripheral role.
Finally, please note that isMultipleAdvertisementSupported is a different feature which indicates if your device supports sending out multiple adverts at the same time. Some devices support sending out different adverts simultaneously, while others don't. However, this does not mean that they do not support advertising at all. A device that supports isMultipleAdvertisementSupported will definitely support BluetoothLeAdvertiser, but the other way around is not guaranteed.
To conclude, the safest way to check if your device supports central and/or peripheral role is through the Android version and the API level used, as indicated by the two links above. On Android 5 (API 21) onwards, you can write applications that support both central and peripheral roles, whereas before that you can only write applications for the central role.
I hope this helps.

Android & Dual mode Bluetooth device: Custom BLE service not found when paired to BR/EDR (Classic)

I've built a dual mode Bluetooth device using the BT 121 from Silicon Labs. The device implements SPP over the classic connection. The device name of the classic node is "XYZ Classic". It also implements a custom service (128-bit UUID) in BLE. The device name of the BLE node is "XYZ_BLE". Both nodes have the same MAC address.
When pairing under 'Bluetooth' settings, sometimes I will see 'XYZ Classic' and sometimes I will see 'XYZ_BLE'. It seems random which one it will pair to but many Android devices I've tested have a tendency to want to pair to the classic node. After pairing, a connection over classic/SPP ALWAYS works. However, I can only connect to the custom service if paired to the BLE node. If paired to classic I can see non-custom BLE services but not my custom service. To summarize:
Function Classic Pairing BLE Pairing
Spp Works Works
Cust BLE Doesn't Work Works
When I pair in code (Android) the problem also happens despite the fact that I search for the devices named 'XYZ_BLE' and then pair to the device returned. I've looked but I can't see a way to force Android to pair to the BLE node.
My only workaround thus far has been to modify my BT 121 firmware to not allow bonding in classic mode. This is not an ideal solution has any Bluetooth Classic only devices will not be able to bond with my device (In reality this might not be too big of a problem but I have one tablet in my possession that only has Bluetooth Classic).
It should be noted that I've used 'BLE Scanner' from the play store to verify that my custom service works/doesn't work depending on the pairing mode. In other words, it's not just my code. :)
So, does anybody have any ideas on how to force Android to pair to the BLE node?
I see similar issues. Some hints:
Android behaviour differs dependent on the bit flags you set in the BLE advertising. There is for example a bit called "no br/edr support" or so. There are also bits telling explicitly that br/edr dual role is supported.
Also ble pairing may be enforced if you access a characteristic which returns a "not authenticated error" from a ble app. At least on iohone, the os will initiate the ble pairing automatically.

Bluetooth Low Energy List

what is Bluetooth low energy in android.I know how to connect two devices using Bluetooth. But i don't know How to connect two android device using Bluetooth low energy.
If you wanna get a list of Bluetooth LE (Low Energy) devices. You need to use the Bluetooth LE scanning API's.
If you are supporting API's lower than 21 (above 18, though) you should use the startLeScan() to discover LE devices. When on API level 21 and above, you get access to a more robust and powerful scanning API that allows you to customize the devices returned back based on Services available, device name, MAC address and such. Instead of calling startLeScan on the BluetoothAdapter, you'd call startScan() on a BluetoothLeScanner object that you'd get from BluetoothAdapter via a call to getBluetoothLeScanner().
When using either API, you must have BLUETOOTH_ADMIN permission. You most also hold the at least one of the following location permissions, ACCESS_COARSE_LOCATION or ACCESS_FINE_LOCATION when running on API 21 and above.
To connect to an LE device you simply need to call connectGatt() on a LE BluetoothDevice. You can check if a BluetoothDevice is an LE device by calling getType() which returns a int constant that represents one of the various bluetooth device types android supports.
If you want to connect two device using bluetooth low energy then you need to make one device as a simulator same as BLE device, like your device one is advertising and In second device you need to scan that device and connect that device and now your both device is connected. you can send and receive data.
For Bluetooth advertising :
refer this link : - https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser

Android Lollipop BLE scan - getting peripherals without duplications

Android Lollipop introduced a new way to scan for BLE peripherals, via BluetoothLeScanner.
From what I read, the new scanning API solved an issue that happened with the old scanning API (BluetoothAdapter.startLeScan(UUID[],LeScanCallback)) where on some devices the callback (onLeScan) was called only once per peripheral, even if the peripheral keeps advertising.
This issue is handled on iOS with the CBCentralManagerScanOptionAllowDuplicatesKey option, that allows you to choose whether you want to detect only new peripherals or keep getting advertisements from previously-found peripherals.
Is there a similar option in the new Android Lollipop API? i.e. decide that you want the callback to be called only for new peripherals (new MAC addresses) and not called twice for the same peripheral.
I know that it could easily be implemented by saving a list\set of all the MAC addresses that were previously received - but this way does not take advantage of hardware optimizations.

Categories

Resources