Android端程序化获取已连接蓝牙耳机列表并切换音频输出
Android 多蓝牙耳机连接状态获取与音频输出切换方案
一、获取已连接的蓝牙耳机/耳塞列表
要筛选出仅已连接的蓝牙耳机设备,需结合BluetoothManager和蓝牙Profile(A2DP、HFP)获取设备,再通过BluetoothClass过滤设备类型:
权限配置
在AndroidManifest.xml中添加对应权限(根据系统版本适配):<!-- Android 12+ --> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android 11及以下 --> <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />获取已连接设备
通过BluetoothProfile.ServiceListener监听A2DP或HFP Profile的连接状态,获取所有已连接的设备:private val bluetoothManager = getSystemService(BLUETOOTH_SERVICE) as BluetoothManager private var a2dpProfile: BluetoothA2dp? = null // 初始化A2DP Profile监听 bluetoothManager.adapter.getProfileProxy(this, object : BluetoothProfile.ServiceListener { override fun onServiceConnected(profile: Int, proxy: BluetoothProfile) { if (profile == BluetoothProfile.A2DP) { a2dpProfile = proxy as BluetoothA2dp // 获取已连接的A2DP设备 val connectedDevices = a2dpProfile?.connectedDevices ?: emptyList() // 筛选蓝牙耳机/耳塞 val bluetoothHeadsets = connectedDevices.filter { device -> val bluetoothClass = device.bluetoothClass // 判断是否为音频设备(耳机/耳塞) bluetoothClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES || bluetoothClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET || bluetoothClass.deviceClass == BluetoothClass.Device.AUDIO_VIDEO_EARPHONES } // 此时bluetoothHeadsets即为目标列表,可用于UI展示 } } override fun onServiceDisconnected(profile: Int) { if (profile == BluetoothProfile.A2DP) { a2dpProfile = null } } }, BluetoothProfile.A2DP)注:若需兼容HFP设备(通话耳机),可同时监听
BluetoothProfile.HEADSETProfile,合并去重设备列表。
二、程序化切换音频输出设备
针对多设备切换需求,需根据Android版本使用对应API:
1. Android 11(API 30)及以上版本
使用AudioManager.setPreferredDevice()直接指定目标蓝牙设备:
private val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager // 切换到目标蓝牙设备 fun switchAudioOutput(targetDevice: BluetoothDevice) { // 检查设备是否支持A2DP输出 val supportsA2dp = a2dpProfile?.isA2dpPlaying(targetDevice) ?: false if (supportsA2dp) { audioManager.setPreferredDevice(AudioDeviceInfo.TYPE_BLUETOOTH_A2DP, targetDevice.address) } else { // 若为HFP设备,切换到SCO链路 audioManager.setPreferredDevice(AudioDeviceInfo.TYPE_BLUETOOTH_SCO, targetDevice.address) audioManager.startBluetoothSco() } }
2. Android 10(API 29)及以下版本
需结合BluetoothA2dp的setPriority()和connect()方法(需注意部分厂商适配差异):
fun switchAudioOutputLegacy(targetDevice: BluetoothDevice) { a2dpProfile?.let { profile -> // 先断开当前连接的A2DP设备(若有) profile.connectedDevices.forEach { device -> if (device != targetDevice) { profile.disconnect(device) } } // 设置目标设备优先级并连接 profile.setPriority(targetDevice, BluetoothProfile.PRIORITY_ON) profile.connect(targetDevice) } }
注意事项
- 需动态申请权限:Android 12+需在运行时请求
BLUETOOTH_CONNECT权限; - 部分厂商对蓝牙音频切换有定制逻辑,需在对应设备上测试兼容性;
- 切换后可通过
AudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)验证当前输出设备。
内容的提问来源于stack exchange,提问作者Rifat Haque Amit
相关产品推荐
相关产品推荐

