How to scan for available bluetooth devices in range in android?
I need to get a list of available bluetooth devices in the area using google android 2.1. Thing is, i don’t just need a list of those devices, i need some unique id for each device found and i need an indicator, how «good» the signal is received (like the «level» in android.wifi.ScanResult). How do i do that?
4 Answers 4
mBluetoothAdapter.startDiscovery(); mReceiver = new BroadcastReceiver() < public void onReceive(Context context, Intent intent) < String action = intent.getAction(); //Finding devices if (BluetoothDevice.ACTION_FOUND.equals(action)) < // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); // Add the name and address to an array adapter to show in a ListView mArrayAdapter.add(device.getName() + "\n" + device.getAddress()); >> >; IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mReceiver, filter);
@SaharMillis: What about it doesn’t work for you? It works fine, but your other device needs to be discoverable, not just with bluetooth on.
how does this work if there are multiple bluetooth devices found in the range. Does the receiver get triggered multiple times?
@Zapnologica the BroadcastReceiver gets notified once per device; therefore one has to keep them in an ArrayList field, or alike. while there are two? further actions available, beside the BluetoothDevice.ACTION_FOUND , of which one indicates the scan being complete.
Call method bluetoothScanning, context is required
void bluetoothScanning() < IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); context.registerReceiver(mReceiver, filter); final BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); mBluetoothAdapter.startDiscovery(); >// Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver mReceiver = new BroadcastReceiver() < public void onReceive(Context context, Intent intent) < String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) < // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address Log.i("Device Name: " , "device " + deviceName); Log.i("deviceHardwareAddress " , "hard" + deviceHardwareAddress); >> >;
Name: LE-Bose Revolve+ SoundLink deviceHardwareAddress: MAC .
@GregD this is my exact problem. it was working fine, but then it started to show only mac addresses and not names. can’t figure out why
This code uses BeaconManager, it continuously scans for new Bluetooth devices and returns a Beacons List object which you can use to get what ever information you need.
Make sure you import BeaconManager
private BeaconManager beaconManager; //In onCreate method beaconManager = BeaconManager.getInstanceForApplication(this); beaconManager.getBeaconParsers().add(new BeaconParser(). setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24")); //use these out of the onCreate method public void onScanStart(View view) < stopScanButton.setEnabled(true); scanningButton.setEnabled(false); beaconManager.bind(this); >@Override public void onBeaconServiceConnect() < beaconManager.removeAllRangeNotifiers(); beaconManager.addRangeNotifier(new RangeNotifier() < @Override public void didRangeBeaconsInRegion(Collectionbeacons, Region region) < for (Beacon b : beacons) < System.out.println(String.format("%s: %f: %d", b.getBluetoothName(), b.getDistance(), b.getRssi())); >); try < //Tells the BeaconService to start looking for beacons that match the passed. beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null)); >catch (RemoteException e) < Toast.makeText(this, e.toString(), Toast.LENGTH_LONG).show(); >>
Let me know if that works for you!
To able to discovery devices by bluetooth. Make sure you
- Enable bluetooth
- Allow required permissions for your application (some permission is runtime permission). You can check here https://developer.android.com/about/versions/12/features/bluetooth-permissions
AndroidManifest.xml
MainActivity
class MainActivity : AppCompatActivity() < private var bluetoothAdapter: BluetoothAdapter? = null private val bluetoothReceiver: BroadcastReceiver = object : BroadcastReceiver() < override fun onReceive(context: Context?, intent: Intent) < val action = intent.action Log.i("TAG", "onReceive $action") if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED == action) < Log.i("TAG", "Discovery finished, hide loading") >else if (BluetoothDevice.ACTION_FOUND == action) < val device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) Log.i("TAG", "Device Name: " + (device?.name ?: "")) Log.i("TAG", "Device Address:" + (device?.address ?: "")) > > > override fun onCreate(savedInstanceState: Bundle?) < . findViewById(R.id.button_start_discovery).setOnClickListener < if (bluetoothAdapter == null) < initBluetoothDiscovery() >startDiscovery() > > private fun initBluetoothDiscovery() < val bluetoothManager = getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager bluetoothAdapter = bluetoothManager.adapter val intentFilter = IntentFilter().apply < addAction(BluetoothDevice.ACTION_FOUND) addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED) >registerReceiver(bluetoothReceiver, intentFilter) > private fun startDiscovery() < if (bluetoothAdapter?.isDiscovering == true) < Log.i("TAG", "cancel start discovery") bluetoothAdapter?.cancelDiscovery() >Log.i("TAG", "start discovery, show loading") bluetoothAdapter?.startDiscovery() > override fun onDestroy() < super.onDestroy() bluetoothAdapter?.cancelDiscovery(); unregisterReceiver(bluetoothReceiver); >>
Find Bluetooth devices
Using the BluetoothAdapter , you can find remote Bluetooth devices either through device discovery or by querying the list of paired devices.
Make sure you have the appropriate Bluetooth permissions and set up your app for Bluetooth before attempting to find Bluetooth devices.
Device discovery is a scanning procedure that searches the local area for Bluetooth-enabled devices and requests some information about each one. This process is sometimes referred to as discovering, inquiring, or scanning. A nearby Bluetooth device responds to a discovery request only if it is currently accepting information requests by being discoverable. If a device is discoverable, it responds to the discovery request by sharing some information, such as the device’s name, its class, and its unique MAC address. Using this information, the device that is performing the discovery process can then choose to initiate a connection to the discovered device.
Because discoverable devices might reveal information about the user’s location, the device discovery process requires location access. If your app is being used on a device that runs Android 8.0 (API level 26) or higher, consider using the Companion Device Manager API instead. This API performs device discovery on your app’s behalf, so your app doesn’t need to request location permissions.
Once a connection is made with a remote device for the first time, a pairing request is automatically presented to the user. When a device is paired, the basic information about that device—such as the device’s name, class, and MAC address—is saved and can be read using the Bluetooth APIs. Using the known MAC address for a remote device, a connection can be initiated with it at any time without performing discovery, assuming the device is still within range.
Note that there is a difference between being paired and being connected:
- To be paired means that two devices are aware of each other’s existence, have a shared link-key that can be used for authentication, and are capable of establishing an encrypted connection with each other.
- To be connected means that the devices currently share an RFCOMM channel and are able to transmit data with each other. The current Bluetooth APIs require devices to be paired before an RFCOMM connection can be established. Pairing is automatically performed when you initiate an encrypted connection with the Bluetooth APIs.
The following sections describe how to find devices that have been paired and how to discover new devices using device discovery.
Note: Android-powered devices are not discoverable by default. A user can make the device discoverable for a limited time through the system settings, or an app can request that the user enable discoverability without leaving the app. For more information, see the enable discoverability section on this page.
Query paired devices
Before performing device discovery, it’s worth querying the set of paired devices to see if the desired device is already known. To do so, call getBondedDevices() . This returns a set of BluetoothDevice objects representing paired devices. For example, you can query all paired devices and get the name and MAC address of each device, as the following code snippet demonstrates:
Kotlin
val pairedDevices: Set? = bluetoothAdapter?.bondedDevices pairedDevices?.forEach < device ->val deviceName = device.name val deviceHardwareAddress = device.address // MAC address >
Java
Set pairedDevices = bluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) < // There are paired devices. Get the name and address of each paired device. for (BluetoothDevice device : pairedDevices) < String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address >>
To initiate a connection with a Bluetooth device, all that’s needed from the associated BluetoothDevice object is the MAC address, which you retrieve by calling getAddress() . You can learn more about creating a connection in Connect Bluetooth devices.
Discover devices
To start discovering devices, call startDiscovery() . The process is asynchronous and returns a boolean value indicating whether discovery has successfully started. The discovery process usually involves an inquiry scan of about 12 seconds, followed by a page scan of each device found to retrieve its Bluetooth name.
To receive information about each device discovered, your app must register a BroadcastReceiver for the ACTION_FOUND intent. The system broadcasts this intent for each device. The intent contains the extra fields EXTRA_DEVICE and EXTRA_CLASS , which in turn contain a BluetoothDevice and a BluetoothClass , respectively. The following code snippet shows how you can register to handle the broadcast when devices are discovered:
Kotlin
override fun onCreate(savedInstanceState: Bundle?) < . // Register for broadcasts when a device is discovered. val filter = IntentFilter(BluetoothDevice.ACTION_FOUND) registerReceiver(receiver, filter) >// Create a BroadcastReceiver for ACTION_FOUND. private val receiver = object : BroadcastReceiver() < override fun onReceive(context: Context, intent: Intent) < val action: String = intent.action when(action) < BluetoothDevice.ACTION_FOUND -> < // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. val device: BluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE) val deviceName = device.name val deviceHardwareAddress = device.address // MAC address >> > > override fun onDestroy() < super.onDestroy() . // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver) >
Java
@Override protected void onCreate(Bundle savedInstanceState) < . // Register for broadcasts when a device is discovered. IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(receiver, filter); >// Create a BroadcastReceiver for ACTION_FOUND. private final BroadcastReceiver receiver = new BroadcastReceiver() < public void onReceive(Context context, Intent intent) < String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) < // Discovery has found a device. Get the BluetoothDevice // object and its info from the Intent. BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); String deviceName = device.getName(); String deviceHardwareAddress = device.getAddress(); // MAC address >> >; @Override protected void onDestroy() < super.onDestroy(); . // Don't forget to unregister the ACTION_FOUND receiver. unregisterReceiver(receiver); >
To initiate a connection with a Bluetooth device, you call getAddress() on the BluetoothDevice to retrieve the associated MAC address.
Caution: Performing device discovery consumes a lot of the Bluetooth adapter’s resources. After you have found a device to connect to, be certain that you stop discovery with cancelDiscovery() before attempting a connection. Also, you shouldn’t perform discovery while connected to a device because the discovery process significantly reduces the bandwidth available for any existing connections.
Enable discoverability
To make the local device discoverable to other devices, call startActivityForResult(Intent, int) with the ACTION_REQUEST_DISCOVERABLE intent. This issues a request to enable the system’s discoverable mode without having to navigate to the Settings app, which would stop your own app. By default, the device becomes discoverable for two minutes. You can define a different duration, up to one hour, by adding the EXTRA_DISCOVERABLE_DURATION extra.
Caution: If you set the EXTRA_DISCOVERABLE_DURATION extra’s value to 0, the device is always discoverable. This configuration is insecure and therefore highly discouraged.
The following code snippet sets the device to be discoverable for five minutes:
Kotlin
val requestCode = 1; val discoverableIntent: Intent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).apply < putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300) >startActivityForResult(discoverableIntent, requestCode)
Java
int requestCode = 1; Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivityForResult(discoverableIntent, requestCode);
Figure 2: The enabling discoverability dialog.
A dialog is displayed, requesting the user’s permission to make the device discoverable, as shown in figure 2. If the user responds «Allow,» then the device becomes discoverable for the specified amount of time. Your activity then receives a call to the onActivityResult() callback, with the result code equal to the duration that the device is discoverable. If the user responded «Deny», or if an error occurred, the result code is RESULT_CANCELED .
Note: If Bluetooth has not been enabled on the device, then making the device discoverable automatically enables Bluetooth.
The device silently remains in discoverable mode for the allotted time. To be notified when the discoverable mode has changed, register a BroadcastReceiver for the ACTION_SCAN_MODE_CHANGED intent. This intent contains the extra fields EXTRA_SCAN_MODE and EXTRA_PREVIOUS_SCAN_MODE , which provide the new and old scan mode, respectively. Possible values for each extra are as follows:
SCAN_MODE_CONNECTABLE_DISCOVERABLE The device is in discoverable mode. SCAN_MODE_CONNECTABLE The device isn’t in discoverable mode but can still receive connections. SCAN_MODE_NONE The device isn’t in discoverable mode and cannot receive connections.
If you are initiating the connection to a remote device, you don’t need to enable device discoverability. Enabling discoverability is only necessary when you want your app to host a server socket that accepts incoming connections, as remote devices must be able to discover other devices before initiating connections to those other devices.
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.