# MediaSession.Callback

Artifact: [androidx.media3:media3-session](https://developer.android.com/jetpack/androidx/releases/media3) [View Source](https://cs.android.com/search?q=file:androidx/media3/session/MediaSession.java+class:androidx.media3.session.MediaSession.Callback)

*** ** * ** ***


```
interface MediaSession.Callback
```

<br />

Known direct subclasses [MediaLibraryService.MediaLibrarySession.Callback](https://developer.android.com/reference/kotlin/androidx/media3/session/MediaLibraryService.MediaLibrarySession.Callback)

|---|---|
| `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaLibraryService.MediaLibrarySession.Callback` | An extended `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback` for the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaLibraryService.MediaLibrarySession`. |

*** ** * ** ***

A callback to handle incoming commands from `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController`.

The callback methods will be called from the application thread associated with the `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#getApplicationLooper()` of the underlying `https://developer.android.com/reference/kotlin/androidx/media3/common/Player`.

If it's not set by `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Builder#setCallback(androidx.media3.session.MediaSession.Callback)`, the session will accept all controllers and all incoming commands by default.

## Summary

| ### Public functions |
|---|---|
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<(https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-mutable-list/index.html)https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-list/index.html<https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem!>!>!` | `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onAddMediaItems(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.common.MediaItem>)( mediaSession: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, mediaItems: (https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-mutable-list/index.html)https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-list/index.html<https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem!>! )` Called when a controller requested to add new `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` to the playlist via one of the `Player.addMediaItem(s)` methods. |
| `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult!` | `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnect(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)(session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!)` It's strongly recommended to override `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnectAsync(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` instead of this method. |
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult!>!` | `@https://developer.android.com/reference/kotlin/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnectAsync(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo! )` Called when a controller is about to connect to this session. |
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult!>!` | `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onCustomCommand(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, customCommand: https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand!, args: https://developer.android.com/reference/android/os/Bundle.html! )` Called when a controller sent a custom command through `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController#sendCustomCommand(androidx.media3.session.SessionCommand,android.os.Bundle)`. |
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult!>!` | `@https://developer.android.com/reference/kotlin/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onCustomCommand(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle,androidx.media3.session.MediaSession.ProgressReporter)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, customCommand: https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand!, args: https://developer.android.com/reference/android/os/Bundle.html!, progressReporter: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ProgressReporter? )` Called when a controller sent a custom command through `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController#sendCustomCommand(androidx.media3.session.SessionCommand,android.os.Bundle,androidx.media3.session.MediaController.ProgressListener)`. |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onDisconnected(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo! )` Called when a controller is disconnected. |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | `@https://developer.android.com/reference/kotlin/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onMediaButtonEvent(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,android.content.Intent)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controllerInfo: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, intent: https://developer.android.com/reference/android/content/Intent.html! )` Called when a media button event has been received by the session. |
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition!>!` | `@https://developer.android.com/reference/kotlin/androidx/media3/common/util/UnstableApi [onPlaybackResumption](https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPlaybackResumption(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo))( mediaSession: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo! )` **This function is deprecated.** Override `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPlaybackResumption(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,boolean)` instead. <br /> |
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition!>!` | `@https://developer.android.com/reference/kotlin/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPlaybackResumption(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,boolean)( mediaSession: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, isForPlayback: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html )` Returns the playlist with which the player should be prepared when a controller requests to play without a current `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem`. |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | `@https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult.Code [onPlayerCommandRequest](https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPlayerCommandRequest(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,int))( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, @https://developer.android.com/reference/kotlin/androidx/media3/common/Player.Command playerCommand: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html )` **This function is deprecated.** Modify the `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#getAvailableCommands()` of the player or use `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommands,androidx.media3.common.Player.Commands)` instead. <br /> |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `@https://developer.android.com/reference/kotlin/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPlayerInteractionFinished(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.common.Player.Commands)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controllerInfo: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, playerCommands: https://developer.android.com/reference/kotlin/androidx/media3/common/Player.Commands! )` Called after all concurrent interactions with `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#getPlayer()` from a controller have finished. |
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-unit/index.html` | `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPostConnect(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo! )` Called immediately after a controller is connected. |
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition!>!` | `@https://developer.android.com/reference/kotlin/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onSetMediaItems(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.common.MediaItem>,int,long)( mediaSession: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, mediaItems: (https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-mutable-list/index.html)https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-list/index.html<https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem!>!, startIndex: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html, startPositionMs: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html )` Called when a controller requested to set `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` to the playlist via one of the `Player.setMediaItem(s)` methods. |
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult!>!` | `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onSetRating(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.common.Rating)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, rating: https://developer.android.com/reference/kotlin/androidx/media3/common/Rating! )` Called when a controller requested to set a rating for the current media item for the current user by `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController#setRating(androidx.media3.common.Rating)`. |
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult!>!` | `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onSetRating(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,java.lang.String,androidx.media3.common.Rating)( session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!, controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!, mediaId: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/index.html!, rating: https://developer.android.com/reference/kotlin/androidx/media3/common/Rating! )` Called when a controller requested to set a rating to a media for the current user by `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController#setRating(java.lang.String,androidx.media3.common.Rating)`. |

## Public functions

### onAddMediaItems

```
fun onAddMediaItems(
    mediaSession: MediaSession!,
    controller: MediaSession.ControllerInfo!,
    mediaItems: (Mutable)List<MediaItem!>!
): ListenableFuture<(Mutable)List<MediaItem!>!>!
```

Called when a controller requested to add new `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` to the playlist via one of the `Player.addMediaItem(s)` methods. Unless overridden, `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onSetMediaItems(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.common.MediaItem>,int,long)` will direct `Player.setMediaItem(s)` to this method as well.

In addition, unless `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onSetMediaItems(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.common.MediaItem>,int,long)` is overridden, this callback is also called when an app is using a legacy `https://developer.android.com/reference/kotlin/android/support/v4/media/session/MediaControllerCompat.TransportControls` to prepare or play media (for instance when browsing the catalogue and then selecting an item for preparation from Android Auto that is using the legacy Media1 library).

By default, if and only if each of the provided `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` has a set `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.LocalConfiguration` (for example, a URI), then the callback returns the list unaltered. Otherwise, the default implementation returns an `https://developer.android.com/reference/java/lang/UnsupportedOperationException.html`.

If the requested `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` don't have a `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.LocalConfiguration`, they need to be updated to make them playable by the underlying `https://developer.android.com/reference/kotlin/androidx/media3/common/Player`. Typically, this callback would be overridden with implementation that identifies the correct item by its `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem#mediaId()` and/or the `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem#requestMetadata()`.

Return a `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` with the resolved `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem`. You can also return the items directly by using Guava's `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/Futures.html#immediateFuture(V)`. Once the `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` have been resolved, the session will call `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItems(java.util.List<androidx.media3.common.MediaItem>)` or `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#addMediaItems(java.util.List<androidx.media3.common.MediaItem>)` as requested.

Interoperability: This method will be called, unless `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onSetMediaItems(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.common.MediaItem>,int,long)` is overridden, in response to the following `https://developer.android.com/reference/kotlin/android/support/v4/media/session/MediaControllerCompat` methods:

- `prepareFromUri`
- `playFromUri`
- `prepareFromMediaId`
- `playFromMediaId`
- `prepareFromSearch`
- `playFromSearch`
- `addQueueItem`

The values of `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem#mediaId()`, `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.RequestMetadata#mediaUri()`, `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.RequestMetadata#searchQuery()` and `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.RequestMetadata#extras()` will be set to match the legacy method call. The session will call `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItems(java.util.List<androidx.media3.common.MediaItem>)` or `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#addMediaItems(java.util.List<androidx.media3.common.MediaItem>)`, followed by `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#prepare()` and `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#play()` as appropriate once the `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` has been resolved.

| Parameters |
|---|---|
| `mediaSession: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |
| `mediaItems: (https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-mutable-list/index.html)https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-list/index.html<https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem!>!` | The list of requested `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem`. |

| Returns |
|---|---|
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<(https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-mutable-list/index.html)https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-list/index.html<https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem!>!>!` | A `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` for the list of resolved `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` that are playable by the underlying `https://developer.android.com/reference/kotlin/androidx/media3/common/Player`. |

### onConnect

```
fun onConnect(session: MediaSession!, controller: MediaSession.ControllerInfo!): MediaSession.ConnectionResult!
```

It's strongly recommended to override `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnectAsync(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` instead of this method. This method will be deprecated as soon as the `@UnstableApi` annotation is removed.

Called when a controller is about to connect to this session.

If this callback is not overridden, it allows all controllers to connect. If the controller is `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo#isTrusted()`, all session and player commands are made available. Untrusted controllers obtain read access only.

Return a `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult` for the controller by using `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult#accept(androidx.media3.session.SessionCommands,androidx.media3.common.Player.Commands)` or the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult.AcceptedResultBuilder`.

You can use `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo#isTrusted()` to filter by system apps, apps with media control permissions, and your own app.

Note that the player commands in `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult#availablePlayerCommands()` will be intersected with the `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#getAvailableCommands()` of the underlying `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` and the controller will only be able to call the commonly available commands.

Returning `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult#reject()` rejects the connection. In that case, the controller will get `https://developer.android.com/reference/java/lang/SecurityException.html` when resolving the `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` returned by `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController.Builder#buildAsync()`.

The controller isn't connected yet, so calls to the controller (e.g. `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle)`, `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#setMediaButtonPreferences(androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.session.CommandButton>)`) will be ignored. Use `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPostConnect(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` for custom initialization of the controller instead.

Interoperability: If a `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo#LEGACY_CONTROLLER_VERSION()` is connecting to the session then this callback may block the main thread, even if it's called on a different application thread. If it's possible that platform or legacy controllers will connect to the session, you should ensure that the callback returns quickly to avoid blocking the main thread for a long period of time.

Custom layouts, media button preferences, session extras, and session activities returned in the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult` for a platform or legacy controller are ignored by the platform session. To configure initial commands, media button preferences, or custom actions for the shared platform session, configure the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult` returned when `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#getMediaNotificationControllerInfo()` connects. When the notification controller is connected, System UI does not invoke this callback and automatically adopts the platform session configuration.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |

| Returns |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult!` | A `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` of the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult`. |

### onConnectAsync

```
@UnstableApi
fun onConnectAsync(
    session: MediaSession!,
    controller: MediaSession.ControllerInfo!
): ListenableFuture<MediaSession.ConnectionResult!>!
```

Called when a controller is about to connect to this session.

If this callback is not overridden, it allows all controllers to connect. If the controller is `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo#isTrusted()`, all session and player commands are made available. Untrusted controllers obtain read access only.

Return a `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult` for the controller by using `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult#accept(androidx.media3.session.SessionCommands,androidx.media3.common.Player.Commands)` or the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult.AcceptedResultBuilder`.

Return a `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` to send a `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult` back to the controller asynchronously. You can also return a `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult` wrapped in an immediate future by using `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/Futures.html#immediateFuture(V)` which results in a blocking and immediate execution.

If both `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnect(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` and this method are overridden, the deprecated `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnect(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` takes precedence for backward compatibility.

You can use `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo#isTrusted()` to filter by system apps, apps with media control permissions, and your own app.

Note that the player commands in `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult#availablePlayerCommands()` will be intersected with the `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#getAvailableCommands()` of the underlying `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` and the controller will only be able to call the commonly available commands.

Returning `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult#reject()` rejects the connection. In that case, the controller will get `https://developer.android.com/reference/java/lang/SecurityException.html` when resolving the `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` returned by `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController.Builder#buildAsync()`.

The controller isn't connected yet, so calls to the controller (e.g. `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle)`, `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#setMediaButtonPreferences(androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.session.CommandButton>)`) will be ignored. Use `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPostConnect(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` for custom initialization of the controller instead.

Interoperability: If a `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo#LEGACY_CONTROLLER_VERSION()` is connecting to the session then this callback may block the main thread, even if it's called on a different application thread. If it's possible that platform or legacy controllers will connect to the session, you should ensure that the callback returns quickly to avoid blocking the main thread for a long period of time. In particular, the returned future must not be completed on or by posting to the application thread (or main thread), as this will cause a deadlock while the thread is blocked.

Custom layouts, media button preferences, session extras, and session activities returned in the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult` for a platform or legacy controller are ignored by the platform session. To configure initial commands, media button preferences, or custom actions for the shared platform session, configure the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult` returned when `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#getMediaNotificationControllerInfo()` connects. When the notification controller is connected, System UI does not invoke this callback and automatically adopts the platform session configuration.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |

| Returns |
|---|---|
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult!>!` | A `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` of the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult`. |

### onCustomCommand

```
fun onCustomCommand(
    session: MediaSession!,
    controller: MediaSession.ControllerInfo!,
    customCommand: SessionCommand!,
    args: Bundle!
): ListenableFuture<SessionResult!>!
```

Called when a controller sent a custom command through `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController#sendCustomCommand(androidx.media3.session.SessionCommand,android.os.Bundle)`.

Note: By default `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onCustomCommand(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle,androidx.media3.session.MediaSession.ProgressReporter)` delegates all calls to this method and drops the option to send progress updates. If you want to implement progress updates you should override `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onCustomCommand(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle,androidx.media3.session.MediaSession.ProgressReporter)` instead to get access to the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ProgressReporter` in case a controller requests progress updates.

`https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController` instances are only allowed to send a command if the command has been added to the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult#availableSessionCommands()` in `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnectAsync(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` or set via `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommands,androidx.media3.common.Player.Commands)`.

Interoperability: This will also be called when custom action buttons in the media notification or on Android Auto / Automotive OS are clicked, or when legacy controller APIs are used (such as `MediaControllerCompat.TransportControls#sendCustomAction(String,
Bundle)`, `MediaControllerCompat#sendCommand(String, Bundle, ResultReceiver)`, or `android.support.v4.media.MediaBrowserCompat#sendCustomAction(String, Bundle,
CustomActionCallback)`). If the controller connects as a platform or legacy controller (note that the media notification, Android Auto, and Automotive OS may connect as either platform or Media3 controllers), the incoming extras will be considered as `args` and the custom command will have empty `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand#customExtras()`.

Return a `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` to send a `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult` back to the controller asynchronously. You can also return a `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult` directly by using Guava's `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/Futures.html#immediateFuture(V)`.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |
| `customCommand: https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand!` | The custom command. |
| `args: https://developer.android.com/reference/android/os/Bundle.html!` | A `https://developer.android.com/reference/android/os/Bundle.html` for additional arguments. May be empty. |

| Returns |
|---|---|
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult!>!` | The result of handling the custom command. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand#COMMAND_CODE_CUSTOM()` |   |

### onCustomCommand

```
@UnstableApi
fun onCustomCommand(
    session: MediaSession!,
    controller: MediaSession.ControllerInfo!,
    customCommand: SessionCommand!,
    args: Bundle!,
    progressReporter: MediaSession.ProgressReporter?
): ListenableFuture<SessionResult!>!
```

Called when a controller sent a custom command through `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController#sendCustomCommand(androidx.media3.session.SessionCommand,android.os.Bundle,androidx.media3.session.MediaController.ProgressListener)`.

By default this callback delegates to `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onCustomCommand(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle)`. If this method is overridden, the callback `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onCustomCommand(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle)` is never called.

If a non-null `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ProgressReporter` is passed in, then the session can report progress updates to the controller. It's the decision of the session whether or not to send progress updates. In any case, the transaction ends by completing the `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` returned by this method.

`https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController` instances are only allowed to send a command if the command has been added to the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ConnectionResult#availableSessionCommands()` in `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnectAsync(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` or set via `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommands,androidx.media3.common.Player.Commands)`.

Interoperability: This will also be called when custom action buttons in the media notification or on Android Auto / Automotive OS are clicked, or when legacy controller APIs are used (such as `MediaControllerCompat.TransportControls#sendCustomAction(String,
Bundle)`, `MediaControllerCompat#sendCommand(String, Bundle, ResultReceiver)`, or `android.support.v4.media.MediaBrowserCompat#sendCustomAction(String, Bundle,
CustomActionCallback)`). If the controller connects as a platform or legacy controller (note that the media notification, Android Auto, and Automotive OS may connect as either platform or Media3 controllers), the incoming extras will be considered as `args` and the custom command will have empty `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand#customExtras()`.

Return a `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` to send a `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult` back to the controller asynchronously. You can also return a `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult` directly by using Guava's `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/Futures.html#immediateFuture(V)`. Progress updates are dispatched only until the future has completed.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |
| `customCommand: https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand!` | The custom command. |
| `args: https://developer.android.com/reference/android/os/Bundle.html!` | A `https://developer.android.com/reference/android/os/Bundle.html` for additional arguments. May be empty. |
| `progressReporter: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ProgressReporter?` | A `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ProgressReporter` to send progress update until the future has completed. May be null if progress updates are not supported. |

| Returns |
|---|---|
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult!>!` | The result of handling the custom command. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand#COMMAND_CODE_CUSTOM()` |   |

### onDisconnected

```
fun onDisconnected(
    session: MediaSession!,
    controller: MediaSession.ControllerInfo!
): Unit
```

Called when a controller is disconnected.

Interoperability: For legacy controllers, this is called when the controller doesn't send any command for a while. It's because there were no explicit disconnection in legacy controller APIs.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |

### onMediaButtonEvent

```
@UnstableApi
fun onMediaButtonEvent(
    session: MediaSession!,
    controllerInfo: MediaSession.ControllerInfo!,
    intent: Intent!
): Boolean
```

Called when a media button event has been received by the session.

Media3 handles media button events internally. An app can override the default behaviour by overriding this method.

Return true to stop propagating the event any further. When false is returned, Media3 handles the event and calls `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#getPlayer()` accordingly.

Apps normally don't need to override this method. When overriding this method, an app can/needs to handle all API-level specifics on its own. The intent passed to this method can come directly from the system that routed a media key event (for instance sent by Bluetooth) to your session.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session that received the media button event. |
| `controllerInfo: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` to which the media button event is attributed to. |
| `intent: https://developer.android.com/reference/android/content/Intent.html!` | The media button intent. |

| Returns |
|---|---|
| `https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | True if the event was handled, false otherwise. |

### onPlaybackResumption

```
@UnstableApi
fun [onPlaybackResumption](https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPlaybackResumption(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo))(
    mediaSession: MediaSession!,
    controller: MediaSession.ControllerInfo!
): ListenableFuture<MediaSession.MediaItemsWithStartPosition!>!
```

> [!CAUTION]
> **This function is deprecated.**   
>
> Override `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPlaybackResumption(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,boolean)` instead.

### onPlaybackResumption

```
@UnstableApi
fun onPlaybackResumption(
    mediaSession: MediaSession!,
    controller: MediaSession.ControllerInfo!,
    isForPlayback: Boolean
): ListenableFuture<MediaSession.MediaItemsWithStartPosition!>!
```

Returns the playlist with which the player should be prepared when a controller requests to play without a current `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem`.

This happens, for example, if [playback resumption](https://developer.android.com/media/media3/session/background-playback#resumption) is requested from a media button receiver or the System UI notification.

If `isForPlayback` is `false`, the controller only requests metadata about the item that will be played once playback resumption is requested without an immediate intention to start playback. For example, this may happen immediately after reboot of the device for System UI to populate its playback resumption notification. In these cases, only one `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` is needed and it's useful to provide additional metadata to allow System UI to generate the notification:

- Use `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaMetadata#artworkData()` or `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaMetadata#artworkUri()` with a content URI to set locally available artwork data for the playback resumption notification. Note that network access may not be available when this method is called during boot time.
- Use `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaConstants#EXTRAS_KEY_COMPLETION_STATUS()` and `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaConstants#EXTRAS_KEY_COMPLETION_PERCENTAGE()` to statically indicate the completion status.

If `isForPlayback` is `true`, return the initial playlist for the `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` and the intended start position. `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItem(androidx.media3.common.MediaItem)`, `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItems(java.util.List<androidx.media3.common.MediaItem>)`, `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#prepare()` and `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#play()` will be called automatically as required. Any additional initial setup like setting playback speed, repeat mode or shuffle mode can be done from within this callback.

The method will only be called if the `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` has `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#COMMAND_GET_CURRENT_MEDIA_ITEM()` and either `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#COMMAND_SET_MEDIA_ITEM()` or `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#COMMAND_CHANGE_MEDIA_ITEMS()` available.

| Parameters |
|---|---|
| `mediaSession: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The media session for which playback resumption is requested. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` that requests the playback resumption. This may be a short living controller created only for issuing a play command for resuming playback. |
| `isForPlayback: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-boolean/index.html` | Whether playback is intended to start after this callback. If false, the controller only requests metadata about the item that will be played once playback resumption is requested. If true, playback will be started automatically with the provided `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition`. |

| Returns |
|---|---|
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition!>!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition` to resume playback with. |

### onPlayerCommandRequest

```
@SessionResult.Code
fun [onPlayerCommandRequest](https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onPlayerCommandRequest(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,int))(
    session: MediaSession!,
    controller: MediaSession.ControllerInfo!,
    @Player.Command playerCommand: Int
): Int
```

> [!CAUTION]
> **This function is deprecated.**   
>
> Modify the `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#getAvailableCommands()` of the player or use `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommands,androidx.media3.common.Player.Commands)` instead. The controller triggering a `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` method can be obtained via `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#getControllerForCurrentRequest()`.

Value is one of the following:

- `SessionError.INFO_CANCELLED`
- `SessionError.ERROR_UNKNOWN`
- `SessionError.ERROR_INVALID_STATE`
- `SessionError.ERROR_BAD_VALUE`
- `SessionError.ERROR_PERMISSION_DENIED`
- `SessionError.ERROR_IO`
- `SessionError.ERROR_SESSION_DISCONNECTED`
- `SessionError.ERROR_NOT_SUPPORTED`
- `SessionError.ERROR_SESSION_AUTHENTICATION_EXPIRED`
- `SessionError.ERROR_SESSION_PREMIUM_ACCOUNT_REQUIRED`
- `SessionError.ERROR_SESSION_CONCURRENT_STREAM_LIMIT`
- `SessionError.ERROR_SESSION_PARENTAL_CONTROL_RESTRICTED`
- `SessionError.ERROR_SESSION_NOT_AVAILABLE_IN_REGION`
- `SessionError.ERROR_SESSION_SKIP_LIMIT_REACHED`
- `SessionError.ERROR_SESSION_SETUP_REQUIRED`

<br />

### onPlayerInteractionFinished

```
@UnstableApi
fun onPlayerInteractionFinished(
    session: MediaSession!,
    controllerInfo: MediaSession.ControllerInfo!,
    playerCommands: Player.Commands!
): Unit
```

Called after all concurrent interactions with `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#getPlayer()` from a controller have finished.

A controller may call multiple `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` methods within a single `https://developer.android.com/reference/android/os/Looper.html` message. Those `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` method calls are batched together and once finished, this callback is called to signal that no further `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` interactions coming from this controller are expected for now.

Apps can use this callback if they need to trigger different logic depending on whether certain methods are called together, for example just `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItems(java.util.List<androidx.media3.common.MediaItem>)`, or `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItems(java.util.List<androidx.media3.common.MediaItem>)` and `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#play()` together.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession` that received the `https://developer.android.com/reference/kotlin/androidx/media3/common/Player` calls. |
| `controllerInfo: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` sending the calls. |
| `playerCommands: https://developer.android.com/reference/kotlin/androidx/media3/common/Player.Commands!` | The set of `https://developer.android.com/reference/kotlin/androidx/media3/common/Player.Commands` used to send these calls. |

### onPostConnect

```
fun onPostConnect(
    session: MediaSession!,
    controller: MediaSession.ControllerInfo!
): Unit
```

Called immediately after a controller is connected. This is for custom initialization of the controller.

Note that calls to the controller (e.g. `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle)`, `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession#setMediaButtonPreferences(androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.session.CommandButton>)`) work here but don't work in `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnectAsync(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)` because the controller isn't connected yet in `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onConnectAsync(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo)`.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |

### onSetMediaItems

```
@UnstableApi
fun onSetMediaItems(
    mediaSession: MediaSession!,
    controller: MediaSession.ControllerInfo!,
    mediaItems: (Mutable)List<MediaItem!>!,
    startIndex: Int,
    startPositionMs: Long
): ListenableFuture<MediaSession.MediaItemsWithStartPosition!>!
```

Called when a controller requested to set `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` to the playlist via one of the `Player.setMediaItem(s)` methods. The default implementation calls `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.Callback#onAddMediaItems(androidx.media3.session.MediaSession,androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.common.MediaItem>)`. Override this method if you want to modify/set the starting index/position for the `Player.setMediaItem(s)` methods.

This callback is also called when an app is using a legacy to prepare or play media (for instance when browsing the catalogue and then selecting an item for preparation from Android Auto that is using the legacy Media1 library).

By default, if and only if each of the provided `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` has a set `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.LocalConfiguration` (for example, a URI), then the callback returns the list unaltered. Otherwise, the default implementation returns an `https://developer.android.com/reference/java/lang/UnsupportedOperationException.html`.

If the requested `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` don't have a `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.LocalConfiguration`, they need to be updated to make them playable by the underlying `https://developer.android.com/reference/kotlin/androidx/media3/common/Player`. Typically, this callback would be overridden with implementation that identifies the correct item by its `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem#mediaId()` and/or the `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem#requestMetadata()`.

Return a `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` with the resolved `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition`. You can also return the items directly by using Guava's `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/Futures.html#immediateFuture(V)`. Once the `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition` has been resolved, the session will call `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItems(java.util.List<androidx.media3.common.MediaItem>)` as requested. If the resolved `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition#startIndex()` is `https://developer.android.com/reference/kotlin/androidx/media3/common/C#INDEX_UNSET()` then the session will call `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItem(androidx.media3.common.MediaItem,boolean)` with `
resetPosition` set to `true`.

Interoperability: This method will be called in response to the following methods:

- 
- 
- 
- 
- 
- 
- 

The values of `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem#mediaId()`, `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.RequestMetadata#mediaUri()`, `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.RequestMetadata#searchQuery()` and `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem.RequestMetadata#extras()` will be set to match the legacy method call. The session will call `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItems(java.util.List<androidx.media3.common.MediaItem>)` or `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#addMediaItems(java.util.List<androidx.media3.common.MediaItem>)`, followed by `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#prepare()` and `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#play()` as appropriate once the `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` has been resolved.

| Parameters |
|---|---|
| `mediaSession: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |
| `mediaItems: (https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-mutable-list/index.html)https://kotlinlang.org/api/core/kotlin-stdlib/kotlin.collections/-list/index.html<https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem!>!` | The list of requested `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem`. |
| `startIndex: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-int/index.html` | The start index in the `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem` list from which to start playing, or `https://developer.android.com/reference/kotlin/androidx/media3/common/C#INDEX_UNSET()` to start playing from the default index in the playlist. |
| `startPositionMs: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-long/index.html` | The starting position in the media item from where to start playing, or `https://developer.android.com/reference/kotlin/androidx/media3/common/C#TIME_UNSET()` to start playing from the default position in the media item. This value is ignored if startIndex is C.INDEX_UNSET |

| Returns |
|---|---|
| `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition!>!` | A `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` with a `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition` containing a list of resolved `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem`, and a starting index and position that are playable by the underlying `https://developer.android.com/reference/kotlin/androidx/media3/common/Player`. If returned `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition#startIndex()` is `https://developer.android.com/reference/kotlin/androidx/media3/common/C#INDEX_UNSET()` and `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.MediaItemsWithStartPosition#startPositionMs()` is `https://developer.android.com/reference/kotlin/androidx/media3/common/C#TIME_UNSET()`, then `https://developer.android.com/reference/kotlin/androidx/media3/common/Player#setMediaItems(java.util.List<androidx.media3.common.MediaItem>,boolean)` will be called to set media items with default index and position. |

### onSetRating

```
fun onSetRating(
    session: MediaSession!,
    controller: MediaSession.ControllerInfo!,
    rating: Rating!
): ListenableFuture<SessionResult!>!
```

Called when a controller requested to set a rating for the current media item for the current user by `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController#setRating(androidx.media3.common.Rating)`.

To allow setting the user rating for the current `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem`, the item's `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem#mediaMetadata()` should have the `https://developer.android.com/reference/kotlin/androidx/media3/common/Rating` field in order to provide possible rating style for controllers. Controllers will follow the rating style.

Return a `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` to send a `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult` back to the controller asynchronously. You can also return a `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult` directly by using Guava's `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/Futures.html#immediateFuture(V)`.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |
| `rating: https://developer.android.com/reference/kotlin/androidx/media3/common/Rating!` | The new rating from the controller. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand#COMMAND_CODE_SESSION_SET_RATING()` |   |

### onSetRating

```
fun onSetRating(
    session: MediaSession!,
    controller: MediaSession.ControllerInfo!,
    mediaId: String!,
    rating: Rating!
): ListenableFuture<SessionResult!>!
```

Called when a controller requested to set a rating to a media for the current user by `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaController#setRating(java.lang.String,androidx.media3.common.Rating)`.

To allow setting the user rating for a `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem`, the item's `https://developer.android.com/reference/kotlin/androidx/media3/common/MediaItem#mediaMetadata()` should have the `https://developer.android.com/reference/kotlin/androidx/media3/common/Rating` field in order to provide possible rating style for controllers. Controllers will follow the rating style.

Return a `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` to send a `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult` back to the controller asynchronously. You can also return a `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionResult` directly by using Guava's `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/Futures.html#immediateFuture(V)`.

| Parameters |
|---|---|
| `session: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession!` | The session for this event. |
| `controller: https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo!` | The `https://developer.android.com/reference/kotlin/androidx/media3/session/MediaSession.ControllerInfo` information. |
| `mediaId: https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/-string/index.html!` | The media id. |
| `rating: https://developer.android.com/reference/kotlin/androidx/media3/common/Rating!` | The new rating from the controller. |

| See also |
|---|---|
| `https://developer.android.com/reference/kotlin/androidx/media3/session/SessionCommand#COMMAND_CODE_SESSION_SET_RATING()` |   |