I've been trying to look for a good solution to detect when headphones are connected in Android regardless of whether they are wired or wireless.
The case for wired headphones is fairly straight-forward. However, when detecting if a wireless headset is connected, the APIs I have been using require Manifest.permission.BLUETOOTH
or Manifest.permission.BLUETOOTH_CONNECT
.
For some time I've accepted that only if those permissions are granted will I know for sure if headphones are connected, but this is now increasingly becoming problematic.
Does anyone know of an alternative that would determine if a headset is connected without user-facing 'dangerous' permission prompts like the BluetoothHeadset solution does? Is there anything in the AudioManager that can be used instead?
Here is what I have today:
package ai.numbereight.sdk.platform.sensors
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothHeadset
import android.bluetooth.BluetoothProfile
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.util.Log
private val listener = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val connection = when (intent.getIntExtra(BluetoothHeadset.EXTRA_STATE,
BluetoothHeadset.STATE_DISCONNECTED)) {
BluetoothHeadset.STATE_CONNECTED -> "Connected"
BluetoothHeadset.STATE_DISCONNECTED -> "Disconnected"
else -> "Unknown"
}
Log.d("Connection", connection)
}
}
fun register(context: Context) {
// Register for changes - events will only be received
// if Manifest.permission.BLUETOOTH (< Android 10)
// or Manifest.permission.BLUETOOTH_CONNECT (>= Android 10)
// are granted.
val filter = IntentFilter()
filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)
context.registerReceiver(listener, filter)
// Fire initial event - this API call requires the above Bluetooth permissions
// For brevity I assume that the default adapter is not null
val currentState = BluetoothAdapter.getDefaultAdapter()!!.getProfileConnectionState(BluetoothProfile.HEADSET)
val initialIntent = Intent(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)
initialIntent.putExtra(BluetoothHeadset.EXTRA_STATE, currentState)
listener.onReceive(context, initialIntent)
}