@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 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 Legacy Session APIs

An active MediaSessionCompat is internally created with the session for backwards compatibility. It's used to handle incoming connections and commands from instances, and helps to utilize existing APIs that are built with legacy media session APIs.

Backward Compatibility with Legacy Controller APIs

In addition to MediaController, the session also supports connections from the legacy controller APIs - framework controller and AndroidX controller compat. However, ControllerInfo may not be precise for legacy 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 custom layout 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.

Public methods

final void

Broadcasts a custom command to all connected controllers.

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.

@Nullable MediaSession.ControllerInfo

Returns the ControllerInfo of the media notification controller.

final Player

Returns the underlying Player.

final @Nullable PendingIntent

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

final MediaSessionCompat.Token

Returns the MediaSessionCompat.Token of the MediaSessionCompat created internally by this session.

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.

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
setAvailableCommands(
    MediaSession.ControllerInfo controller,
    SessionCommands sessionCommands,
    Player.Commands playerCommands
)

Sets the new available commands for the controller.

final void

Sets the custom layout that can initially be set when building the session.

final ListenableFuture<SessionResult>

Sets the custom layout for the given Media3 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
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 is a synchronous call and doesn't wait for results from the controllers.

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.

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 ImmutableList<CommandButtongetCustomLayout()

Returns the custom layout of the session.

For informational purpose only. Mutations on the Bundle of either a or a SessionCommand do not have effect. To change the custom layout use setCustomLayout or setCustomLayout.

getId

public final String getId()

Returns the session ID.

getMediaNotificationControllerInfo

@UnstableApi
public @Nullable MediaSession.ControllerInfo getMediaNotificationControllerInfo()

Returns the ControllerInfo of the media notification controller.

Use this controller info to set available commands and custom layout that are consistently applied to the media notification on all API levels.

Available session commands of the media notification controller are used to enable or disable buttons of the custom layout before it is passed to the notification provider. Disabled command buttons are not converted to notification actions when using . This affects the media notification displayed by System UI below API 33.

The available session commands of the media notification controller are used to maintain custom actions of the platform session (see PlaybackStateCompat.getCustomActions()). Command buttons of the custom layout are disabled or enabled according to the available session commands. Disabled command buttons are not converted to custom actions of the platform session. This affects the media notification displayed by System UI starting with API 33.

The available player commands are intersected with the actual available commands of the underlying player to determine the playback actions of the platform session (see PlaybackStateCompat.getActions()).

getPlayer

public final Player getPlayer()

Returns the underlying Player.

getSessionActivity

public final @Nullable PendingIntent getSessionActivity()

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

Returns
@Nullable PendingIntent

The PendingIntent to launch an activity belonging to the session.

getSessionCompatToken

@UnstableApi
public final MediaSessionCompat.Token getSessionCompatToken()

Returns the MediaSessionCompat.Token of the MediaSessionCompat created internally by this session.

getSessionExtras

@UnstableApi
public Bundle getSessionExtras()

Returns the session extras.

For informational purpose only. Mutations on the Bundle do not have immediate effect. To change the session extras use setSessionExtras or setSessionExtras.

getShowPlayButtonIfPlaybackIsSuppressed

@UnstableApi
public final boolean getShowPlayButtonIfPlaybackIsSuppressed()

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

getToken

public final SessionToken getToken()

Returns the SessionToken for creating MediaController.

isAutoCompanionController

@UnstableApi
public final boolean isAutoCompanionController(MediaSession.ControllerInfo controllerInfo)

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

Note: This is not a security validation.

Parameters
MediaSession.ControllerInfo controllerInfo

The controller info of the connected controller.

Returns
boolean

True if the controller into belongs to a connected Auto companion client app.

isAutomotiveController

@UnstableApi
public final boolean isAutomotiveController(MediaSession.ControllerInfo controllerInfo)

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

Note: This is not a security validation.

Parameters
MediaSession.ControllerInfo controllerInfo

The controller info of the connected controller.

Returns
boolean

True if the controller into belongs to a connected Automotive OS controller.

isMediaNotificationController

@UnstableApi
public boolean isMediaNotificationController(
    MediaSession.ControllerInfo controllerInfo
)

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

See getMediaNotificationControllerInfo.

Parameters
MediaSession.ControllerInfo controllerInfo

The controller info.

Returns
boolean

Whether the controller info belongs to the media notification controller.

release

public final void release()

Releases the session and disconnects all connected controllers.

The session must not be used after calling this method.

Releasing the session removes the session's listeners from the player but does not stop or release the player. An app can further use the player after the session is released and needs to make sure to eventually release the player.

sendCustomCommand

public final ListenableFuture<SessionResultsendCustomCommand(
    MediaSession.ControllerInfo controller,
    SessionCommand command,
    Bundle args
)

Sends a custom command to a specific controller.

The result from onCustomCommand will be returned.

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

Interoperability: This call has no effect when called for a legacy controller.

Parameters
MediaSession.ControllerInfo controller

The controller to send the custom command to.

SessionCommand command

A custom command.

Bundle args

A Bundle for additional arguments. May be empty.

Returns
ListenableFuture<SessionResult>

A ListenableFuture of SessionResult from the controller.

setAvailableCommands

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

Sets the new available commands for the controller.

This is a synchronous call. Changes in the available commands take effect immediately regardless of the controller notified about the change through onAvailableCommandsChanged and onAvailableSessionCommandsChanged.

Note that playerCommands will be intersected with the available commands of the underlying Player and the controller will only be able to call the commonly available commands.

Parameters
MediaSession.ControllerInfo controller

The controller to change allowed commands.

SessionCommands sessionCommands

The new available session commands.

Player.Commands playerCommands

The new available player commands.

setCustomLayout

public final void setCustomLayout(List<CommandButton> layout)

Sets the custom layout that can initially be set when building the session.

Calling this method broadcasts the custom layout to all connected Media3 controllers, including the media notification controller.

On the controller side, the enabled flag is set according to the available commands of the controller which overrides a value that has been set by the session.

onCustomLayoutChanged is only called if the new custom layout is different to the custom layout the controller already has available. Note that extras are ignored when comparing command buttons.

Controllers that connect after calling this method will have the new custom layout available with the initial connection result. A custom layout specific to a controller can be set when the controller connects by using an .

Parameters
List<CommandButton> layout

The ordered list of CommandButton.

setCustomLayout

@CanIgnoreReturnValue
public final ListenableFuture<SessionResultsetCustomLayout(
    MediaSession.ControllerInfo controller,
    List<CommandButton> layout
)

Sets the custom layout for the given Media3 controller.

Make sure to have the session commands of all command buttons of the custom layout available for controllers. Include the custom session commands a controller should be able to send in the available commands of the connection result that your app returns when the controller connects. The isEnabled flag is set according to the available commands of the controller and overrides a value that may have been set by the app.

On the controller side, onCustomLayoutChanged is only called if the new custom layout is different to the custom layout the controller already has available. Note that this comparison uses equals and therefore ignores extras.

It's up to controller's decision how to represent the layout in its own UI.

Interoperability: This call has no effect when called for a legacy controller.

Parameters
MediaSession.ControllerInfo controller

The controller for which to set the custom layout.

List<CommandButton> layout

The ordered list of command buttons.

setPlayer

public final void setPlayer(Player player)

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

Parameters
Player player

A player that handles actual media playback in your app.

Throws
java.lang.IllegalArgumentException

if the new player's application looper differs from the current player's looper, or canAdvertiseSession returns false.

java.lang.IllegalStateException

if the new player's application looper differs from the current looper.

setSessionActivity

@UnstableApi
public final void setSessionActivity(PendingIntent activityPendingIntent)

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

Parameters
PendingIntent activityPendingIntent

The pending intent to start the session activity.

setSessionExtras

public final void setSessionExtras(Bundle sessionExtras)

Sets the session extras and sends them to connected controllers.

The initial extras can be set when building the session.

This is a synchronous call and doesn't wait for results from the controllers.

Parameters
Bundle sessionExtras

The session extras.

setSessionExtras

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

Sends the session extras to the connected controller.

The initial extras for a specific controller can be set in onConnect when building the connection result.

This is a synchronous call and doesn't wait for results from the controller.

Interoperability: This call has no effect when called for a legacy controller.

Parameters
MediaSession.ControllerInfo controller

The controller to send the extras to.

Bundle sessionExtras

The session extras.