list connected bluetooth devices?
This works, but it’s more like polling. Is there a way to have a nice callback of when the list changes? Using BluetoothDevice.ACTION_ACL_CONNECTED, it’s not quite the same as it’s about pairing/bonding, and it’s not reliable either (doesn’t say when it finished bonding) .
As of API 14 (Ice Cream), Android has a some new BluetoothAdapter methods including:
public int getProfileConnectionState (int profile)
where profile is one of HEALTH, HEADSET, A2DP
Check response, if it’s not STATE_DISCONNECTED you know you have a live connection.
Here is code example that will work on any API device:
BluetoothAdapter mAdapter; /** * Check if a headset type device is currently connected. * * Always returns false prior to API 14 * * @return true if connected */ public boolean isVoiceConnected() < boolean retval = false; try < Method method = mAdapter.getClass().getMethod("getProfileConnectionState", int.class); // retval = mAdapter.getProfileConnectionState(android.bluetooth.BluetoothProfile.HEADSET) != android.bluetooth.BluetoothProfile.STATE_DISCONNECTED; retval = (Integer)method.invoke(mAdapter, 1) != 0; >catch (Exception exc) < // nothing to do >return retval; >
final BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
if (btAdapter != null && btAdapter.isEnabled()) // null means no Bluetooth!
If the Bluetooth is not turned out you can either use btAdapter.enable() which is not recommended in the documentation or ask the user to do it : Programmatically enabling bluetooth on Android
- Fourth, you create a BluetoothProfile.ServiceListener which contains two callbacks triggered when a service is connected and disconnected :
final BluetoothProfile.ServiceListener listener = new BluetoothProfile.ServiceListener() < @Override public void onServiceConnected(int profile, BluetoothProfile proxy) < >@Override public void onServiceDisconnected(int profile) < >>;
Now since you have to repeat the querying process for all available Bluetooth Profiles in the Android SDK (A2Dp, GATT, GATT_SERVER, Handset, Health, SAP) you should proceed as follow :
In onServiceConnected , place a condition that check what is the current profile so that we add the found devices into the correct collection and we use : proxy.getDevicesMatchingConnectionStates(states) to filter out unconnected devices:
And finally, the last thing to do is start the querying process :
btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.A2DP); btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.GATT); // NOTE ! Requires SDK 18 ! btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.GATT_SERVER); // NOTE ! Requires SDK 18 ! btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.HEADSET); btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.HEALTH); // NOTE ! Requires SDK 14 ! btAdapter.getProfileProxy(yourContext, listener, BluetoothProfile.SAP); // NOTE ! Requires SDK 23 !
Android bluetooth get connected devices
How can I get a list of all connected bluetooth devices for Android regardless of profile? Alternatively, I see that you can get all connected devices for a specific profile via BluetoothManager.getConnectedDevices. And I guess I could see which devices are connected by listening for connections/disconnections via ACTION_ACL_CONNECTED/ACTION_ACL_DISCONNECTED. seems error prone. But I’m wondering if there’s a simpler way to get the list of all connected bluetooth devices.
you’re right in that just listening to acl connected / disconnect is problematic because it can occur while your app is not running or listening for the broadcasts
3 Answers 3
To see a complete list, this is a 2-step operation:
To get a list of, and iterate, the currently paired devices:
Set pairedDevices = BluetoothAdapter.getDefaultAdapter().getBondedDevices(); if (pairedDevices.size() > 0) < for (BluetoothDevice d: pairedDevices) < String deviceName = d.getName(); String macAddress = d.getAddress(); Log.i(LOGTAG, "paired device: " + deviceName + " at " + macAddress); // do what you need/want this these list items >>
Discovery is a little bit more of a complex operation. To do this, you’ll need to tell the BluetoothAdapter to start scanning/discovering. As it finds things, it sends out Intents that you’ll need to receive with a BroadcastReceiver.
First, we’ll set up the receiver:
private void setupBluetoothReceiver() < BroadcastRecevier btReceiver = new BroadcastReciver() < @Override public void onReceive(Context context, Intent intent) < handleBtEvent(context, intent); >>; IntentFilter eventFilter = new IntentFilter(BluetoothDevice.ACTION_FOUND); // this is not strictly necessary, but you may wish // to know when the discovery cycle is done as well eventFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); myContext.registerReceiver(btReceiver, eventFilter); > private void handleBtEvent(Context context, Intent intent) < String action = intent.getAction(); Log.d(LOGTAG, "action received: " + action); if (BluetoothDevice.ACTION_FOUND.equals(action)) < BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Log.i(LOGTAG, "found device: " + device.getName()); >else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) < Log.d(LOGTAG, "discovery complete"); >>
Now all that is left is to tell the BluetoothAdapter to start scanning:
BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); // if already scanning . cancel if (btAdapter.isDiscovering()) < btAdapter.cancelDiscovery(); >btAdapter.startDiscovery();
Определение подключенности Bluetooth под Android
Итак, передо мной возникла задача — программно определить подключенно ли какое-то из сопряженных устройств в данный момент к моему телефону посредством Bluetooth. Долго и безуспешно выискивал в сети какое-либо готовое решение по этому поводу, однако удалость найти лишь только указание на то, что есть возможность отслеживания события подключения по Bluetooth. Но ведь программа может быть запущена уже после события, следовательно, это мне не подошло.
Собственно после этого (и листания разделов посвященных Bluetooth в официальной документации Android) и пришла мысль попробовать соединяться с каждым сопряженным устройством, а далее смотреть на успех операции: если успешно — значит устройство в зоне покрытия и подключено. Затея оказалась успешной.
Однако, на пути к ее реализации ожидал еще подвох:
BluetoothSocket bs = device.createRfcommSocketToServiceRecord(MY_UUID); bs.connect();
Этот код создания клиентского подключения никак не хотел выполняться, всегда возвращая ошибку «Service discovery failed». Снова поиск, чтение и выявление факта массы жалоб на такую же проблему. Советы же по решению данной проблемы сводились к одному: предложению различных значений для MY_UUID. Я перепробовал N-ное количество различных UUID из этих советов, но ни с одним соединение между Windows Mobile и Android получить не удалось. Интересный момент: при попытке соединения у «спящего» WM-коммуникатора загорался дисплей. То есть соединение все же инициализируется, но по каким-то причинам не устанавливается. Решение нашлось у соотечественника:
Method m = device.getClass().getMethod("createRfcommSocket",new Class[] < int.class >); socket = (BluetoothSocket)m.invoke(device, Integer.valueOf(1));
И данный способ действительно работает безотказно.
Общий же код проверки Bluetooth’а на подключенность выглядит примерно так:
boolean checkConnected() < BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); boolean connected = false; for (BluetoothDevice device : mBluetoothAdapter.getBondedDevices()) < try < try < Method m = device.getClass().getMethod("createRfcommSocket",new Class[] < int.class >); try < BluetoothSocket bs = (BluetoothSocket) m.invoke(device,Integer.valueOf(1)); bs.connect(); connected = true; Log.d(TAG, device.getName() + " - connected"); break; >catch (IOException e) < Log.e(TAG, "IOException: "+e.getLocalizedMessage()); Log.d(TAG, device.getName() + " - not connected"); >> catch (IllegalArgumentException e) < Log.e(TAG, "IllegalArgumentException: "+e.getLocalizedMessage()); >catch (IllegalAccessException e) < Log.e(TAG, "IllegalAccessException: "+e.getLocalizedMessage()); >catch (InvocationTargetException e) < Log.e(TAG, "InvocationTargetException: "+e.getLocalizedMessage()); >> catch (SecurityException e) < Log.e(TAG, "SecurityException: "+e.getLocalizedMessage()); >catch (NoSuchMethodException e) < Log.e(TAG, "NoSuchMethodException: "+e.getLocalizedMessage()); >> return connected; >
Конечно, работает код не молниеносно. Но тем не менее, код работает и функцию свою выполняет, тем более, что других решений мне найти не удалось. В связи с тем, что опыт работы в Андроид у меня не такой большой, возможно, в коде есть что еще подправить или существует какое-то другое решение. Но это уже подскажут знатоки.
Currently connected bluetooth device android
I can able to see two states in Bluetooth device in Android. 1. Paired 2. Connected. —
I am trying to get currently connected Bluetooth device in Android. But I am getting only paired device list from adapter.getBondedDevices(); I need currently connected device. How can i get this. Please someone help me to achieve this. Thanks in advance.
The question is not entirely clear for me. What exactly do you do? You create Connected btlDevice when doing btlDevice.CreateRfcommSocketToServiceRecord (MY_UUID); Alternatively the system use last connected btlDevice. Please more detail what you doing.
4 Answers 4
That’s pretty straight forward. Android BluetoothManager have method of
BluetoothManager manager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE); List connected = manager.getConnectedDevices(GATT); Log.i("Connected Devices: ", connected.size()+"");
If you want more details about connected devices then you can use the above list method put it into for loop and get the inner details of each Bluetooth device which are connected.
12-20 18:04:09.679 14933-14933/com.salman.dleague.blescanning I/Connected Devices:: 2
Isn’t this for BLE? I tried connect my smartphone for media audio. Both GATT and GATT_SERVER return 0 size
@GNK. Sorry no. I ened up with no need to work on this. For viewing BT devices from Android Setting UI, maybe you can checkout on Setting app source code. I have seen this but it is quite complex..Also the comments under the question (for Android 10) may help
Add this in your manifest file
public class MyBluetoothReceiver extends BroadcastReceiver < @Override public void onReceive(Context context, Intent intent) < String action = intent.getAction(); // When discovery finds a device if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) < BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); Toast.makeText(getApplicationContext(),device.getName() +" CONNECTED",Toast.LENGTH_LONG).show(); >else if (BluetoothAdapter.ACL_DISCONNECTED .equals(action)) < >> >
This will only give notification when the device gets Connected. What about the device is already connected and then you launch your app.? How to get the connected devices?
I previously was using a method to get connected devices by the «headset» profile, but I ran in to an issue with a Samsung Galaxy Watch 4 where it comes up as a «headset» device even though it does not support audio. This is problematic when just asking if a «headset» is connected, because you may inadvertently try to send audio to that device even though it doesn’t support it.
To get all of the connected devices you need to use a ServiceListener . The good news is that the service listener will always list the devices connected, and you can use that to inspect if they support audio or not. To simplify things further, I used a callback flow like follows:
@OptIn(ExperimentalCoroutinesApi::class) internal fun headsetConnectedAndSupportsAudio() = callbackFlow < val serviceListener = object : BluetoothProfile.ServiceListener < override fun onServiceDisconnected(profile: Int) = Unit // no op override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) < var connected = false var supportsAudio = false // check for a device that supports audio and is connected in our connected bluetooth devices. for (device in proxy.connectedDevices) < connected = proxy.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED supportsAudio = device.bluetoothClass.hasService(BluetoothClass.Service.AUDIO) Timber.d("Bluetooth Device - $isConnected: $connected supportsAudio: $supportsAudio") // we have found a connected device that supports audio, stop iterating and emit a success if (connected && supportsAudio) < break >> trySend(connected && supportsAudio) .onClosed < throwable ->Timber.e(throwable) > .isSuccess getBluetoothAdapter().closeProfileProxy(profile, proxy) close() > > // register our service listener to receive headset connection updates getBluetoothAdapter().getProfileProxy( context, serviceListener, BluetoothProfile.HEADSET ) awaitClose < channel.close() >>
And then to use the callback flow you do something like:
mainScope.launch < headsetConnectedAndSupportsAudio().cancellable().collect < btAudioSourceConnected ->if (btAudioSourceConnected) < Timber.d("Bluetooth headset connected + supports audio" >else < Timber.d("No Bluetooth headset connected that supports audio") >>
How to get bluetooth connected devices using BluetoothHeadset API
I want to get list of bluetooth connected devices. not just paired devices. I found BluetoothHeadset API in API level 11 which provides method getConnectedDevices() to get list of connected bluetooth devices. How to get list of bluetooth connected devices using this API ?
2 Answers 2
Finally got the solution. Below are a few code snippets for getting Bluetooth audio connected devices using BluetoothHeadset API.
BluetoothHeadset mBluetoothHeadset; // Get the default adapter BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // Establish connection to the proxy. mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
// Define Service Listener of BluetoothProfile private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() < public void onServiceConnected(int profile, BluetoothProfile proxy) < if (profile == BluetoothProfile.HEADSET) < mBluetoothHeadset = (BluetoothHeadset) proxy; >> public void onServiceDisconnected(int profile) < if (profile == BluetoothProfile.HEADSET) < mBluetoothHeadset = null; >> >;
// call functions on mBluetoothHeadset to check if Bluetooth SCO audio is connected. List devices = mBluetoothHeadset.getConnectedDevices(); for ( final BluetoothDevice dev : devices )
// finally Close proxy connection after use. mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
I’m using a similar solution but I’m seeing E/BluetoothA2dp﹕ Could not bind to Bluetooth A2DP Service with Intent < act=android.bluetooth.IBluetoothA2dp cmp=com.android.bluetooth/.a2dp.A2dpService >when I try to connect after exiting my app via the back button. I’m sure it must be something to do with not cleaning up properly, but since I’m taking care to call closeProfileProxy I’m not sure what it could be. Is this something you’ve seen?
First of all you need to define Permission in Androindmanifest.xml
Search Connected Devices Activity,
private static BluetoothAdapter mBtAdapter; private final static int REQUEST_ENABLE_BT = 1; // Register for broadcasts when a device is discovered IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(mReceiver, filter); // Register for broadcasts when discovery has finished filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(mReceiver, filter); filter = new IntentFilter( BluetoothAdapter.ACTION_DISCOVERY_STARTED ); this.registerReceiver( mReceiver, filter );
private final BroadcastReceiver mReceiver = new BroadcastReceiver() < @Override public void onReceive(Context context, Intent intent) < try < String action = intent.getAction(); // When discovery finds a device if ( BluetoothDevice.ACTION_FOUND.equals(action) ) < // Get the BluetoothDevice object from the Intent BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); >> catch ( Exception e ) < logger.info( DateFormat.format( ConstantCodes.dateFormat ,new java.util.Date()).toString(),"Broadcast Error : " + e.toString(), ConstantCodes.SEARCH_ACTIVITY ); System.out.println ( "Broadcast Error : " + e.toString() ); >> >;