-
Notifications
You must be signed in to change notification settings - Fork 471
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Listening to changes of current audio output #2080
Comments
I got a working solution. I leave it here.I found there is an AndroidX version of implementation("androidx.mediarouter:mediarouter:1.7.0") I created a custom type for my solution: sealed interface AudioOutputType {
data object Headphones : AudioOutputType
data object Speaker : AudioOutputType
data object Unknown : AudioOutputType
} Solution: class AudioRouteMonitor(private val context: Context) {
private val mediaRouter: MediaRouter by lazy { MediaRouter.getInstance(context) }
private var callback: ((AudioOutputType) -> Unit)? = null
private val selector = MediaRouteSelector.Builder()
.addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
.build()
private val mediaRouterCallback = object : MediaRouter.Callback() {
override fun onRouteSelected(router: MediaRouter, route: RouteInfo, reason: Int) {
handleRouteChange(route)
}
}
fun startMonitoring(outputChangeCallback: (AudioOutputType) -> Unit) {
callback = outputChangeCallback
mediaRouter.addCallback(selector, mediaRouterCallback,
MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN)
handleRouteChange(mediaRouter.selectedRoute)
}
fun stopMonitoring() {
mediaRouter.removeCallback(mediaRouterCallback)
callback = null
}
private fun handleRouteChange(route: RouteInfo) {
val outputType = when {
isSpeakerRoute(route) -> AudioOutputType.Speaker
isHeadphonesRoute(route) -> AudioOutputType.Headphones
else -> AudioOutputType.Unknown
}
Timber.d("Active audio route changed to: $outputType")
callback?.invoke(outputType)
}
private fun isSpeakerRoute(route: RouteInfo): Boolean {
if (route.isDefault) return true
return listOf(
RouteInfo.DEVICE_TYPE_BUILTIN_SPEAKER,
RouteInfo.DEVICE_TYPE_REMOTE_SPEAKER,
RouteInfo.DEVICE_TYPE_SMARTPHONE
)
.contains(route.deviceType)
}
private fun isHeadphonesRoute(route: RouteInfo): Boolean {
return listOf(
RouteInfo.DEVICE_TYPE_BLUETOOTH_A2DP,
RouteInfo.DEVICE_TYPE_WIRED_HEADPHONES,
RouteInfo.DEVICE_TYPE_WIRED_HEADSET,
RouteInfo.DEVICE_TYPE_USB_HEADSET,
RouteInfo.DEVICE_TYPE_BLE_HEADSET,
)
.contains(route.deviceType)
}
} I call this class in my |
Glad that you were able to create a working solution using the MediaRouter APIs! Closing the thread as completed. Please feel free to create a new issue if you have additional questions. |
For future readers: The approach with MediaRouter isn't necessarily reliable in all situations. The audio track created by ExoPlayer is routed according to its audio attributes and manual overrides (e.g. by using |
Use case description
I’m developing an app that plays audio for users in a museum (like a virtual tour guide). The app needs to detect the current audio output device so it can automatically adjust the maximum volume. Specifically:
Proposed solution
Add an API that allows apps to listen to changes of current audio output (e.g., speaker ↔ headphones ↔ Bluetooth).
This would enable apps to accurately respond in real time and adjust their audio behavior accordingly.
Users can change it here:
Alternatives considered
AudioManager
,AudioDeviceCallback
,MediaRouter
or silentAudioTrack
withAudioRouting
) has proven unreliable or inconsistent when the user switches audio outputs manually without disconnecting headphones.AudioBecomingNoisy
doesn't trigger when the user switches audio outputs manually and works only in one direction (from headphones to speaker).C.USAGE_VOICE_COMMUNICATION
can mimic call-like audio, but it causes problems:Given these limitations, an official, reliable listener/callback for audio output routing changes in Media3/ExoPlayer would greatly simplify the development of apps with dynamic audio output requirements.
The text was updated successfully, but these errors were encountered: