MediaSession2

open class MediaSession2 : SessionPlayer, AutoCloseable
kotlin.Any
   ↳ androidx.media2.MediaSession2

Allows a media app to expose its transport controls and playback information in a process to other processes including the Android framework and other apps. Common use cases are as follows.

  • Bluetooth/wired headset key events support
  • Android Auto/Wearable support
  • Separating UI process and playback process

A MediaSession2 should be created when an app wants to publish media playback information or handle media keys. In general an app only needs one session for all playback, though multiple sessions can be created to provide finer grain controls of media.

If you want to support background playback, MediaSessionService2 is preferred instead. With it, your playback can be revived even after playback is finished. See MediaSessionService2 for details.

Topic covered here:

  1. Session Lifecycle
  2. Audio focus and noisy intent
  3. Thread
  4. Media key events mapping
Session Lifecycle

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

When a session receive transport control commands, the session sends the commands directly to the the underlying media player set by Builder or updatePlayerConnector.

When an app is finished performing playback it must call close() to clean up the session and notify any controllers.

Audio focus and noisy intent

MediaSession2 handles audio focus and noisy intent with AudioAttributesCompat set to the underlying MediaPlayerConnector by default. You need to set the audio attribute before the session is created, and playback started with the session.

Here's the table of automatic audio focus behavior with audio attributes.

Audio AttributesAudio Focus Gain TypeMisc AudioAttributesCompat#USAGE_VOICE_COMMUNICATION_SIGNALLING android.media.AudioManager#AUDIOFOCUS_NONE android.media.AudioManager#AUDIOFOCUS_GAIN Developers should specific a proper usage instead of AudioAttributesCompat#USAGE_UNKNOWN android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE AudioAttributesCompat#USAGE_ASSISTANCE_ACCESSIBILITY android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT if AudioAttributesCompat#CONTENT_TYPE_SPEECH, android.media.AudioManager#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK otherwise null No audio focus handling, and sets the player volume to 0 Only valid if your media contents don't have audio Any other AudioAttributes No audio focus handling, and sets the player volume to 0 This is to handle error

For more information about the audio focus, take a look at Managing audio focus

Thread

MediaSession2 objects are thread safe, but should be used on the thread on the looper.

Media key events mapping

Here's the table of per key event.

Key codeMediaSession2 API KeyEvent#KEYCODE_MEDIA_PLAY MediaSession2#play() KeyEvent#KEYCODE_MEDIA_PAUSE MediaSession2#pause() KeyEvent#KEYCODE_MEDIA_NEXT MediaSession2#skipToNextItem() KeyEvent#KEYCODE_MEDIA_PREVIOUS MediaSession2#skipToPreviousItem() KeyEvent#KEYCODE_MEDIA_STOP MediaSession2#pause() and then MediaSession2#seekTo(long) with 0 KeyEvent#KEYCODE_MEDIA_FAST_FORWARD SessionCallback#onFastForward KeyEvent#KEYCODE_MEDIA_REWIND SessionCallback#onRewind

Summary

Nested classes
abstract

Interface definition of a callback to be invoked when a MediaItem2 in the playlist didn't have a DataSourceDesc2 but it's needed now for preparing or playing it.

abstract

Callback to be called for all incoming commands from MediaController2s.

Builder for MediaSession2.

Information of a controller.

Button for a SessionCommand2 that will be shown by the controller.

Constants
static Int

This is the default error code and indicates that none of the other error codes applies.

static Int

Error code when the application state is invalid to fulfill the request.

static Int

Error code when the request is not supported by the application.

static Int

Error code when the request cannot be performed because authentication has expired.

static Int

Error code when a premium account is required for the request to succeed.

static Int

Error code when too many concurrent streams are detected.

static Int

Error code when the content is blocked due to parental controls.

static Int

Error code when the content is blocked due to being regionally unavailable.

static Int

Error code when the requested content is already playing.

static Int

Error code when the application cannot skip any more songs because skip limit is reached.

static Int

Error code when the action is interrupted due to some external event.

static Int

Error code when the playback navigation (previous, next) is not possible because the queue was exhausted.

static Int

Error code when the session needs user's manual intervention.

Public methods
open MediaItem2!

Return currently playing media item.

open Long

Gets the duration of the currently playing media item.

open Unit
updatePlaylistMetadata(@Nullable metadata: MediaMetadata2?)

Updates the playlist metadata to the MediaPlaylistAgent.

open Unit

Skips to the next item.

open Unit

Set the playback speed.

open Long

Gets the current position.

open MutableList<MediaItem2!>!

Returns the playlist from the MediaPlaylistAgent.

open Unit

Play playback.

open Unit
setAllowedCommands(@NonNull controller: MediaSession2.ControllerInfo, @NonNull commands: SessionCommandGroup2)

Set the new allowed command group for the controller

open Int

Gets the shuffle mode from the MediaPlaylistAgent.

open Unit

open MediaPlaylistAgent

open Int

Gets the repeat mode from the MediaPlaylistAgent.

open Int

Gets the current player state.

open Unit
setPlaylist(@NonNull list: MutableList<MediaItem2!>, @Nullable metadata: MediaMetadata2?)

Sets a list of MediaItem2 to the MediaPlaylistAgent.

open Float

Get the playback speed.

open Unit
setShuffleMode(shuffleMode: Int)

Sets the shuffle mode to the MediaPlaylistAgent.

open Long

Gets the buffered position, or MediaPlayerConnector#UNKNOWN_TIME if unknown.

open Unit
notifyError(errorCode: Int, @Nullable extras: Bundle?)

Notify errors to the connected controllers

open Unit
replacePlaylistItem(index: Int, @NonNull item: MediaItem2)

Replaces the media item at index in the playlist.

open MediaPlayerConnector?

open Unit

Sets the data source missing helper.

open Unit
addPlaylistItem(index: Int, @NonNull item: MediaItem2)

Adds the media item to the playlist at position index.

open Unit
seekTo(pos: Long)

Move to a new location in the media stream.

open SessionToken2

Returns the SessionToken2 for creating MediaController2.

open Int

Gets the current buffering state of the player.

open Unit

Removes the media item in the playlist.

open Unit
setRepeatMode(repeatMode: Int)

Sets the repeat mode to the MediaPlaylistAgent.

open MutableList<MediaSession2.ControllerInfo!>

Returns the list of connected controller.

open Unit

Stop playback, and reset the player to the initial state.

open Unit
notifyRoutesInfoChanged(@NonNull controller: MediaSession2.ControllerInfo, @Nullable routes: MutableList<Bundle!>?)

Notify routes information to a connected controller

open Unit

Skips to the item in the playlist.

open Unit

Request that the player prepare its playback.

open Unit

Pause playback.

open MediaMetadata2!

Gets the playlist metadata from the MediaPlaylistAgent.

open Unit
updatePlayerConnector(@NonNull player: MediaPlayerConnector, @Nullable playlistAgent: MediaPlaylistAgent?)

Sets the underlying MediaPlayerConnector and MediaPlaylistAgent for this session to dispatch incoming event to.

open Unit

Skips to the previous item.

open Unit

Clears the data source missing helper.

open Unit
sendCustomCommand(@NonNull command: SessionCommand2, @Nullable args: Bundle?)

Send custom command to all connected controllers.

open Unit
sendCustomCommand(@NonNull controller: MediaSession2.ControllerInfo, @NonNull command: SessionCommand2, @Nullable args: Bundle?, @Nullable receiver: ResultReceiver?)

Send custom command to a specific controller.

open Unit

Sets ordered list of CommandButton for controllers to build UI with it.

Constants

ERROR_CODE_UNKNOWN_ERROR

static val ERROR_CODE_UNKNOWN_ERROR: Int

This is the default error code and indicates that none of the other error codes applies.

Value: 0

ERROR_CODE_APP_ERROR

static val ERROR_CODE_APP_ERROR: Int

Error code when the application state is invalid to fulfill the request.

Value: 1

ERROR_CODE_NOT_SUPPORTED

static val ERROR_CODE_NOT_SUPPORTED: Int

Error code when the request is not supported by the application.

Value: 2

ERROR_CODE_AUTHENTICATION_EXPIRED

static val ERROR_CODE_AUTHENTICATION_EXPIRED: Int

Error code when the request cannot be performed because authentication has expired.

Value: 3

ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED

static val ERROR_CODE_PREMIUM_ACCOUNT_REQUIRED: Int

Error code when a premium account is required for the request to succeed.

Value: 4

ERROR_CODE_CONCURRENT_STREAM_LIMIT

static val ERROR_CODE_CONCURRENT_STREAM_LIMIT: Int

Error code when too many concurrent streams are detected.

Value: 5

ERROR_CODE_PARENTAL_CONTROL_RESTRICTED

static val ERROR_CODE_PARENTAL_CONTROL_RESTRICTED: Int

Error code when the content is blocked due to parental controls.

Value: 6

ERROR_CODE_NOT_AVAILABLE_IN_REGION

static val ERROR_CODE_NOT_AVAILABLE_IN_REGION: Int

Error code when the content is blocked due to being regionally unavailable.

Value: 7

ERROR_CODE_CONTENT_ALREADY_PLAYING

static val ERROR_CODE_CONTENT_ALREADY_PLAYING: Int

Error code when the requested content is already playing.

Value: 8

ERROR_CODE_SKIP_LIMIT_REACHED

static val ERROR_CODE_SKIP_LIMIT_REACHED: Int

Error code when the application cannot skip any more songs because skip limit is reached.

Value: 9

ERROR_CODE_ACTION_ABORTED

static val ERROR_CODE_ACTION_ABORTED: Int

Error code when the action is interrupted due to some external event.

Value: 10

ERROR_CODE_END_OF_QUEUE

static val ERROR_CODE_END_OF_QUEUE: Int

Error code when the playback navigation (previous, next) is not possible because the queue was exhausted.

Value: 11

ERROR_CODE_SETUP_REQUIRED

static val ERROR_CODE_SETUP_REQUIRED: Int

Error code when the session needs user's manual intervention.

Value: 12

Public methods

getCurrentMediaItem

open fun getCurrentMediaItem(): MediaItem2!

Return currently playing media item.

Return
MediaItem2!: currently playing media item

getDuration

open fun getDuration(): Long

Gets the duration of the currently playing media item.

Return
Long: the duration of the current item from MediaPlayerConnector#getDuration().

updatePlaylistMetadata

open fun updatePlaylistMetadata(@Nullable metadata: MediaMetadata2?): Unit

Updates the playlist metadata to the MediaPlaylistAgent.

Parameters
metadata MediaMetadata2?: metadata of the playlist

skipToNextItem

open fun skipToNextItem(): Unit

Skips to the next item.

This calls MediaPlaylistAgent#skipToNextItem() and the behavior depends on the playlist agent implementation, especially with the shuffle/repeat mode.

setPlaybackSpeed

open fun setPlaybackSpeed(speed: Float): Unit

Set the playback speed.

getCurrentPosition

open fun getCurrentPosition(): Long

Gets the current position.

Return
Long: the current playback position in ms, or MediaPlayerConnector#UNKNOWN_TIME if unknown.

getPlaylist

open fun getPlaylist(): MutableList<MediaItem2!>!

Returns the playlist from the MediaPlaylistAgent.

This list may differ with the list that was specified with setPlaylist(List, MediaMetadata2) depending on the MediaPlaylistAgent implementation. Use media items returned here for other playlist agent APIs such as MediaPlaylistAgent#skipToPlaylistItem(MediaItem2).

Return
MutableList<MediaItem2!>!: playlist

play

open fun play(): Unit

Play playback.

This calls MediaPlayerConnector#play().

setAllowedCommands

open fun setAllowedCommands(@NonNull controller: MediaSession2.ControllerInfo, @NonNull commands: SessionCommandGroup2): Unit

Set the new allowed command group for the controller

Parameters
controller MediaSession2.ControllerInfo: controller to change allowed commands
commands MediaSession2.ControllerInfo: new allowed commands

getShuffleMode

open fun getShuffleMode(): Int

Gets the shuffle mode from the MediaPlaylistAgent.

Return
Int: The shuffle mode

close

open fun close(): Unit

getPlaylistAgent

@NonNull open fun getPlaylistAgent(): MediaPlaylistAgent
Return
MediaPlaylistAgent: playlist agent

getPlayerState

open fun getPlayerState(): Int

Gets the current player state.

Return
Int: the current player state

setPlaylist

open fun setPlaylist(@NonNull list: MutableList<MediaItem2!>, @Nullable metadata: MediaMetadata2?): Unit

Sets a list of MediaItem2 to the MediaPlaylistAgent. Ensure uniqueness of each MediaItem2 in the playlist so the session can uniquely identity individual items.

This may be an asynchronous call, and MediaPlaylistAgent may keep the copy of the list. Wait for SessionCallback#onPlaylistChanged(MediaSession2, MediaPlaylistAgent, * List, MediaMetadata2) to know the operation finishes.

You may specify a MediaItem2 without DataSourceDesc2. In that case, MediaPlaylistAgent has responsibility to dynamically query {link DataSourceDesc2} when such media item is ready for preparation or play. Default implementation needs OnDataSourceMissingHelper for such case.

It's recommended to fill MediaMetadata2 in each MediaItem2 especially for the duration information with the key MediaMetadata2#METADATA_KEY_DURATION. Without the duration information in the metadata, session will do extra work to get the duration and send it to the controller.

Parameters
list MutableList<MediaItem2!>: A list of MediaItem2 objects to set as a play list.
Exceptions
IllegalArgumentException if given list is null, or has duplicated media items.

getPlaybackSpeed

open fun getPlaybackSpeed(): Float

Get the playback speed.

Return
Float: speed

setShuffleMode

open fun setShuffleMode(shuffleMode: Int): Unit

Sets the shuffle mode to the MediaPlaylistAgent.

Parameters
shuffleMode Int: The shuffle mode

getBufferedPosition

open fun getBufferedPosition(): Long

Gets the buffered position, or MediaPlayerConnector#UNKNOWN_TIME if unknown.

Return
Long: the buffered position in ms, or MediaPlayerConnector#UNKNOWN_TIME.

notifyError

open fun notifyError(errorCode: Int, @Nullable extras: Bundle?): Unit

Notify errors to the connected controllers

Parameters
errorCode Int: error code
extras Int: extras

replacePlaylistItem

open fun replacePlaylistItem(index: Int, @NonNull item: MediaItem2): Unit

Replaces the media item at index in the playlist. This can be also used to update metadata of an item.

Parameters
index Int: the index of the item to replace
item Int: the new item

getPlayerConnector

@Nullable open fun getPlayerConnector(): MediaPlayerConnector?
Return
MediaPlayerConnector?: player. Can be null if and only if the session is released.

setOnDataSourceMissingHelper

open fun setOnDataSourceMissingHelper(@NonNull helper: MediaSession2.OnDataSourceMissingHelper): Unit

Sets the data source missing helper. Helper will be used to provide default implementation of MediaPlaylistAgent when it isn't set by developer.

Default implementation of the MediaPlaylistAgent will call helper when a MediaItem2 in the playlist doesn't have a DataSourceDesc2. This may happen when

If it's not set, playback wouldn't happen for the item without data source descriptor.

The helper will be run on the executor that was specified by Builder#setSessionCallback(Executor, SessionCallback).

Parameters
helper MediaSession2.OnDataSourceMissingHelper: a data source missing helper.
Exceptions
IllegalStateException when the helper is set when the playlist agent is set

addPlaylistItem

open fun addPlaylistItem(index: Int, @NonNull item: MediaItem2): Unit

Adds the media item to the playlist at position index. Index equals or greater than the current playlist size (e.g. Integer#MAX_VALUE) will add the item at the end of the playlist.

This will not change the currently playing media item. If index is less than or equal to the current index of the play list, the current index of the play list will be incremented correspondingly.

Parameters
index Int: the index you want to add
item Int: the media item you want to add

seekTo

open fun seekTo(pos: Long): Unit

Move to a new location in the media stream.

Parameters
pos Long: Position to move to, in milliseconds.

getToken

@NonNull open fun getToken(): SessionToken2

Returns the SessionToken2 for creating MediaController2.

getBufferingState

open fun getBufferingState(): Int

Gets the current buffering state of the player. During buffering, see getBufferedPosition() for the quantifying the amount already buffered.

Return
Int: the buffering state.

removePlaylistItem

open fun removePlaylistItem(@NonNull item: MediaItem2): Unit

Removes the media item in the playlist.

If the item is the currently playing item of the playlist, current playback will be stopped and playback moves to next source in the list.

Parameters
item MediaItem2: the media item you want to add

setRepeatMode

open fun setRepeatMode(repeatMode: Int): Unit

Sets the repeat mode to the MediaPlaylistAgent.

Parameters
repeatMode Int: repeat mode

getConnectedControllers

@NonNull open fun getConnectedControllers(): MutableList<MediaSession2.ControllerInfo!>

Returns the list of connected controller.

Return
MutableList<MediaSession2.ControllerInfo!>: list of ControllerInfo

reset

open fun reset(): Unit

Stop playback, and reset the player to the initial state.

This calls MediaPlayerConnector#reset().

notifyRoutesInfoChanged

open fun notifyRoutesInfoChanged(@NonNull controller: MediaSession2.ControllerInfo, @Nullable routes: MutableList<Bundle!>?): Unit

Notify routes information to a connected controller

Parameters
controller MediaSession2.ControllerInfo: controller information
routes MediaSession2.ControllerInfo: The routes information

skipToPlaylistItem

open fun skipToPlaylistItem(@NonNull item: MediaItem2): Unit

Skips to the item in the playlist.

This calls MediaPlaylistAgent#skipToPlaylistItem(MediaItem2) and the behavior depends on the playlist agent implementation, especially with the shuffle/repeat mode.

Parameters
item MediaItem2: The item in the playlist you want to play

prepare

open fun prepare(): Unit

Request that the player prepare its playback. In other words, other sessions can continue to play during the preparation of this session. This method can be used to speed up the start of the playback. Once the preparation is done, the session will change its playback state to MediaPlayerConnector#PLAYER_STATE_PAUSED. Afterwards, play can be called to start playback.

This calls MediaPlayerConnector#reset().

pause

open fun pause(): Unit

Pause playback.

This calls MediaPlayerConnector#pause().

getPlaylistMetadata

open fun getPlaylistMetadata(): MediaMetadata2!

Gets the playlist metadata from the MediaPlaylistAgent.

Return
MediaMetadata2!: the playlist metadata

updatePlayerConnector

open fun updatePlayerConnector(@NonNull player: MediaPlayerConnector, @Nullable playlistAgent: MediaPlaylistAgent?): Unit

Sets the underlying MediaPlayerConnector and MediaPlaylistAgent for this session to dispatch incoming event to.

When a MediaPlaylistAgent is specified here, the playlist agent should manage MediaPlayerConnector for calling MediaPlayerConnector#setNextDataSources(List).

If the MediaPlaylistAgent isn't set, session will recreate the default playlist agent.

Parameters
player MediaPlayerConnector: a MediaPlayerConnector that handles actual media playback in your app
playlistAgent MediaPlayerConnector: a MediaPlaylistAgent that manages playlist of the player

skipToPreviousItem

open fun skipToPreviousItem(): Unit

Skips to the previous item.

This calls MediaPlaylistAgent#skipToPreviousItem() and the behavior depends on the playlist agent implementation, especially with the shuffle/repeat mode.

clearOnDataSourceMissingHelper

open fun clearOnDataSourceMissingHelper(): Unit

Clears the data source missing helper.

sendCustomCommand

open fun sendCustomCommand(@NonNull command: SessionCommand2, @Nullable args: Bundle?): Unit

Send custom command to all connected controllers.

Parameters
command SessionCommand2: a command
args SessionCommand2: optional argument

sendCustomCommand

open fun sendCustomCommand(@NonNull controller: MediaSession2.ControllerInfo, @NonNull command: SessionCommand2, @Nullable args: Bundle?, @Nullable receiver: ResultReceiver?): Unit

Send custom command to a specific controller.

Parameters
command MediaSession2.ControllerInfo: a command
args MediaSession2.ControllerInfo: optional argument
receiver MediaSession2.ControllerInfo: result receiver for the session

setCustomLayout

open fun setCustomLayout(@NonNull controller: MediaSession2.ControllerInfo, @NonNull layout: MutableList<MediaSession2.CommandButton!>): Unit

Sets ordered list of CommandButton for controllers to build UI with it.

It's up to controller's decision how to represent the layout in its own UI. Here's the same way (layout[i] means a CommandButton at index i in the given list) For 5 icons row layout[3] layout[1] layout[0] layout[2] layout[4] For 3 icons row layout[1] layout[0] layout[2] For 5 icons row with overflow icon (can show +5 extra buttons with overflow button) expanded row: layout[5] layout[6] layout[7] layout[8] layout[9] main row: layout[3] layout[1] layout[0] layout[2] layout[4]

This API can be called in the SessionCallback#onConnect(MediaSession2, ControllerInfo).

Parameters
controller MediaSession2.ControllerInfo: controller to specify layout.
layout MediaSession2.ControllerInfo: ordered list of layout.