To enable media playback in Android Auto and Android Automotive OS (AAOS), implement playback controls by registering a media session and handling its callback methods. This page explains how to:
Register a
MediaSessionCompat
object in your media browser service.Implement
MediaSessionCompat.Callback
methods to respond to user playback requests.Configure standard and custom playback actions.
Set the initial playback state for your media session.
Add icons to indicate audio format.
Create links from actively playing media items.
Android Auto and AAOS send playback control commands through
MediaSessionCompat
for your service. You must register a session and
implement the associated callback methods.
Register a media session
In your media browser service's onCreate
method, create an instance of
MediaSessionCompat
, then call setSessionToken
to register the
media session. This code snippet shows how to create and register a media
session:
Kotlin
override fun onCreate() {
super.onCreate()
...
// Start a new MediaSession.
val session = MediaSessionCompat(this, "session tag").apply {
// Set a callback object that implements MediaSession.Callback
// to handle play control requests.
setCallback(MyMediaSessionCallback())
}
sessionToken = session.sessionToken
...
}
Java
public void onCreate() {
super.onCreate();
...
// Start a new MediaSession.
MediaSessionCompat session = new MediaSessionCompat(this, "session tag");
setSessionToken(session.getSessionToken());
// Set a callback object that implements MediaSession.Callback
// to handle play control requests.
session.setCallback(new MyMediaSessionCallback());
...
}
When you create the media session object, you set a callback object that is used
to handle playback control requests. You create this callback object by
providing an implementation of the MediaSessionCompat.Callback
class for your app. The next section discusses how to implement this object.
Implement play commands
When a user requests playback for a media item from your app, Android Automotive
OS and Android Auto use the MediaSessionCompat.Callback
class from your app's MediaSessionCompat
object that they obtained from
your app's media browser service. When a user wants to control content playback,
such as pausing playback or skipping to the next track, Android Auto and Android
Automotive OS invoke one of the callback object's methods.
To handle content playback, your app must extend the abstract
MediaSessionCompat.Callback
class and implement the methods that your app
supports.
Implement each of these callback methods that make sense for the type of content offered by your app:
onPrepare
- AAOS invokes this method when the media source changes.
onPlay
Invoked when the user selects play without choosing a specific item. Your app must play its default content or, if playback was paused with
onPause
, your app resumes playback.onPlayFromMediaId
Invoked when the user chooses to play a specific item. The method receives the ID that your media browser service assigned to the media item in the content hierarchy.
onPlayFromSearch
Invoked when the user chooses to play from a search query. The app must make an appropriate choice based on the search string that was passed in.
onPause
Invoked when the user chooses to pause playback.
onSkipToNext
Invoked when the user chooses to skip to the next item.
onSkipToPrevious
Invoked when the user chooses to skip to the previous item.
onStop
Invoked when the user chooses to stop play. Override these methods in your app to provide the chosen result. You needn't implement a method if its purpose isn't supported by your app. For example, if your app plays a livestream, such as a sports broadcast, you needn't implement
onSkipToNext
. Instead, use the default implementation ofonSkipToNext
.
Your app doesn't need any special logic to play content through the car's speakers. When your app receives a request to play content, it plays audio in the same way that content is played through a user's phone speakers or headphones. Android Auto and AAOS automatically send the audio content to the car's system to play over the car's speakers.
To learn more about playing audio content, see Media Player overview, Audio app overview, and the ExoPlayer overview.
Set standard playback actions
Android Auto and AAOS display playback controls based on the
actions that are enabled in the PlaybackStateCompat
object. By default, your app must support the following actions:
Your app can additionally support the following actions if they are relevant to the app's content:
In addition, you can optionally create a play queue for display to for the user.
To do this, call the setQueue
and setQueueTitle
methods, enable
the ACTION_SKIP_TO_QUEUE_ITEM
action, and define the callback
onSkipToQueueItem
.
Also, add support for the Now playing icon, which is an indicator for what
is playing. To do this, call the setActiveQueueItemId
method and pass
the ID of the playing item in the queue. You need to update
setActiveQueueItemId
whenever there is a queue change.
Android Auto and AAOS display buttons for each enabled action as well as the
playback queue. When users click these buttons, the system invokes the
corresponding callback from MediaSessionCompat.Callback
.
Reserve unused space
Android Auto and AAOS reserve space in the UI for the
ACTION_SKIP_TO_PREVIOUS
and ACTION_SKIP_TO_NEXT
actions. If your app does
not support one of these functions, Android Auto and AAOS use
the space to display any custom actions you create.
If you don't want to fill those spaces with custom actions, you can reserve them so that Android Auto and AAOS leave the space blank whenever your app doesn't support the corresponding function.
To do so, call the setExtras
method with an extras bundle that contains
constants that correspond to the reserved functions.
SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_NEXT
corresponds to ACTION_SKIP_TO_NEXT
, and
SESSION_EXTRAS_KEY_SLOT_RESERVATION_SKIP_TO_PREV
corresponds to ACTION_SKIP_TO_PREVIOUS
. Use these constants as keys in the
bundle, and use the boolean true
as values.
Set initial PlaybackState
As Android Auto and AAOS communicate with your media browser
service, your media session communicates the status of content playback using
the PlaybackStateCompat
.
Your app shouldn't automatically start playing music when AAOS or Android Auto connects to your media browser service. Instead, rely on Android Auto and AAOS to resume or start playback based on the car's state or user actions.
To accomplish this, set the initial PlaybackStateCompat
of your media session to STATE_STOPPED
, STATE_PAUSED
,
STATE_NONE
, or STATE_ERROR
.
Media sessions within Android Auto and AAOS only last for the
duration of the drive, so users start and stop these sessions frequently. To
promote a seamless experience between drives, keep track of the user's previous
session state, so that when the media app receives a resume request, the user
can automatically pick up where they left off. For example, the last played
media item, the PlaybackStateCompat
, and the queue.
Add custom playback actions
You can add custom playback actions to display additional actions that your
media app supports. If space permits (and you don't reserve it), Android
adds the custom actions to the transport controls. Otherwise, the custom
actions appear in the Overflow menu. Android displays custom actions in the
order you add them to PlaybackStateCompat
.
Use custom actions to provide behavior distinct from standard actions. Don't use them to replace or duplicate standard actions.
To add custom actions, use the addCustomAction
method in the
PlaybackStateCompat.Builder
class. This code snippet shows how to add
a custom action to "Start a radio channel":
Kotlin
val customActionExtras = Bundle()
customActionExtras.putInt(
androidx.media3.session.MediaConstants.EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT,
androidx.media3.session.CommandButton.ICON_RADIO)
stateBuilder.addCustomAction(
PlaybackStateCompat.CustomAction.Builder(
CUSTOM_ACTION_START_RADIO_FROM_MEDIA,
resources.getString(R.string.start_radio_from_media),
startRadioFromMediaIcon // or R.drawable.media3_icon_radio
).run {
setExtras(customActionExtras)
build()
}
)
Java
Bundle customActionExtras = new Bundle();
customActionExtras.putInt(
androidx.media3.session.MediaConstants.EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT,
androidx.media3.session.CommandButton.ICON_RADIO);
stateBuilder.addCustomAction(
new PlaybackStateCompat.CustomAction.Builder(
CUSTOM_ACTION_START_RADIO_FROM_MEDIA,
resources.getString(R.string.start_radio_from_media),
startRadioFromMediaIcon) // or R.drawable.media3_icon_radio
.setExtras(customActionExtras)
.build());
For a more detailed example of this method, see the setCustomAction
method in the Universal Android Music Player sample app on GitHub. After you
create your custom action, your media session can respond to the actions
by overriding the onCustomAction
method.
This code snippet shows how your app could respond to a "Start a radio channel" action:
Kotlin
override fun onCustomAction(action: String, extras: Bundle?) {
when(action) {
CUSTOM_ACTION_START_RADIO_FROM_MEDIA -> {
...
}
}
}
Java
@Override
public void onCustomAction(@NonNull String action, Bundle extras) {
if (CUSTOM_ACTION_START_RADIO_FROM_MEDIA.equals(action)) {
...
}
}
To learn more, see the onCustomAction
method in the Universal Android
Music Player sample app on GitHub.
Create icons for custom actions
Each custom action that you create requires an icon.
If the description of that icon matches one of the CommandButton.ICON_
constants, set the integer value for the
EXTRAS_KEY_COMMAND_BUTTON_ICON_COMPAT
key of the custom action's
extras. On supported systems, doing so overrides the icon resource passed to
CustomAction.Builder
, allowing system components to consistently render
your action and other playback actions.
You must also specify an icon resource. Apps in cars can run on many different screen sizes and densities, so icons that you provide must be vector drawables. Use a vector drawable to scale assets without losing detail. A vector drawable can align edges and corners to pixel boundaries at smaller resolutions.
If a custom action is stateful (if it toggles a playback setting on or off), provide different icons for the different states to help users see a change when they select the action.
Provide alternative icon styles for disabled actions
When a custom action is unavailable for the current context, swap the custom action icon with an alternative icon that shows the action as disabled.

Indicate audio format
To indicate that the playing media uses a special audio format,
you can specify icons that are rendered in cars that support this feature. You
can set the KEY_CONTENT_FORMAT_TINTABLE_LARGE_ICON_URI
and the
KEY_CONTENT_FORMAT_TINTABLE_SMALL_ICON_URI
in the extras bundle of the
currently playing media item (passed to MediaSession.setMetadata
).
Set both extras to accommodate the different layouts.
In addition, you can set the KEY_IMMERSIVE_AUDIO
extra
to tell car OEMs that this is immersive audio, and they should be very careful
when deciding whether to apply audio effects that might interfere with the
immersive content.
Add links from currently-playing item
You can configure the playing media item so its subtitle, description, or both are links to other media items. That lets the user jump quickly to related items; for example, they might jump to other songs by the same artist or to other episodes of a podcast. If the car supports this feature, users can tap the link to browse to that content.
To add links, configure the KEY_SUBTITLE_LINK_MEDIA_ID
metadata
(to link from the subtitle) or KEY_DESCRIPTION_LINK_MEDIA_ID
(to link
from the description). For details, see the reference documentation for those
metadata fields.