Android bluetooth find devices

Find BLE devices

To find BLE devices, you use the startScan() method. This method takes a ScanCallback as a parameter. You must implement this callback, because that is how scan results are returned. Because scanning is battery-intensive, you should observe the following guidelines:

  • As soon as you find the desired device, stop scanning.
  • Never scan on a loop, and always set a time limit on your scan. A device that was previously available may have moved out of range, and continuing to scan drains the battery.

In the following example, the BLE app provides an activity ( DeviceScanActivity ) to scan for available Bluetooth LE devices and display them in a list to the user. The following snippet shows how to start and stop a scan:

Kotlin

private val bluetoothLeScanner = bluetoothAdapter.bluetoothLeScanner private var scanning = false private val handler = Handler() // Stops scanning after 10 seconds. private val SCAN_PERIOD: Long = 10000 private fun scanLeDevice() < if (!scanning) < // Stops scanning after a pre-defined scan period. handler.postDelayed(< scanning = false bluetoothLeScanner.stopScan(leScanCallback) >, SCAN_PERIOD) scanning = true bluetoothLeScanner.startScan(leScanCallback) > else < scanning = false bluetoothLeScanner.stopScan(leScanCallback) >>

Java

private BluetoothLeScanner bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner(); private boolean scanning; private Handler handler = new Handler(); // Stops scanning after 10 seconds. private static final long SCAN_PERIOD = 10000; private void scanLeDevice() < if (!scanning) < // Stops scanning after a predefined scan period. handler.postDelayed(new Runnable() < @Override public void run() < scanning = false; bluetoothLeScanner.stopScan(leScanCallback); >>, SCAN_PERIOD); scanning = true; bluetoothLeScanner.startScan(leScanCallback); > else < scanning = false; bluetoothLeScanner.stopScan(leScanCallback); >>

Note: The BluetoothLeScanner is only available from the BluetoothAdapter if Bluetooth is currently enabled on the device. If Bluetooth is not enabled, then getBluetoothLeScanner() returns null.

To scan for only specific types of peripherals, you can instead call startScan(List, ScanSettings, ScanCallback) , providing a list of ScanFilter objects that restrict the devices that the scan looks for and a ScanSettings object that specifies parameters about the scan.

The following code sample is an implementation of ScanCallback , which is the interface used to deliver BLE scan results. When results are found, they are added to a list adapter in the DeviceScanActivity to display to the user.

Kotlin

private val leDeviceListAdapter = LeDeviceListAdapter() // Device scan callback. private val leScanCallback: ScanCallback = object : ScanCallback() < override fun onScanResult(callbackType: Int, result: ScanResult) < super.onScanResult(callbackType, result) leDeviceListAdapter.addDevice(result.device) leDeviceListAdapter.notifyDataSetChanged() >>

Java

private LeDeviceListAdapter leDeviceListAdapter = new LeDeviceListAdapter(); // Device scan callback. private ScanCallback leScanCallback = new ScanCallback() < @Override public void onScanResult(int callbackType, ScanResult result) < super.onScanResult(callbackType, result); leDeviceListAdapter.addDevice(result.getDevice()); leDeviceListAdapter.notifyDataSetChanged(); >>;

Note: You can only scan for Bluetooth LE devices or scan for classic Bluetooth devices, as described in Bluetooth overview. You cannot scan for both Bluetooth LE and classic devices at the same time.

Читайте также:  Lenovo s110 bluetooth driver

Content and code samples on this page are subject to the licenses described in the Content License. Java and OpenJDK are trademarks or registered trademarks of Oracle and/or its affiliates.

Last updated 2021-10-27 UTC.

Источник

Find all Bluetooth devices (headsets, phones etc) nearby, without forcing the devices in discoverable mode

My goal: To detect all nearby Bluetooth devices(phones, headsets, etc.) from my Android application. Here’s a nice example from developer.android.com which discovers the Bluetooth devices nearby along with the list of already paired devices. My situation: I had two Bluetooth headsets turned on and they were not being detected after a successful Bluetooth scan! So I dig into the problem and somewhere found that the Bluetooth headset needs to be switched to pairing mode in case of being detected by android. To switch the headsets in pairing mode, I had to long-press the power button while turning them on. And yes, finally, the Bluetooth headsets are now detected by the scan from my application. My problem: I want my headsets will be detected automatically without switching them in pairing mode. Couldn’t find a way to detect all nearby Bluetooth devices which are turned on.

You can’t. That would violate the Bluetooth specification. If a device is not discoverable then you will not be able to see it (following standard BT and not some sniffing hack of course). Furthermore, if a device has actively disabled pairing then you can’t pair with it even if you can discover it. Bluetooth discovery and pairing are cooperative processes. If either side declines to participate then the operation cannot be completed.

Not necessarily I’ve to pair with the bluetooth device. I just need to discover them all. When my bluetooth headset is turned on, I think this is discoverable already. My android can’t detect it until I force it to pairing mode. That’s my problem actually. I want to discover them all without forcing them in pairing mode.

What you call «pairing mode» is more likely discoverable and pairable mode together. That’s how most devices work. That is, it isn’t discoverable just by turning on the device.

1 Answer 1

So, here’s all I found after reading blogs, threads, documentations, SO answers etc. regarding Android’s bluetooth discovery. Thought this might be useful to post my findings here.

So before someone starts reading, I want to clarify that, I could not find any way to detect a bluetooth device nearby which is turned on but not discoverable.

Detect all nearby Bluetooth devices

My primary target is to detect all nearby bluetooth devices. To do so, we have a BluetoothAdapter class in Android which has a startDiscovery function to scan for bluetooth devices nearby. Hence, this doesn’t serves my purpose, as the bluetooth devices need to be discoverable to be detected by a bluetooth scan by Android. What I want is to detect all Bluetooth devices nearby without forcing them to be discoverable. I started searching for a solution to achieve this goal.

Читайте также:  Подключение samsung компьютеру bluetooth

I started with studying Bluetooth protocols and found the underlying protocols used for bluetooth detection, connection and pairing. For Android, I found no API to discover/detect BT devices which are turned on but not in discoverable mode.

Bluetooth devices with class 0x00 are ignored

Digging into this detection problem without forcing the bluetooth devices to discoverable mode lead us to a point where we found Bluetooth device which advertises itself as class 0×00 is ignored automatically while running scan for nearby BT devices. This problem is stated in several places. Here I have listed some.

I tried to find a work-around of this problem and yes, I found one, though the documentation and reviews along with this work-around says, it doesn’t work for all kind of Android devices. Anyway, the alternate scan is the same as the default BT scan, but it does some additional works. It reads the Android log after a successful BT scan and check if there’s any BT device is skipped through out the operation. This is a simple hack described here . There’s a google group discussing about the same work-around here.

The work-around above doesn’t solve my problem either. Bluetooth headsets need to be discoverable for being detected by a BT scan. They are not skipped while Android is scanning nearby BT devices. They are simply not found.

Bluetooth Page Scan

However, I started searching for a solution again and found something interesting again! This is from another Stackoverflow answer which says, It is possible to know whether a bluetooth device is around, even if he is in an undiscoverable mode, by knowing his full MAC address in the first place. I’m quoting again from his answer for future reference,

The technique is to try a PAGE request, sending all the 6 bytes that are composing the seeked Bluetooth host MAC identifier. A PAGE request allows one to connect with a Bluetooth slave when knowing his BT ADDR. Devices that are in undiscoverable mode does not respond to inquiry scan (device discovery intent), but they do respond to page scan which is used by a device wanting to connect to an another previously known device.

I found hope and started searching for, how can we initiate a page scan in Android but failed this time too. Couldn’t find any kind of APIs to initiate page scan. From Android documentation of BluetoothAdapter class, I came to know that, when a BT scan starts,

This usually involves an inquiry scan of about 12 seconds, followed by a page scan of each new device to retrieve its Bluetooth name.

There is an indication of page scan in Android documentation, but, surprisingly, there is no other documentation regarding page scan anywhere. I put a Stackoverflow question for inquiry.

Can we «fool» android by appending a list of BTIDs to the «already paired» list?

No, I did not find any way to do so. I read about how Android’s bluetooth pairing works. Here is a nice flow diagram along with detailed reading manual. We were trying to use Android’s hidden APIs and could use some hidden APIs using Reflection. Then we started to look for hidden APIs which we might use to serve my purpose. But, unfortunately, we failed to find any hidden APIs to add a BT device in Android’s already paired list programatically.

Читайте также:  Пежо 308 магнитола есть ли блютуз

Here are some helpful links to check for bluetooth pairing, hidden APIs and how to invoke them via reflection for future reference.

So I could pair a BT device when it was in discoverable mode and was not in the paired list in Android. In my case, I used a bluetooth headset. It was turned on and put in discoverable mode. The BT Address (MAC address) of the headset was known. So I called the function createBond from my code using reflection and it worked perfectly. The device was added in the «already-paired» list of Android successfully. While roaming around for solutions to serve my purpose I found something interesting.

Interesting observation about already paired devices

I found that, android preserves a previously paired device in its memory even if I remove it from the already-paired list. Let us share a case study along with the findings here for a better understanding. In my case the headset was paired previously.

  1. Unpaired/forget the headset from Android
  2. Then turned the headset off.
  3. Then started scanning for bluetooth devices nearby
  4. Of course, the headset was not found
  5. But we went through the Android logs and found that, Android remembers the change of bonding state (paring state) of that headset.
  6. It scanned for the previously bonded headphone and reported remote device is down

Here is the log that printed along with the MAC address of the headset we paired before and then unpaired.

PREV_BOND_STATE = 11 // BOND_BONDING (BluetoothDevice.java) BOND_STATE = 10 // BOND_NONE REASON = 4 // UNBOND_REASON_REMOTE_DEVICE_DOWN 

Then again, I ran the same test, but this time we turned the bluetooth headset on (not discoverable). The headset was not found in this case too, but the interesting thing is, this time a different log was printed.

PREV_BOND_STATE = 11 // BOND_BONDING (BluetoothDevice.java) BOND_STATE = 10 // BOND_NONE REASON = 2 // UNBOND_REASON_AUTH_CANCELLED 

The REASON is changed and hence I can understand Android tried to connect with the bluetooth headset. The headset was not in discoverable mode, yet Android could find it and tried to connect with it as it was in paired list before.

This log was printed while a bluetooth scan was running with adding ACTION_BOND_STATE_CHANGED action with intent.addAction .

Can Android be used as beacon?

Yes, but in that case Android needs to advertise itself as a BLE too. This is what new in Android and not all devices support this functionality till now. Here is a list of devices which support Bluetooth LE advertisement capability. But, as Bluetooth LE advertisement has a very low power consumption along with a high performance, I think this will be the next big thing in Android.

Here are some helpful links for future research.

Helpful functions and libraries for bluetooth operations

Источник

Оцените статью
Adblock
detector