The media2 extension for ExoPlayer

Jaewan Kim
AndroidX Media3
Published in
4 min readSep 21, 2020

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:

The code snippet below shows how the media2 extension makes it simple to integrate ExoPlayer with the media2 session API.

Example of media2 session integration using ExoPlayer’s media2 extension

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.

Using custom MediaItemConverter and ControlDispatcher instances when building a SessionPlayerConnector

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.

Using SessionCallbackBuilder setters to customizing a MediaSession.SessionCallback

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:

An AllowedCommandProvider 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:

A MediaItemProvider that converts a media ID to a UriMediaItem with metadata.

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.

--

--