Is there anyway to get the connected devices list from support profiles (HDD,Spp and audio). The requirement is like my device will support HDD,SPP and Audio, so i have to filter the devices which supports all these profiles. Is there anyway to filter the devices?
How to get the connected device list from a specific bluetooth profile
5k Views Asked by Sainath At
2
There are 2 best solutions below
1
On
extending @Mack answer, I was able to create a composable that return list of currently connected devices, with a refresh button:
here's the complete code:
package com.example.audio_output_selector
import android.Manifest
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothProfile
import android.content.Context
import android.content.pm.PackageManager
import android.util.Log
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext
import androidx.core.app.ActivityCompat
@Composable
fun getConnectedBluetoothDevices(): List<BluetoothDevice> {
val context = LocalContext.current
val bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
val bluetoothAdapter: BluetoothAdapter = bluetoothManager.getAdapter()
if (bluetoothAdapter.isEnabled == false) {
Log.i("MainActivity", "Bluetooth is not enabled")
}
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.BLUETOOTH_CONNECT
) != PackageManager.PERMISSION_GRANTED
) {
Log.i("MainActivity", "Should Requesting Bluetooth permission")
return emptyList()
}
var connectedBluetoothDevices by remember {
mutableStateOf(
ConnectedBluetoothDevices(
emptyList(), emptyList(), emptyList(), emptyList(), emptyList()
)
)
}
var currentBluetoothProfile: BluetoothProfile? = null
var isRefreshing by remember { mutableStateOf(false) }
LaunchedEffect(bluetoothAdapter, currentBluetoothProfile, isRefreshing) {
if (isRefreshing) {
bluetoothAdapter.getProfileProxy(context, object : BluetoothProfile.ServiceListener {
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
currentBluetoothProfile = proxy
connectedBluetoothDevices = handleBluetoothService(profile, proxy)
}
override fun onServiceDisconnected(profile: Int) {
if (profile == BluetoothProfile.A2DP) {
Log.i("MainActivity", "A2DP devices disconnected")
}
}
}, BluetoothProfile.A2DP)
}
isRefreshing = false
}
// bluetoothAdapter.getProfileConnectionState(BluetoothProfile.A2DP) == BluetoothProfile.STATE_CONNECTED
bluetoothAdapter.getProfileProxy(context, object : BluetoothProfile.ServiceListener {
override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) {
connectedBluetoothDevices = handleBluetoothService(profile, proxy)
}
override fun onServiceDisconnected(profile: Int) {
if (profile == BluetoothProfile.A2DP) {
Log.i("MainActivity", "A2DP devices disconnected")
}
}
}, BluetoothProfile.A2DP)
Button(onClick = { isRefreshing = true }) {
Text("Refresh BT")
}
// currently we are relating only on A2DP devices
// but we could use them later with a little change if needed
return connectedBluetoothDevices.a2dpDevices
}
fun handleBluetoothService(profile: Int, proxy: BluetoothProfile): ConnectedBluetoothDevices {
val states = intArrayOf(
BluetoothProfile.STATE_CONNECTED,
// BluetoothProfile.STATE_CONNECTING,
// BluetoothProfile.STATE_DISCONNECTED,
// BluetoothProfile.STATE_DISCONNECTING
)
val ad2dpDevices = mutableListOf<BluetoothDevice>()
val gattDevices = mutableListOf<BluetoothDevice>()
val gattServerDevices = mutableListOf<BluetoothDevice>()
val headsetDevices = mutableListOf<BluetoothDevice>()
val sapDevices = mutableListOf<BluetoothDevice>()
when (profile) {
BluetoothProfile.A2DP -> ad2dpDevices.addAll(proxy.getDevicesMatchingConnectionStates(states))
BluetoothProfile.GATT -> gattDevices.addAll(proxy.getDevicesMatchingConnectionStates(states))
BluetoothProfile.GATT_SERVER -> gattServerDevices.addAll(
proxy.getDevicesMatchingConnectionStates(
states
)
)
BluetoothProfile.HEADSET -> headsetDevices.addAll(
proxy.getDevicesMatchingConnectionStates(
states
)
)
BluetoothProfile.SAP -> sapDevices.addAll(proxy.getDevicesMatchingConnectionStates(states))
}
return ConnectedBluetoothDevices(
ad2dpDevices,
gattDevices,
gattServerDevices,
headsetDevices,
sapDevices
)
// to get the connected devices of selected profile
// if (profile == BluetoothProfile.A2DP) {
// val a2dp = proxy as BluetoothProfile
// val devices = a2dp.connectedDevices
// Log.i("MainActivity", "A2DP devices: $devices")
// }
}
data class ConnectedBluetoothDevices(
val a2dpDevices: List<BluetoothDevice>,
val gattDevices: List<BluetoothDevice>,
val gattServerDevices: List<BluetoothDevice>,
val headsetDevices: List<BluetoothDevice>,
val sapDevices: List<BluetoothDevice>,
)
Yes that is possible but your Android application must target SDK 11 or later (Android 3.0.X).
The solution to your question is that you have to query all BluetoothDevices known by your Android device. By known I mean all paired connected or unconnected devices and unpaired connected devices.
We will filter out unconnected devices later since you only want currently connected devices.
BluetoothAdapter: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 AndroidFourth, you create a
BluetoothProfile.ServiceListenerwhich contains two callbacks triggered when a service is connected and disconnected :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 :