First, it is important to distinct MediaSessionCompat
from any service such as MediaBrowserServiceCompat
.
MediaSessionCompat
is communicating with the external MediaSessionStack
that dictates which app will get media key commands from external MediaSessionService
. On API 26+ the key will be sent to the last playing app. Devices with API < 26 will first look for active playing/buffering session, then for active session and then for last playing session. The latter allows apps to 'steal' the focus by keeping the mMediaSesssion.isActive
tag on when they shouldn't. More details about priority can be found in the official guide.
So as long as your app set mMediaSesssion.isActive = true
at some point and was last playing, it will get media keys unless mMediaSession.release()
was called. The latter removes your session from MediaSessionStack
and thus will your session no longer receives media keys. That's why it is important to call release()
once you no longer expect user to continue playing video or music. There is one more caveat: If system thinks your app was killed as opposed to ended gracefully, then the app is removed from MediaSessionStack
as well, which makes sense, because in service onDestroy()
is not necessarily called in such scenario and thus the system releases your session for you. This might happen when you swipe away the app. A workaround I use is to keep the service in foreground while the main app is in use and then end the service after a short delay upon receiving a call to onTaskRemoved()
in service.
The call to mMediaSession.release()
will happen at some point if you put it in onDestroy()
of your service. The service is expected to end when it is not being used, as otherwise it is taking system resources. Thus, it is recommended to end it in onStop()
command or when swiping away app or notification. In your case it may happen that power manager killed your service after being inactive for some time. Depending on implementation the some parts of the player might still be working even if the service is destroyed. Also the notification might still be there, as the service is no longer in foreground. That might've fool you into thinking that the service was running. Though without more details, I cannot really say what exactly went wrong in your case.
One additional cause that might prevent your app from getting media keys is if your manifest is not properly configured. Make sure that your BroadcaseReceiver
entry includes android.intent.action.MEDIA_BUTTON
intent filter.
Another possible mistake is initializing your media key callback MediaSessionCompat.Callback()
in the service or any other lifecycle component. Thus, if that component gets destroyed, it can quickly lead to unexpected behavior.
TLDR:
Filter your Logcat
for MediaSessionStack|MediaSessionService
to ensure that your app gets the media keys. If it doesn't, then:
- ensure that
mMusicService.isActive = true
is set (in e.g. in onPlay()
)
- ensure that
mMusicService.release()
is not called
- ensure that your manifest is properly set
- ensure that the system doesn't think your service was killed (e.g. by swiping away the app) as opposed to being ended gracefully
Then make sure your app is handling media keys properly.
- In case of custom receiver, they should be there.
- In case of
androidx.media.session.MediaButtonReceiver
they should be in MediaControllerCompat.Callback()
whose state should not depend on any service or lifecycle component
I wrote the answer a little bit more general, since it is an old question and others might benefit from it more than the OP.