0

I want to use the media buttons to control a foreground app, but not for audio use. So the goal is to detect button clicks to do certain things in the app.

I can achieve that by using MediaSession and the MediaButtonReceiver. see here

The problem is that when the app is used, often users play music in the background, so the audio focus of the background app takes over the MediaSession and i cannot control my app anymore.

Is there a way to achieve that? Directly listening for button clicks with onKeyDown does not seem to work.

cwiesner
  • 934
  • 1
  • 8
  • 24

1 Answers1

1

sadly there is no way for two active MediaSessions at the same time. if another app is playing music and run MediaSession then yours doesn't have focus and isn't active... this is made for purpose - better UX - only one "player" app can play music (or video). if this wouldn't work like that and you could play music by few apps at once then how should work media button on e.g. headphones? pasuing/resuming all players? this is just not user-friendly, so Android team introduced MediaSession pattern with option for calling "focus on me now" by any app, but then another app/MediaSession pauses and doesn't get any inputs (this active session does)

if you need physical buttons presses then onKeyDown should work (inside Activity or eventually using AccessibilityService, which would work "globally" in whole system). if you need some on-screen notification buttons presses then just make custom layout for your notification with as much buttons as you like, even styled as a player

note that in Android 11 active MediaSessions notification is stickied to top of notification section when you drop down status bar. your custom notification will be somewhere below between all others (you can manipulate position a bit using priority param for notification/channel)

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • seems like `onKeyDown` is not called in my active Activity bc. MediaSessionService is swallowing it. Is that possible? Using AccessibilityService would require granting permission, that's not suitable for me here. – cwiesner Jan 08 '21 at 08:52
  • i can receive `VOLME_UP` for example, but `KEYCODE_MEDIA_PLAY` is not propagated to the Activity, but in the logs i see that `MediaSessionService` is sending those events - so somehow that keys where propagated/catched to the service but not to my running activity – cwiesner Jan 08 '21 at 09:01
  • `KEYCODE_MEDIA_PLAY` is aggregated event - may come from physical button (wired headset, BT speaker etc.) or some virtual button visible on screen (in app or on notification). this aggregation is done on system level by OS and/or Google Play Services (which is privileged services pack) for purpose as above - mechanism handles audio playing preventing multiple outputs commin out at once, there is no way for preventing that – snachmsm Jan 08 '21 at 09:11
  • thanks for clarification. so there is no way for listening to those key events other than `MediaSession.Callback` but i cannot use that as i have background audio... – cwiesner Jan 08 '21 at 09:23
  • exacly, service playing audio and running media session gains audio focus and its callback is getting called, all other won't. you may acquire audio focus at almost any time (e.g. by starting some sticky `Service` and after 84573 seconds requesting focus) even when you won't play any audio, but this will make your `Callback` active disabling all others. just before revoking focus from this another/previous `MediaSession` audio/session managing mechanism will call some "pause" method for stopping prev audio and preventing simultaneous playback - thats the feature :) – snachmsm Jan 08 '21 at 09:56