Understanding MediaSession (Part 2/4)
Making sense of the complex media landscape
Introduction
The goal of this series of articles is to give you a deep understanding of MediaSession
, what it is good for, when to use it, and when not to. This is the second part of a 4 part series that includes:
- Is MediaSession for me?
- Making sense of the complex media landscape (this article)
- How to use it for simple use cases
- How to use it for complex use cases
It’s a complex media landscape
If you’re developing a media playback app, it probably creates a UI, and manages a media player (for example, MediaPlayer
or ExoPlayer
). It might also deal with browsing media catalogs, queues, and playlists, etc.
The user of your media playback app also expects to be able to control it outside of the UI of the app itself. Here are some examples of their expectations.
Users expect to be able to pause playback in your app by telling the Google Assistant to “
pause playback
” without interacting with the UI of your app.They expect to be able to use media keys on their headphones to be able to control playback without interacting with the UI.
If the user has Android Auto, then they expect to see a catalog of music that they want played when their phone connects with their car.
We will call the “things” outside of your app that are controlling media “outside actors”. These outside actors include: Android TV, Android Wear, Android Auto, the media buttons on your headset, Google Assistant, Lock Screen controls, and even MediaStyle
notifications.
Each of these may cause state changes inside your app, and there needs to be a way to respond to these changes. This is where MediaSession comes into play.
What does MediaSession do?
MediaSession
does the following things:
- Playback Control — It provides a single interface to control playback (eg: play, pause, stop, skip to next, play for search) that can be used by your app’s UI and external actors (eg: media buttons, Google Assistant). This might seem confusing at first, but if you bypass the
MediaSession
and directly control your player, then your app’s UI can easily go out of sync with the player and session when outside actors change playback state, or load different media. - State Sync — It broadcasts the current playback state (playing, paused, stopped, etc) and media metadata (album art, song duration, song title, etc) to all outside actors, and your app itself.
What is MediaSession?
MediaSession
is the middleware that allows outside actors to control the media player in your app (outside of the app’s own UI). It also allows your app to report changes in its player’s state (what media is loaded, is the player currently paused, or playing, etc) to interested parties outside and inside of your app.
What is MediaSession not?
MediaSession
doesn’t manage your app’s media player; you still have to create a media player, load media into it, prepare it for playback, actually control playback, etc. The app still has to deal with audio focus. And it has to manage its own UI and have that integrate with the MediaSession
.
Let’s take two examples of a user invoking a pause action in your app by pressing a media button, or by asking the Google Assistant to pause playback. Let’s say that audio is already playing in the background in your app’s service when this happens. In either case, very similar things happen in your app.
- Pressing on the media pause button fires an Intent that is received by your app. The
MediaSession
then transmits this to your app by callingonPause()
in the callback to your code that you provide to theMediaSession
. A very similar thing happens when the Google Assistant is asked to “pause playback”. Both paths end up in theonPause()
method that is called by theMediaSession
into your code. - At this point, you are responsible for implementing
onPause()
in your music service and connecting to your player and actually pausing its playback. As soon as this is done, you are responsible for reporting that the playback state has changed, by communicating this back to theMediaSession
by callingsetPlaybackState()
with the new state. - Your app’s UI should connect to the
MediaSession
and when this playback state is changed, you have to implement anonPlaybackStateChanged()
method in your UI code. Here, you can update your UI to show that the playback state has changed to pause.
This is a brief overview of some high level steps that you have to take in order to use MediaSession
. The next article in the series covers this in much greater detail for simple use cases (eg: apps that play video in the foreground).