# MediaController.Listener

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/MediaController.java+class:androidx.media3.session.MediaController.Listener)

*** ** * ** ***

<br />

```
public interface MediaController.Listener
```

<br />

Known direct subclasses [MediaBrowser.Listener](https://developer.android.com/reference/androidx/media3/session/MediaBrowser.Listener)

|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaBrowser.Listener` | A listener for events from `https://developer.android.com/reference/androidx/media3/session/MediaLibraryService`. |

*** ** * ** ***

A listener for events and incoming commands from `https://developer.android.com/reference/androidx/media3/session/MediaSession`.

The methods will be called from the application thread associated with the `https://developer.android.com/reference/androidx/media3/session/MediaController#getApplicationLooper()` of the controller.

## Summary

| ### Public methods |
|---|---|
| `default void` | `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onAvailableSessionCommandsChanged(androidx.media3.session.MediaController,androidx.media3.session.SessionCommands)( https://developer.android.com/reference/androidx/media3/session/MediaController controller, https://developer.android.com/reference/androidx/media3/session/SessionCommands commands )` Called when the available session commands are changed by session. |
| `default https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/androidx/media3/session/SessionResult>` | `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onCustomCommand(androidx.media3.session.MediaController,androidx.media3.session.SessionCommand,android.os.Bundle)( https://developer.android.com/reference/androidx/media3/session/MediaController controller, https://developer.android.com/reference/androidx/media3/session/SessionCommand command, https://developer.android.com/reference/android/os/Bundle.html args )` Called when the session sends a custom command through `https://developer.android.com/reference/androidx/media3/session/MediaSession#sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle)`. |
| `default void` | `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onCustomLayoutChanged(androidx.media3.session.MediaController,java.util.List<androidx.media3.session.CommandButton>)( https://developer.android.com/reference/androidx/media3/session/MediaController controller, https://developer.android.com/reference/java/util/List.html<https://developer.android.com/reference/androidx/media3/session/CommandButton> layout )` Called when the `https://developer.android.com/reference/androidx/media3/session/MediaController#getCustomLayout()` changed. |
| `default void` | `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onDisconnected(androidx.media3.session.MediaController)(https://developer.android.com/reference/androidx/media3/session/MediaController controller)` Called when the controller is disconnected from the session. |
| `default void` | `@https://developer.android.com/reference/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onError(androidx.media3.session.MediaController,androidx.media3.session.SessionError)(https://developer.android.com/reference/androidx/media3/session/MediaController controller, https://developer.android.com/reference/androidx/media3/session/SessionError sessionError)` Called when an non-fatal error `https://developer.android.com/reference/androidx/media3/session/MediaSession#sendError(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionError)` is received. |
| `default void` | `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onExtrasChanged(androidx.media3.session.MediaController,android.os.Bundle)(https://developer.android.com/reference/androidx/media3/session/MediaController controller, https://developer.android.com/reference/android/os/Bundle.html extras)` Called when the session extras are set on the session side. |
| `default void` | `@https://developer.android.com/reference/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onMediaButtonPreferencesChanged(androidx.media3.session.MediaController,java.util.List<androidx.media3.session.CommandButton>)( https://developer.android.com/reference/androidx/media3/session/MediaController controller, https://developer.android.com/reference/java/util/List.html<https://developer.android.com/reference/androidx/media3/session/CommandButton> mediaButtonPreferences )` Called when the `https://developer.android.com/reference/androidx/media3/session/MediaController#getMediaButtonPreferences()` changed. |
| `default void` | `@https://developer.android.com/reference/androidx/media3/common/util/UnstableApi https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onSessionActivityChanged(androidx.media3.session.MediaController,android.app.PendingIntent)( https://developer.android.com/reference/androidx/media3/session/MediaController controller, @https://developer.android.com/reference/androidx/annotation/Nullable https://developer.android.com/reference/android/app/PendingIntent.html sessionActivity )` Called when the `https://developer.android.com/reference/android/app/PendingIntent.html` to launch the session activity `https://developer.android.com/reference/androidx/media3/session/MediaSession#setSessionActivity(android.app.PendingIntent)` on the session side. |
| `default https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html<https://developer.android.com/reference/androidx/media3/session/SessionResult>` | `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onSetCustomLayout(androidx.media3.session.MediaController,java.util.List<androidx.media3.session.CommandButton>)( https://developer.android.com/reference/androidx/media3/session/MediaController controller, https://developer.android.com/reference/java/util/List.html<https://developer.android.com/reference/androidx/media3/session/CommandButton> layout )` Called when the session sets the custom layout through `https://developer.android.com/reference/androidx/media3/session/MediaSession#setCustomLayout(androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.session.CommandButton>)`. |

## Public methods

### onAvailableSessionCommandsChanged

```
default void onAvailableSessionCommandsChanged(
    MediaController controller,
    SessionCommands commands
)
```

Called when the available session commands are changed by session.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaController controller` | The controller. |
| `https://developer.android.com/reference/androidx/media3/session/SessionCommands commands` | The new available session commands. |

### onCustomCommand

```
default ListenableFuture<SessionResult> onCustomCommand(
    MediaController controller,
    SessionCommand command,
    Bundle args
)
```

Called when the session sends a custom command through `https://developer.android.com/reference/androidx/media3/session/MediaSession#sendCustomCommand(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommand,android.os.Bundle)`.

Return a `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` to reply with a `https://developer.android.com/reference/androidx/media3/session/SessionResult` to the session asynchronously. You can also return a `https://developer.android.com/reference/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)`.

The default implementation returns `https://guava.dev/releases/snapshot-android/api/docs/com/google/common/util/concurrent/ListenableFuture.html` of `https://developer.android.com/reference/androidx/media3/session/SessionError#ERROR_NOT_SUPPORTED()`.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaController controller` | The controller. |
| `https://developer.android.com/reference/androidx/media3/session/SessionCommand command` | The custom command. |
| `https://developer.android.com/reference/android/os/Bundle.html args` | The 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/androidx/media3/session/SessionResult>` | The result of handling the custom command. |

### onCustomLayoutChanged

```
default void onCustomLayoutChanged(
    MediaController controller,
    List<CommandButton> layout
)
```

Called when the `https://developer.android.com/reference/androidx/media3/session/MediaController#getCustomLayout()` changed.

This method will be deprecated, prefer to use `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onMediaButtonPreferencesChanged(androidx.media3.session.MediaController,java.util.List<androidx.media3.session.CommandButton>)`. Note that the media button preferences use `https://developer.android.com/reference/androidx/media3/session/CommandButton#slots()` to define the allowed button placement.

The custom layout can change when either the session `https://developer.android.com/reference/androidx/media3/session/MediaSession#setCustomLayout(androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.session.CommandButton>)`, or when the session `https://developer.android.com/reference/androidx/media3/session/MediaSession#setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommands,androidx.media3.common.Player.Commands)` for a controller that affect whether buttons of the custom layout are enabled or disabled.

Note that the `https://developer.android.com/reference/androidx/media3/session/CommandButton#isEnabled()` flag is set to `false` if the available commands do not allow to use a button.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaController controller` | The controller. |
| `https://developer.android.com/reference/java/util/List.html<https://developer.android.com/reference/androidx/media3/session/CommandButton> layout` | The ordered list of `https://developer.android.com/reference/androidx/media3/session/CommandButton`. |

### onDisconnected

```
default void onDisconnected(MediaController controller)
```

Called when the controller is disconnected from the session. The controller becomes unavailable afterwards and this listener won't be called anymore.

It will be also called after the `https://developer.android.com/reference/androidx/media3/session/MediaController#release()`, so you can put clean up code here. You don't need to call `https://developer.android.com/reference/androidx/media3/session/MediaController#release()` after this.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaController controller` | The controller. |

### onError

```
@UnstableApi
default void onError(MediaController controller, SessionError sessionError)
```

Called when an non-fatal error `https://developer.android.com/reference/androidx/media3/session/MediaSession#sendError(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionError)` is received.

When connected to a legacy or platform session, this callback is called when `https://developer.android.com/reference/android/media/session/MediaController.Callback.html#onPlaybackStateChanged(android.media.session.PlaybackState)` is called with an error code and an error message while the playback state is different to `https://developer.android.com/reference/android/media/session/PlaybackState.html#STATE_ERROR`.

Fatal playback errors are reported to `https://developer.android.com/reference/androidx/media3/common/Player.Listener#onPlayerError(androidx.media3.common.PlaybackException)` and `https://developer.android.com/reference/androidx/media3/common/Player.Listener#onPlayerErrorChanged(androidx.media3.common.PlaybackException)` of listeners `https://developer.android.com/reference/androidx/media3/session/MediaController#addListener(androidx.media3.common.Player.Listener)`.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaController controller` | The `https://developer.android.com/reference/androidx/media3/session/MediaController` that received the error. |
| `https://developer.android.com/reference/androidx/media3/session/SessionError sessionError` | The session error. |

### onExtrasChanged

```
default void onExtrasChanged(MediaController controller, Bundle extras)
```

Called when the session extras are set on the session side.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaController controller` | The controller. |
| `https://developer.android.com/reference/android/os/Bundle.html extras` | The session extras that have been set on the session. |

### onMediaButtonPreferencesChanged

```
@UnstableApi
default void onMediaButtonPreferencesChanged(
    MediaController controller,
    List<CommandButton> mediaButtonPreferences
)
```

Called when the `https://developer.android.com/reference/androidx/media3/session/MediaController#getMediaButtonPreferences()` changed.

The media button preferences can change when either the session `https://developer.android.com/reference/androidx/media3/session/MediaSession#setMediaButtonPreferences(androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.session.CommandButton>)`, or when the session `https://developer.android.com/reference/androidx/media3/session/MediaSession#setAvailableCommands(androidx.media3.session.MediaSession.ControllerInfo,androidx.media3.session.SessionCommands,androidx.media3.common.Player.Commands)` for a controller that affect whether buttons of the media button preferences are enabled or disabled.

Note that the `https://developer.android.com/reference/androidx/media3/session/CommandButton#isEnabled()` flag is set to `false` if the available commands do not allow to use a button.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaController controller` | The controller. |
| `https://developer.android.com/reference/java/util/List.html<https://developer.android.com/reference/androidx/media3/session/CommandButton> mediaButtonPreferences` | The ordered list of `https://developer.android.com/reference/androidx/media3/session/CommandButton`. |

### onSessionActivityChanged

```
@UnstableApi
default void onSessionActivityChanged(
    MediaController controller,
    @Nullable PendingIntent sessionActivity
)
```

Called when the `https://developer.android.com/reference/android/app/PendingIntent.html` to launch the session activity `https://developer.android.com/reference/androidx/media3/session/MediaSession#setSessionActivity(android.app.PendingIntent)` on the session side.

| Parameters |
|---|---|
| `https://developer.android.com/reference/androidx/media3/session/MediaController controller` | The controller. |
| `@https://developer.android.com/reference/androidx/annotation/Nullable https://developer.android.com/reference/android/app/PendingIntent.html sessionActivity` | The pending intent to launch the session activity. |

### onSetCustomLayout

```
default ListenableFuture<SessionResult> onSetCustomLayout(
    MediaController controller,
    List<CommandButton> layout
)
```

Called when the session sets the custom layout through `https://developer.android.com/reference/androidx/media3/session/MediaSession#setCustomLayout(androidx.media3.session.MediaSession.ControllerInfo,java.util.List<androidx.media3.session.CommandButton>)`.

This method will be deprecated. Use `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onCustomLayoutChanged(androidx.media3.session.MediaController,java.util.List<androidx.media3.session.CommandButton>)` instead.

There is a slight difference in behaviour. This to be deprecated method may be consecutively called with an unchanged custom layout passed into it, in which case the new `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onCustomLayoutChanged(androidx.media3.session.MediaController,java.util.List<androidx.media3.session.CommandButton>)` isn't called again for equal arguments.

Further, when the available commands of a controller change in a way that affect whether buttons of the custom layout are enabled or disabled, the new callback `https://developer.android.com/reference/androidx/media3/session/MediaController.Listener#onCustomLayoutChanged(androidx.media3.session.MediaController,java.util.List<androidx.media3.session.CommandButton>)` is called, in which case the deprecated callback isn't called.