MediaSession
@DoNotMock
public class MediaSession
MediaLibraryService.MediaLibrarySession |
An extended |
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:
- Session Lifecycle
- Threading Model
- Media Key Events Mapping
- Supporting Multiple Sessions
- Backward Compatibility with Legacy Session APIs
- 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 | Player API |
|---|---|
KEYCODE_MEDIA_PLAY |
play |
KEYCODE_MEDIA_PAUSE |
pause |
|
|
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.BuilderA builder for |
public interface MediaSession.CallbackA callback to handle incoming commands from |
public final class MediaSession.ConnectionResultA result for |
|
A builder for |
public final class MediaSession.ControllerInfoInformation of a |
@UnstableApiRepresentation of a list of |
@UnstableApiA progress reporter to report progress for a custom command sent by a controller. |
Public methods |
|
|---|---|
final void |
broadcastCustomCommand(SessionCommand command, Bundle args)Broadcasts a custom command to all connected controllers. |
static int |
getBitmapDimensionLimit(Context context)Returns the bitmap dimension limit in pixels. |
final BitmapLoader |
Returns the |
final List<MediaSession.ControllerInfo> |
Returns the list of connected controllers. |
final @Nullable MediaSession.ControllerInfo |
Returns the |
ImmutableList<CommandButton> |
Returns the custom layout of the session. |
final String |
getId()Returns the session ID. |
ImmutableList<CommandButton> |
Returns the media button preferences of the session. |
@Nullable MediaSession.ControllerInfo |
Returns the |
final MediaSession.Token |
Returns the platform |
final Player |
Returns the underlying |
final @Nullable PendingIntent |
Returns the |
Bundle |
Returns the session extras. |
final boolean |
Returns whether a play button is shown if playback is |
final SessionToken |
getToken()Returns the |
final boolean |
@UnstableApiReturns whether the given |
final boolean |
@UnstableApiReturns whether the given |
boolean |
@UnstableApiReturns whether the given media controller info belongs to the media notification controller. |
final void |
release()Releases the session and disconnects all connected controllers. |
final ListenableFuture<SessionResult> |
sendCustomCommand(Sends a custom command to a specific controller. |
final void |
@UnstableApiSends a non-fatal error to all connected controllers. |
final void |
@UnstableApiSends a non-fatal error to the given controller. |
final void |
setAvailableCommands(Sets the new available commands for the controller. |
final void |
setCustomLayout(List<CommandButton> layout)Sets the custom layout for all controllers. |
final ListenableFuture<SessionResult> |
@CanIgnoreReturnValueSets the custom layout for the given controller. |
final void |
@UnstableApiSets the media button preferences for all controllers. |
final ListenableFuture<SessionResult> |
@UnstableApiSets the media button preferences for the given controller. |
final void |
@UnstableApiSets the playback exception for all connected controllers. |
final void |
@UnstableApiSets the playback exception for the given controller. |
final void |
Sets the underlying |
final void |
@UnstableApiUpdates the session activity that was set when |
final void |
@UnstableApiSends the session activity to the connected controller. |
final void |
setSessionExtras(Bundle sessionExtras)Sets the |
final void |
setSessionExtras(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 |
| See also | |
|---|---|
sendCustomCommand |
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. |
getConnectedControllers
public final List<MediaSession.ControllerInfo> getConnectedControllers()
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 |
getCustomLayout
@UnstableApi
public ImmutableList<CommandButton> getCustomLayout()
Returns the custom layout of the session.
This method will be deprecated, prefer to use getMediaButtonPreferences instead. Note that the media button preferences use slots to define the allowed button placement.
For informational purpose only. Mutations on the Bundle of either a CommandButton or a SessionCommand do not have effect. To change the custom layout use setCustomLayout or setCustomLayout.
getMediaButtonPreferences
@UnstableApi
public ImmutableList<CommandButton> getMediaButtonPreferences()
Returns the media button preferences of the session.
For informational purpose only. Mutations on the Bundle of either a CommandButton or a SessionCommand do not have effect. To change the media button preferences use setMediaButtonPreferences.
getMediaNotificationControllerInfo
@UnstableApi
public @Nullable MediaSession.ControllerInfo getMediaNotificationControllerInfo()
Returns the ControllerInfo of the media notification controller.
Use this controller info to set available commands and media button preferences 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 media button preferences before they are passed to the notification provider. Disabled command buttons are not converted to notification actions when using DefaultMediaNotificationProvider. 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 media button preferences 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()).
getPlatformToken
@UnstableApi
public final MediaSession.Token getPlatformToken()
Returns the platform android.media.session.MediaSession.Token of the android.media.session.MediaSession created internally by this session.
getSessionActivity
public final @Nullable PendingIntent getSessionActivity()
Returns the PendingIntent to launch the session activity or null if not set.
| Returns | |
|---|---|
@Nullable PendingIntent |
The |
getSessionExtras
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 instances.
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<SessionResult> sendCustomCommand(
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 platform or legacy controller.
| Parameters | |
|---|---|
MediaSession.ControllerInfo controller |
The controller to send the custom command to. |
SessionCommand command |
A custom command. |
Bundle args |
A |
| Returns | |
|---|---|
ListenableFuture<SessionResult> |
A |
| See also | |
|---|---|
broadcastCustomCommand |
sendError
@UnstableApi
public final void sendError(SessionError sessionError)
Sends a non-fatal error to all connected controllers.
See sendError for sending an error to a specific controller only.
| Parameters | |
|---|---|
SessionError sessionError |
The session error. |
sendError
@UnstableApi
public final void sendError(
MediaSession.ControllerInfo controllerInfo,
SessionError sessionError
)
Sends a non-fatal error to the given controller.
This will call onError of the given connected controller.
When an error is sent to getMediaNotificationControllerInfo or a platform or legacy controller, the error of the playback state of the platform session is updated accordingly.
| Parameters | |
|---|---|
MediaSession.ControllerInfo controllerInfo |
The controller to send the error to. |
SessionError sessionError |
The session error. |
| Throws | |
|---|---|
java.lang.IllegalArgumentException |
thrown if an error is attempted to be sent to a legacy 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 for all controllers.
This method will be deprecated, prefer to use setMediaButtonPreferences. Note that the media button preferences use slots to define the allowed button placement.
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 to false if the available commands of a controller do not allow to use a button.
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 ConnectionResult.AcceptedResultBuilder.
| Parameters | |
|---|---|
List<CommandButton> layout |
The ordered list of |
setCustomLayout
@CanIgnoreReturnValue
public final ListenableFuture<SessionResult> setCustomLayout(
MediaSession.ControllerInfo controller,
List<CommandButton> layout
)
Sets the custom layout for the given controller.
This method will be deprecated, prefer to use setMediaButtonPreferences. Note that the media button preferences use slots to define the allowed button placement.
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.
On the controller side, the enabled flag is set to false if the available commands of the controller do not allow to use a button.
Interoperability: This call has no effect when called for a platform or legacy controller.
| Parameters | |
|---|---|
MediaSession.ControllerInfo controller |
The controller for which to set the custom layout. |
List<CommandButton> layout |
The ordered list of |
setMediaButtonPreferences
@UnstableApi
public final void setMediaButtonPreferences(List<CommandButton> mediaButtonPreferences)
Sets the media button preferences for all controllers.
Calling this method broadcasts the media button preferences to all connected Media3 controllers, including the media notification controller.
On the controller side, the enabled flag is set to false if the available commands of a controller do not allow to use a button.
onMediaButtonPreferencesChanged is only called if the new media button preferences are different to the media button preferences 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 media button preferences available with the initial connection result. Media button preferences specific to a controller can be set when the controller connects by using an ConnectionResult.AcceptedResultBuilder.
| Parameters | |
|---|---|
List<CommandButton> mediaButtonPreferences |
The ordered list of |
setMediaButtonPreferences
@UnstableApi
@CanIgnoreReturnValue
public final ListenableFuture<SessionResult> setMediaButtonPreferences(
MediaSession.ControllerInfo controller,
List<CommandButton> mediaButtonPreferences
)
Sets the media button preferences for the given controller.
Make sure to have the session commands of all command buttons of the media button preferences 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, onMediaButtonPreferencesChanged is only called if the new media button preferences are different to the media button preferences the controller already has available. Note that this comparison uses equals and therefore ignores extras.
On the controller side, the enabled flag is set to false if the available commands of the controller do not allow to use a button.
Interoperability: This call has no effect when called for a platform or legacy controller.
| Parameters | |
|---|---|
MediaSession.ControllerInfo controller |
The controller for which to set the media button preferences. |
List<CommandButton> mediaButtonPreferences |
The ordered list of |
setPlaybackException
@UnstableApi
public final void setPlaybackException(@Nullable PlaybackException playbackException)
Sets the playback exception for all connected controllers.
The exception set for controllers can be removed by passing null. This also resets any exception that may have been set for a specific controller with setPlaybackException.
| Parameters | |
|---|---|
@Nullable PlaybackException playbackException |
The |
| See also | |
|---|---|
setPlaybackException |
setPlaybackException
@UnstableApi
public final void setPlaybackException(
MediaSession.ControllerInfo controllerInfo,
@Nullable PlaybackException playbackException
)
Sets the playback exception for the given controller.
When setting a non-null instance, the original player state is overridden. When the player is not in an error state, the exception is used to modify the player state and send it to the controller. If the player is already in an error state, then this exception replaces the original exception and sends the updated player state to the controller.
An exception set for a given controller can be removed by setting null.
Passing in a playback exception that has equal error info to the previously set exception for the given controller, results in a no-op.
| Parameters | |
|---|---|
MediaSession.ControllerInfo controllerInfo |
The controller for which to set the playback exception. |
@Nullable PlaybackException playbackException |
The |
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 |
java.lang.IllegalStateException |
if the new player's application looper differs from the current looper. |
setSessionActivity
@UnstableApi
public final void setSessionActivity(@Nullable PendingIntent activityPendingIntent)
Updates the session activity that was set when building the session.
Note: When a controller is connected to the session that has a version smaller than 1.6.0, then setting the session activity to null has no effect on the controller side.
| Parameters | |
|---|---|
@Nullable PendingIntent activityPendingIntent |
The pending intent to start the session activity or null. |
| Throws | |
|---|---|
java.lang.IllegalArgumentException |
if the |
setSessionActivity
@UnstableApi
public final void setSessionActivity(
MediaSession.ControllerInfo controller,
@Nullable PendingIntent activityPendingIntent
)
Sends the session activity to the connected controller.
This call immediately returns and doesn't wait for a result from the controller.
Interoperability: This call has no effect when called for a platform or legacy controller. To set the session activity of the platform session use the media notification controller as the target controller.
| Parameters | |
|---|---|
MediaSession.ControllerInfo controller |
The controller to send the session activity to. |
@Nullable PendingIntent activityPendingIntent |
The pending intent to start the session activity. |
| Throws | |
|---|---|
java.lang.IllegalArgumentException |
if the |
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 call immediately returns and doesn't wait for a result from the controller.
| 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 call immediately returns and doesn't wait for a result from the controller.
Interoperability: This call has no effect when called for a platform or legacy controller.
| Parameters | |
|---|---|
MediaSession.ControllerInfo controller |
The controller to send the extras to. |
Bundle sessionExtras |
The session extras. |