How can I programmatically tell if a Bluetooth device is connected?
Solution 1
Add the Bluetooth permission to your AndroidManifest,
<uses-permission android:name="android.permission.BLUETOOTH" />
Then use intent filters to listen to the ACTION_ACL_CONNECTED
, ACTION_ACL_DISCONNECT_REQUESTED
, and ACTION_ACL_DISCONNECTED
broadcasts:
public void onCreate() {
...
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(mReceiver, filter);
}
//The BroadcastReceiver that listens for bluetooth broadcasts
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
... //Device found
}
else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
... //Device is now connected
}
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) {
... //Done searching
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED.equals(action)) {
... //Device is about to disconnect
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
... //Device has disconnected
}
}
};
A few notes:
- There is no way to retrieve a list of connected devices at application startup. The Bluetooth API does not allow you to query, instead it allows you to listen to changes.
- A hoaky workaround to the above problem would be to retrieve the list of all known/paired devices... then trying to connect to each one (to determine if you're connected).
- Alternatively, you could have a background service watch the Bluetooth API and write the device states to disk for your application to use at a later date.
Solution 2
In my use case I only wanted to see if a Bluetooth headset is connected for a VoIP app. The following solution worked for me.
Kotlin:
fun isBluetoothHeadsetConnected(): Boolean {
val mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
return (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled
&& mBluetoothAdapter.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothHeadset.STATE_CONNECTED)
}
Java:
public static boolean isBluetoothHeadsetConnected() {
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
return mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()
&& mBluetoothAdapter.getProfileConnectionState(BluetoothHeadset.HEADSET) == BluetoothHeadset.STATE_CONNECTED;
}
Of course you'll need the Bluetooth permission:
<uses-permission android:name="android.permission.BLUETOOTH" />
Solution 3
There is an isConnected function in the BluetoothDevice system API in https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/bluetooth/BluetoothDevice.java.
If you want to know if a bounded (paired) device is currently connected or not, the following function works fine for me:
public static boolean isConnected(BluetoothDevice device) {
try {
Method m = device.getClass().getMethod("isConnected", (Class[]) null);
boolean connected = (boolean) m.invoke(device, (Object[]) null);
return connected;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}
Solution 4
For some reason, BluetoothAdapter.ACTION_ACL_CONNECTED could not be resolved by Android Studio. Perhaps it was deprecated in Android 4.2.2?
Here is a modification of Skylarsutton's code (Big thanks to Skylarsutton for his answer.) . The registration code is the same; the receiver code differs slightly. I use this in a service which updates a Bluetooth-connected flag that other parts of the app reference.
public void onCreate() {
//...
IntentFilter filter = new IntentFilter();
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
this.registerReceiver(BTReceiver, filter);
}
//The BroadcastReceiver that listens for bluetooth broadcasts
private final BroadcastReceiver BTReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
//Do something if connected
Toast.makeText(getApplicationContext(), "BT Connected", Toast.LENGTH_SHORT).show();
}
else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
//Do something if disconnected
Toast.makeText(getApplicationContext(), "BT Disconnected", Toast.LENGTH_SHORT).show();
}
//else if...
}
};
Solution 5
This code is for the headset profiles, and probably it will work for other profiles too.
First you need to provide a profile listener (Kotlin code):
private val mProfileListener = object : BluetoothProfile.ServiceListener {
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
if (profile == BluetoothProfile.HEADSET)
mBluetoothHeadset = proxy as BluetoothHeadset
}
override fun onServiceDisconnected(profile: Int) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null
}
}
}
Then while checking Bluetooth:
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET)
if (!mBluetoothAdapter.isEnabled) {
return Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
}
It takes a bit of time until onSeviceConnected is called. After that you may get the list of the connected headset devices from:
mBluetoothHeadset!!.connectedDevices
dchappelle
Updated on July 08, 2022Comments
-
dchappelle almost 2 years
I understand how to get a list of paired devices, but how can I tell if they are connected?
It must be possible since I see them listed in my phone's Bluetooth device list and it states their connection status.
-
dchappelle over 13 yearsThis is good to as long as my application is running but how can I get a current list?
-
Skylar Sutton over 13 yearsHow do you plan on executing code without your application "running"? If you mean you need to access this from something other than an Activity... go google Android Services, build one of those to listen to the broadcasts, and persist it to a list.
-
dchappelle over 13 yearsI can listen for the intents BUT how can I get the initial list of connected Bluetooth devices? If any are already connected by the time my Activity or Service is started I won't know. I would imagine (hope) this data is available somewhere? I wouldn't want to have to create a service (that runs constantly as long as the phone is turned on) just to listen for these intents.
-
Skylar Sutton over 13 yearsThere is no way to retrieve the list of connected devices at application startup. The Bluetooth API will only let you listen to connection changes. So yes, the only way to do it is create a long running service and add/remove to a public list. It's a big complaint by a lot of developers. Depending on your performance needs you could retrieve the list of paired devices and try to connect to each one. If it fails, it's not available. Word of warning though: .connect() is a blocking operation.
-
dchappelle over 13 yearsI can try and connect to any paired devices as you mentioned but how do I know the UUID?
-
dchappelle over 13 yearsI've tried connecting to my bluetooth headset (paired and connected to the phone's audio but I get IOException: Service Discovery. I'm using UUID.fromString("00001101-0000-1000-8000-00805F9B34FB" ?
-
JPM about 13 yearsOnly thing was in my case the constants ACTION_ACL_CONNECTED and a few others were in BluetoothDevice not BluetoothAdapter. Otherwise this works great!
-
AgentKnopf over 12 years@skylarsutton +1 Thanks a bunch for this answer, helped me getting started on bluetooth
-
RobLabs almost 11 yearsyour code is correct; it wasn't deprecated in 4.2.2. The BluetoothAdapter class doesn't contain, ACTION_ACL_CONNECTED. That string is in the BluetoothDevice class.
-
pmont almost 11 yearsThanks for clarifying that!
-
esme_louise over 9 yearsAdding onto what @JPM said in his comment, both
ACTION_ACL_DISCONNECT_REQUESTED
andACTION_ACL_DISCONNECTED
are found in theBluetoothDevice
class notBluetoothAdapter
. -
Alexander Gorelik about 9 yearsI wrote a code that lets you detect if Bluetooth mouse or keyboard device connected on startup without using broadcast.If someone need it i can add it to gitHub.
-
DavidBalas almost 9 yearsHappens only when popup for pairing appears and not when pairing completed. Any other way?
-
sud007 almost 7 yearsThis is the one I was seeking for. Just to check upon launch that the Bluetooth is connected or not. Thanks it worked!
-
connorbode over 4 yearsThere is a way to get connected devices at startup, using BluetoothManager.getConnectedDevices, then checking BluetoothManager.getConnectionState for the devices you find.
-
Gumby The Green about 4 yearsHave you seen this give a different result from just checking whether
bluetoothManager.getConnectionState(device, BluetoothProfile.GATT) == BluetoothProfile.STATE_CONNECTED
? -
Gumby The Green about 4 yearsFrom what I can tell, they do give the same result. Note that for Kotlin users, those first two lines are just
val m: Method = device.javaClass.getMethod("isConnected")
andval connected = m.invoke(device)
. -
Takeya almost 4 yearsThank you, exactly what I needed! This is the kotlin equivalent for this method:
fun isConnected(device: BluetoothDevice): Boolean { return try { val m: Method = device.javaClass.getMethod( "isConnected" ) m.invoke(device) as Boolean } catch (e: Exception) { throw IllegalStateException(e) } }
-
neo over 2 yearsit's a good answer. thanks!
-
Juha over 2 yearsThis solution worked until I upgraded Android Studio to version 2021.1.1. Now
getProfileConnectionState(BluetoothHeadset.HEADSET)
call shows error "Call requires permission which may be rejected by user: code should explicitly check to see if permission is available (with checkPermission) or explicitly handle a potential SecurityException". The permission that is required isManifest.permission.BLUETOOTH_CONNECT
. -
notmystyle over 2 yearsI'm seeing an issue where a Samsung Galaxy Watch4 shows up as a headset with this call even though
device.bluetoothClass.hasService(BluetoothClass.Service.AUDIO)=false
. I'm trying to figure out how to determine if there are any connected device that supports audio, but theisConnected
call is SystemApi only. Currently I can see all bonded devices but can't tell if they are connected or not - and so I can't determine if a headset is really connected or just the watch (i.e. i have headphones that are not connected). Does anyone have a solution for this? -
Peterdk about 2 yearsI used this, for A2DP, but it also gets called when there are no devices connected and only bluetooth is active, and when you connect the device, without disabling bluetooth system setting, then you don't get a new event.
-
Hoo about 2 years@AlexanderGorelik yes, I need it
-
Prajwal Waingankar about 2 yearsDONT FORGET to UNREGISTER your RECEIVER in ONDESTROY().