Google is committed to advancing racial equity for Black communities. See how.

MediaController

open class MediaController : Closeable
kotlin.Any
   ↳ androidx.media2.session.MediaController

Allows an app to interact with an active or a MediaSessionService which would provide . Media buttons and other commands can be sent to the session.

MediaController objects are thread-safe.

Topics covered here:

  1. Controller Lifecycle
  2. Controlling the MediaSession in the same process

Controller Lifecycle

When a controller is created with the SessionToken for a MediaSession (i.e. session token type is SessionToken#TYPE_SESSION), the controller will connect to the specific session.

When a controller is created with the SessionToken for a MediaSessionService (i.e. session token type is SessionToken#TYPE_SESSION_SERVICE or SessionToken#TYPE_LIBRARY_SERVICE), the controller binds to the service for connecting to a MediaSession in it. MediaSessionService will provide a session to connect.

When a controller connects to a session, MediaSession.SessionCallback#onConnect(MediaSession, MediaSession.ControllerInfo) will be called to either accept or reject the connection. Wait ControllerCallback#onConnected(MediaController, SessionCommandGroup) or ControllerCallback#onDisconnected(MediaController) for the result.

When the connected session is closed, the controller will receive ControllerCallback#onDisconnected(MediaController).

When you're done, use #close() to clean up resources. This also helps session service to be destroyed when there's no controller associated with it.

Controlling the MediaSession in the same process

When you control the MediaSession and its SessionPlayer, it's recommended to use them directly rather than creating MediaController. However, if you need to use MediaController in the same process, be careful not to block session callback executor's thread. Here's an example code that would never return due to the thread issue.

<code>// Code runs on the main thread.
  MediaSession session = new MediaSession.Builder(context, player)
     .setSessionCallback(sessionCallback, Context.getMainExecutor(context)).build();
  MediaController controller = new MediaController.Builder(context)
     .setSessionToken(session.getToken())
     .setControllerCallback(Context.getMainExecutor(context), controllerCallback)
     .build();
 
  // This will hang and never return.
  controller.play().get();</code>
When a session gets a command from a controller, the session's MediaSession.SessionCallback#onCommandRequest would be executed on the session's callback executor to decide whether to ignore or handle the incoming command. To do so, the session's callback executor shouldn't be blocked to handle the incoming calls. However, if you call ListenableFuture#get on the thread for the session callback executor, then your call wouldn't be executed and never return.

To avoid such issue, don't block the session callback executor's thread. Creating a dedicated thread for the session callback executor would be helpful. See Executors#newSingleThreadExecutor for creating a new thread.

Summary

Nested classes

Builder for MediaController.

abstract

Interface for listening to change in activeness of the MediaSession.

Holds information about the way volume is handled for this session.

Public methods
open ListenableFuture<SessionResult!>
addPlaylistItem(@IntRange(0) index: Int, @NonNull mediaId: String)

Requests that the SessionPlayer associated with the connected MediaSession adds the media item to the playlist at the index with the media ID.

open ListenableFuture<SessionResult!>
adjustVolume(direction: Int, flags: Int)

Requests that the connected MediaSession adjusts the volume of the output that is playing on.

open Unit

Releases this object, and disconnects from the session.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession deselects the TrackInfo for the current media item.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession to fast forward playback.

open SessionCommandGroup?

Gets the cached allowed commands from ControllerCallback#onAllowedCommandsChanged.

open Long

Gets the position for how much has been buffered of the SessionPlayer associated with the connected MediaSession, or SessionPlayer#UNKNOWN_TIME if unknown or not connected.

open Int

Gets the current buffering state of the SessionPlayer associated with the connected MediaSession.

open SessionToken?

Returns the SessionToken of the connected session.

open MediaItem?

Gets the current media item of the SessionPlayer associated with the connected MediaSession.

open Int

Gets the current item index in the playlist of the SessionPlayer associated with the connected MediaSession.

open Long

Gets the playback position of the SessionPlayer associated with the connected MediaSession.

open Long

Gets the duration of the current media item, or SessionPlayer#UNKNOWN_TIME if unknown or not connected.

open Int

Gets the next item index in the playlist of the SessionPlayer associated with the connected MediaSession.

open MediaController.PlaybackInfo?

Get the current playback info for this session.

open Float

Gets the playback speed to be used by the of the SessionPlayer associated with the connected MediaSession when playing.

open Int

Gets the state of the SessionPlayer associated with the connected MediaSession.

open MutableList<MediaItem!>?

Gets the playlist of the SessionPlayer associated with the connected MediaSession.

open MediaMetadata?

Gets the playlist metadata of the SessionPlayer associated with the connected MediaSession.

open Int

Gets the previous item index in the playlist of the SessionPlayer associated with the connected MediaSession.

open Int

Gets the repeat mode of the SessionPlayer associated with the connected MediaSession.

open SessionPlayer.TrackInfo?
getSelectedTrack(trackType: Int)

Gets the currently selected track for the given track type of the SessionPlayer associated with the connected MediaSession.

open PendingIntent?

Gets an intent for launching UI associated with this session if one exists.

open Int

Gets the shuffle mode of the SessionPlayer associated with the connected MediaSession.

open MutableList<SessionPlayer.TrackInfo!>

Gets the full list of selected and unselected tracks that the media contains of the SessionPlayer associated with the connected MediaSession.

open VideoSize

Gets the video size of the SessionPlayer associated with the connected MediaSession.

open Boolean

Returns whether this class is connected to active MediaSession or not.

open ListenableFuture<SessionResult!>
movePlaylistItem(@IntRange(0) fromIndex: Int, @IntRange(0) toIndex: Int)

Requests that the SessionPlayer associated with the connected MediaSession moves the media item at fromIdx to toIdx in the playlist.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession pauses playback.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession starts or resumes playback.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession prepares the media items for playback.

open ListenableFuture<SessionResult!>
removePlaylistItem(@IntRange(0) index: Int)

Requests that the SessionPlayer associated with the connected MediaSession removes the media item at index in the playlist.

open ListenableFuture<SessionResult!>
replacePlaylistItem(@IntRange(0) index: Int, @NonNull mediaId: String)

Requests that the SessionPlayer associated with the connected MediaSession replaces the media item at index in the playlist with the media ID.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession to rewind playback.

open ListenableFuture<SessionResult!>
seekTo(position: Long)

Requests that the SessionPlayer associated with the connected MediaSession seeks to the specified position.

open ListenableFuture<SessionResult!>
selectTrack(@NonNull trackInfo: SessionPlayer.TrackInfo)

Requests that the SessionPlayer associated with the connected MediaSession selects the TrackInfo for the current media item.

open ListenableFuture<SessionResult!>
sendCustomCommand(@NonNull command: SessionCommand, @Nullable args: Bundle?)

Sends a custom command to the session

open ListenableFuture<SessionResult!>
setMediaItem(@NonNull mediaId: String)

Requests that the SessionPlayer associated with the connected MediaSession sets a MediaItem for playback.

open ListenableFuture<SessionResult!>
setMediaUri(@NonNull uri: Uri, @Nullable extras: Bundle?)

Requests that the connected MediaSession sets a specific Uri for playback.

open ListenableFuture<SessionResult!>
setPlaybackSpeed(playbackSpeed: Float)

Requests that the SessionPlayer associated with the connected MediaSession sets the playback speed.

open ListenableFuture<SessionResult!>
setPlaylist(@NonNull list: MutableList<String!>, @Nullable metadata: MediaMetadata?)

Requests that the SessionPlayer associated with the connected MediaSession sets the playlist with the list of media IDs.

open ListenableFuture<SessionResult!>
setRating(@NonNull mediaId: String, @NonNull rating: Rating)

Requests that the connected MediaSession rates the media.

open ListenableFuture<SessionResult!>
setRepeatMode(repeatMode: Int)

Requests that the SessionPlayer associated with the connected MediaSession sets the repeat mode.

open ListenableFuture<SessionResult!>
setShuffleMode(shuffleMode: Int)

Requests that the SessionPlayer associated with the connected MediaSession sets the shuffle mode.

open ListenableFuture<SessionResult!>
setSurface(@Nullable surface: Surface?)

Requests that the SessionPlayer associated with the connected MediaSession sets the Surface to be used as the sink for the video portion of the media.

open ListenableFuture<SessionResult!>
setVolumeTo(value: Int, flags: Int)

Requests that the connected MediaSession sets the volume of the output that is playing on.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession skips forward within the current media item.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession skips backward within the current media item.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession skips to the next item in the playlist.

open ListenableFuture<SessionResult!>
skipToPlaylistItem(@IntRange(0) index: Int)

Requests that the SessionPlayer associated with the connected MediaSession skips to the item in the playlist at the index.

open ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession skips to the previous item in the playlist.

open ListenableFuture<SessionResult!>
updatePlaylistMetadata(@Nullable metadata: MediaMetadata?)

Requests that the SessionPlayer associated with the connected MediaSession updates the playlist metadata while keeping the playlist as-is.

Public methods

addPlaylistItem

@NonNull open fun addPlaylistItem(
    @IntRange(0) index: Int,
    @NonNull mediaId: String
): ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession adds the media item to the playlist at the index with the media ID. Index equals to or greater than the current playlist size (e.g. Integer#MAX_VALUE) will add the item at the end of the playlist.

If index is less than or equal to the current index of the playlist, the current index of the playlist will be increased correspondingly.

On success, a SessionResult would be returned with item added.

Parameters
index Int: the index you want to add
mediaId String: the non-empty media id of the new item

adjustVolume

@NonNull open fun adjustVolume(
    direction: Int,
    flags: Int
): ListenableFuture<SessionResult!>

Requests that the connected MediaSession adjusts the volume of the output that is playing on. The direction must be one of AudioManager#ADJUST_LOWER, AudioManager#ADJUST_RAISE, or AudioManager#ADJUST_SAME.

The command will be ignored if the session does not support VolumeProviderCompat#VOLUME_CONTROL_RELATIVE or VolumeProviderCompat#VOLUME_CONTROL_ABSOLUTE.

If the session is local playback, this changes the device's volume with the stream that session's player is using. Flags will be specified for the AudioManager.

If the session is remote player (i.e. session has set volume provider), its volume provider will receive this request instead.

Parameters
direction Int: the direction to adjust the volume in
flags Int: flags from AudioManager to include with the volume request for local playback
Return
ListenableFuture<SessionResult!> a ListenableFuture representing the pending completion of the command

close

open fun close(): Unit

Releases this object, and disconnects from the session. After this, callbacks wouldn't be received.

deselectTrack

@NonNull open fun deselectTrack(@NonNull trackInfo: SessionPlayer.TrackInfo): ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession deselects the TrackInfo for the current media item.

Generally, a track should already be selected in order to be deselected and audio and video tracks should not be deselected.

The types of tracks supported may vary based on players.

Note: getSelectedTrack(int) returns the currently selected track per track type that can be deselected, but the list may be invalidated when ControllerCallback#onTracksChanged(MediaController, List) is called.

Parameters
trackInfo SessionPlayer.TrackInfo: track to be deselected
Return
ListenableFuture<SessionResult!> a ListenableFuture which represents the pending completion of the command

fastForward

@NonNull open fun fastForward(): ListenableFuture<SessionResult!>

Requests that the SessionPlayer associated with the connected MediaSession to fast forward playback.

The implementation may be different depending on the players. For example, it can be implemented by seeking forward once, series of seeking forward, or increasing playback speed. If you need full control, then use seekTo or setPlaybackSpeed directly.

Return
ListenableFuture<SessionResult!> a ListenableFuture representing the pending completion of the command

getAllowedCommands

@Nullable open fun getAllowedCommands(): SessionCommandGroup?

Gets the cached allowed commands from ControllerCallback#onAllowedCommandsChanged. If it is not connected yet, it returns null.

Return
SessionCommandGroup? the allowed commands

getBufferedPosition

open fun getBufferedPosition(): Long

Gets the position for how much has been buffered of the SessionPlayer associated with the connected MediaSession, or SessionPlayer#UNKNOWN_TIME if unknown or not connected.

Return
Long buffering position in ms, or SessionPlayer#UNKNOWN_TIME if unknown or not connected

getBufferingState

open fun getBufferingState(): Int

Gets the current buffering state of the SessionPlayer associated with the connected MediaSession.

The position is the relative position based on the MediaItem#getStartPosition(). So the position 0 means the start position of the MediaItem.

Return
Int the buffering state, or SessionPlayer#BUFFERING_STATE_UNKNOWN if unknown or not connected

getConnectedToken

@Nullable open fun getConnectedToken(): SessionToken?

Returns the SessionToken of the connected session. If it is not connected yet, it returns null.

This may differ from the SessionToken from the constructor. For example, if the controller is created with the token for MediaSessionService, this would return token for the MediaSession in the service.

Return
SessionToken? SessionToken of the connected session, or null if not connected

getCurrentMediaItem

@Nullable open fun getCurrentMediaItem(): MediaItem?

Gets the current media item of the SessionPlayer associated with the connected MediaSession. This can be currently playing or would be played with later play. This value may be updated when ControllerCallback#onCurrentMediaItemChanged(MediaController, MediaItem) or