@DoNotMock
public class MediaSession


A session that allows a media app to expose its player functionality, information of the playlist and the media item currently being played to other processes including the Android framework and other apps. The common use cases are as follows:

  • Receiving and dispatching media key events (for instance Bluetooth/wired headset and remote control devices).
  • Publish media playback information and player commands to SystemUI (media notification) and Android Auto/Wear OS.
  • Separating UI process and playback process.

A session should be created when an app wants to publish media playback information or handle media key events. In general, an app only needs one session for all playback, though multiple sessions can be created to provide finer grain controls of media. See Supporting Multiple Sessions for details.

If an app wants to support playback when in the background, using a MediaSessionService is the preferred approach. See MediaSessionService for details.

Topics covered here:

  1. Session Lifecycle
  2. Threading Model
  3. Media Key Events Mapping
  4. Supporting Multiple Sessions
  5. Backward Compatibility with Legacy Session APIs
  6. Backward Compatibility with Legacy Controller APIs

Session Lifecycle

A session can be created by Builder. The owner of the session may pass its session token to other processes to allow them to create a MediaController to interact with the session.

When a session receives playback commands, the session calls corresponding methods directly on the underlying player set by Builder or setPlayer.

When an app is finished performing playback it must call release to clean up the session and notify any controllers. The app is responsible for releasing the underlying player after releasing the session.

Threading Model

The instances are thread safe, but must be used on a thread with a looper.

Callback methods will be called on the application thread associated with the application looper of the underlying player. When a new player is set by setPlayer, the player must use the same application looper as the previous one.

The session listens to player events via Player.Listener and expects the callback methods to be called on the application thread. If the player violates the threading contract, an IllegalStateException will be thrown.

Media Key Events Mapping

When the session receives media key events they are mapped to a method call on the underlying player. The following table shows the mapping between the event key code and the Player method which is called.

Key code and corresponding Player API
Key code Player API
KEYCODE_MEDIA_PLAY play
KEYCODE_MEDIA_PAUSE pause
  • For a single tap,
  • In case the media key events are coming from another package ID than the package ID of the media app (events coming for instance from Bluetooth), a double tap generating two key events within a brief amount of time, is converted to seekToNext
KEYCODE_MEDIA_NEXT seekToNext
KEYCODE_MEDIA_PREVIOUS seekToPrevious
KEYCODE_MEDIA_STOP stop
KEYCODE_MEDIA_FAST_FORWARD seekForward
KEYCODE_MEDIA_REWIND seekBack

Supporting Multiple Sessions

Generally, multiple sessions aren't necessary for most media apps. One exception is if your app can play multiple media content at the same time, but only for the playback of video-only media or remote playback, since the audio focus policy recommends not playing multiple audio content at the same time. Also, keep in mind that multiple media sessions would make Android Auto and Bluetooth devices with display to show your app multiple times, because they list up media sessions, not media apps.

Backward compatibility with platform and legacy session APIs

An active android.media.session.MediaSession is internally created with the session for backwards compatibility. It's used to handle incoming connections and commands from android.media.session.MediaController and legacy android.support.v4.media.session.MediaControllerCompat instances.

Backward compatibility with platform and legacy controller APIs

In addition to MediaController, the session also supports connections from the platform and legacy controller APIs - android.media.session.MediaController and android.support.v4.media.session.MediaControllerCompat. However, ControllerInfo may not be precise for these controllers. See ControllerInfo for the details.

Neither an unknown package name nor an unknown UID mean that you should disallow a connection or commands per se. For SDK levels where such issues happen, session tokens can only be obtained by trusted controllers (e.g. Bluetooth, Auto, ...). This means only trusted controllers can connect and an app can accept such controllers in the same way as with legacy sessions.

Summary

Nested types

public final class MediaSession.Builder

A builder for MediaSession.

public interface MediaSession.Callback

A callback to handle incoming commands from MediaController.

A result for onConnect to denote the set of available commands and the media button preferences for a controller.

A builder for ConnectionResult instances to accept a connection.

public final class MediaSession.ControllerInfo

Information of a MediaController or a MediaBrowser.

Representation of a list of media items and where to start playing.

A progress reporter to report progress for a custom command sent by a controller.

Public methods

final void

Broadcasts a custom command to all connected controllers.

static int

Returns the bitmap dimension limit in pixels.

final BitmapLoader

Returns the BitmapLoader.

final List<MediaSession.ControllerInfo>

Returns the list of connected controllers.

final @Nullable MediaSession.ControllerInfo

Returns the ControllerInfo for the controller that sent the current request for a Player method.

ImmutableList<CommandButton>

Returns the custom layout of the session.

final String

Returns the session ID.

ImmutableList<CommandButton>

Returns the media button preferences of the session.

@Nullable MediaSession.ControllerInfo

Returns the ControllerInfo of the media notification controller.

final MediaSession.Token

Returns the platform android.media.session.MediaSession.Token of the android.media.session.MediaSession created internally by this session.

final Player

Returns the underlying Player.

final @Nullable PendingIntent

Returns the PendingIntent to launch the session activity or null if not set.

Bundle

Returns the session extras.

final boolean

Returns whether a play button is shown if playback is suppressed.

final SessionToken

Returns the SessionToken for creating MediaController instances.

final boolean

Returns whether the given ControllerInfo belongs to an Android Auto companion app controller.

final boolean

Returns whether the given ControllerInfo belongs to an Automotive OS controller.

boolean

Returns whether the given media controller info belongs to the media notification controller.

final void

Releases the session and disconnects all connected controllers.

final ListenableFuture<SessionResult>
sendCustomCommand(
    MediaSession.ControllerInfo controller,
    SessionCommand command,
    Bundle args
)

Sends a custom command to a specific controller.

final void

Sends a non-fatal error to all connected controllers.

final void
@UnstableApi
sendError(
    MediaSession.ControllerInfo controllerInfo,
    SessionError sessionError
)

Sends a non-fatal error to the given controller.

final void
setAvailableCommands(
    MediaSession.ControllerInfo controller,
    SessionCommands sessionCommands,
    Player.Commands playerCommands
)

Sets the new available commands for the controller.

final void

Sets the custom layout for all controllers.

final ListenableFuture<SessionResult>

Sets the custom layout for the given controller.

final void

Sets the media button preferences for all controllers.

final ListenableFuture<SessionResult>

Sets the media button preferences for the given controller.

final void

Sets the playback exception for all connected controllers.

final void
@UnstableApi
setPlaybackException(
    MediaSession.ControllerInfo controllerInfo,
    @Nullable PlaybackException playbackException
)

Sets the playback exception for the given controller.

final void
setPlayer(Player player)

Sets the underlying Player for this session to dispatch incoming events to.

final void

Updates the session activity that was set when building the session.

final void
@UnstableApi
setSessionActivity(
    MediaSession.ControllerInfo controller,
    @Nullable PendingIntent activityPendingIntent
)

Sends the session activity to the connected controller.

final void
setSessionExtras(Bundle sessionExtras)

Sets the session extras and sends them to connected controllers.

final void
setSessionExtras(
    MediaSession.ControllerInfo controller,
    Bundle sessionExtras
)

Sends the session extras to the connected controller.

Public methods

broadcastCustomCommand

public final void broadcastCustomCommand(SessionCommand command, Bundle args)

Broadcasts a custom command to all connected controllers.

This call immediately returns and doesn't wait for a result from the controller.

A command is not accepted if it is not a custom command.

Parameters
SessionCommand command

A custom command.

Bundle args

A Bundle for additional arguments. May be empty.

getBitmapDimensionLimit

public static int getBitmapDimensionLimit(Context context)

Returns the bitmap dimension limit in pixels. Bitmaps with width or height larger than this will be scaled down to fit within the limit.

Parameters
Context context

The context in which the bitmap dimension limit is defined.

Returns
int

The bitmap dimension limit in pixels.

getBitmapLoader

@UnstableApi
public final BitmapLoader getBitmapLoader()

Returns the BitmapLoader.

getConnectedControllers

public final List<MediaSession.ControllerInfogetConnectedControllers()

Returns the list of connected controllers.

getControllerForCurrentRequest

public final @Nullable MediaSession.ControllerInfo getControllerForCurrentRequest()

Returns the ControllerInfo for the controller that sent the current request for a Player method.

This method will return a non-null value while Player methods triggered by a controller are executed.

Note: If you want to prevent a controller from calling a method, specify the available commands in onConnect or set them via setAvailableCommands.

This method must be called on the application thread of the underlying player.

Returns
@Nullable MediaSession.ControllerInfo

The ControllerInfo of the controller that sent the current request, or null if not applicable.

getCustomLayout

@UnstableApi
public