The media2 extension for ExoPlayer
The AndroidX media2 session API is the new version of Android’s MediaSession API. By integrating your application’s media player with this API, you can allow playback to be controlled via Bluetooth media control keys, Google Assistant, Android Auto, and other applications running on the user’s device.
The core class in the media2 session API is MediaSession
, which is responsible for exposing your application’s playback controls and media metadata to other processes.
To instantiate a MediaSession
, you need to provide it with a SessionPlayer
and a MediaSession.SessionCallback
. ExoPlayer’s new media2 extension makes this easy by providing:
SessionPlayerConnector
: An implementation ofSessionPlayer
that wraps anExoPlayer
instance.SessionCallbackBuilder
: BuildsMediaSession.SessionCallback
instances for use withSessionPlayerConnector
.
The code snippet below shows how the media2 extension makes it simple to integrate ExoPlayer with the media2 session API.
Customizing a SessionPlayerConnector
SessionPlayerConnector
is an implementation of the AndroidX’s media2 SessionPlayer
interface, which is the base interface for all media players that want to integrate with media2 APIs. SessionPlayerConnector
wraps an ExoPlayer
instance, and so acts as a translation layer between the ExoPlayer and media2 APIs.
Within the SessionPlayerConnector
translation layer, a MediaItemConverter
is responsible for converting between the different media item representations used by the two APIs. Commands on the player are dispatched via a ControlDispatcher
. Custom implementations of these components can be used to modify the behavior of a SessionPlayerConnector
instance.
Media item conversion
ExoPlayer and media2 have different representations of a media item. A MediaItemConverter
converts ExoPlayer MediaItem
instances to media2 MediaItem
instances, and vice-versa.
DefaultMediaItemConverter
is provided as a default implementation of MediaItemConverter
. A common reason for providing a custom implementation is to inject additional MediaMetadata
into the media2 MediaItem
for sharing outside of the application. This can be done by extending DefaultMediaItemConverter
and overriding its getMetadata
method.
Control dispatching
ControlDispatcher
is responsible for dispatching commands to the player. DefaultControlDispatcher
is provided as a default implementation. Custom implementations can be used to modify or temporarily disable certain commands, for example to prevent seeking during playback of an advert. A custom ControlDispatcher
can be set on a SessionPlayerConnector
by calling its setControlDispatcher
method.
When using a custom ControlDispatcher
, it often makes sense to set the same instance on UI components in your application as well. ExoPlayer’s built in UI components support this by defining the same setControlDispatcher
method.
Customizing a MediaSession.SessionCallback
A MediaSession.SessionCallback
handles incoming commands from MediaController
instances that are interacting with the MediaSession. The ExoPlayer media2 extension provides SessionCallbackBuilder
for building instances suitable for use with SessionPlayerConnector
. When building a callback using SessionCallbackBuilder
, various setters can be used to customize its behavior. Here’s an example in which three custom components are set. The components are described in more detail below.
Controller permissions
The media2 MediaSession API supports finer grained permissions than the legacy MediaSession API. The API allows you to accept or reject connections from a controller, and also to allow or disallow individual commands. The allowed commands can be specified based on the caller, and can be changed dynamically.
An AllowedCommandProvider
can be used to specify controller permissions. Here’s an example of an AllowedCommandProvider
implementation that only accepts connections from the same application:
The media2 extension provides DefaultAllowedCommandProvider
as a default implementation of AllowedCommandProvider
. It behaves in a similar way to the legacy MediaSession API. It only accepts connections from trusted applications, which can call MediaSessionManager.getActiveSessions()
, in addition to your own extra trusted package names.
Handling playlist edits
Media2 controllers can request that a new media item with a specified media ID be added to the player’s playlist. When this occurs, the session is expected to create the corresponding media2 MediaItem
and add it to the playlist. This is done by a MediaItemProvider
.
A custom implementation may wish to add metadata into the MediaItem
for other applications to display. For example:
Custom actions
Applications often want to provide additional custom actions to be displayed in a remote player UI, such as those of Android Audio and Wear OS.
The CustomCommandProvider
interface can be implemented to define custom actions. The getCustomCommands
method should be implemented to return custom actions that should be advertised to media controllers. When a media controller sends a custom action, the onCustomCommands
method will be invoked to handle it.
Obtaining a MediaSessionCompat.Token
Your application may depend on APIs that require a MediaSessionCompat.Token
, such as PlayerNotificationManager
. To obtain a token for a media2 MediaSession, MediaSessionUtil.getSessionCompatToken
can be used:
The ExoPlayer media2 extension makes it easy to integrate ExoPlayer with the media2 MediaSession API. It does all the heavy lifting for you, whilst still giving you full control over the behavior of all of the media actions defined by the API.
We’re looking forward to seeing the media2 extension working in your application. We are happy to receive feedback and feature requests on our Github Issue tracker.