Media apps using the Car App Library templates can customize their media browsing and playback experience while ensuring the experience is optimized for car screens and minimizes distractions while driving.
This guide assumes that you already have a media app that plays audio on a phone
and that your media app conforms to the Android media app architecture. The
Car App Library gives you the ability to replace the in-app experience with
templates instead of those built using the Build media apps for cars
MediaBrowser
data structure. You still must provide a MediaSession
for playback controls, and a MediaBrowserService
, which is used for
recommendations and other smart experiences.
Configure your app's manifest
In addition to the steps described in Using the Android for Cars App Library, the following are required of templated media apps:
Declare category support in your manifest
Your app needs to declare the androidx.car.app.category.MEDIA
car app category in the intent
filter of its CarAppService
.
<application>
...
<service
...
android:name=".MyCarAppService"
android:exported="true">
<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.MEDIA"/>
</intent-filter>
</service>
...
<application>
To get access to the MediaPlaybackTemplate
, your app also
needs to declare the androidx.car.app.MEDIA_TEMPLATES
permission in its
manifest file:
<manifest ...>
...
<uses-permission android:name="androidx.car.app.MEDIA_TEMPLATES"/>
...
</manifest>
Set the minimum car app API level
Media apps using the MediaPlaybackTemplate
are only supported in CAL API 8,
be sure your minimum Car App API level
is set to 8.
<application ...>
...
<meta-data
android:name="androidx.car.app.minCarApiLevel"
android:value="8"/>
...
</application>
Declare Android Auto support
Ensure the following is included in your app's manifest:
<application>
...
<meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/>
...
</application>
Then, add the template declaration to automotive_app_desc.xml
in your xml
resources. It should look as follows:
<automotiveApp xmlns:android="http://schemas.android.com/apk/res/android">
<uses name="media"/>
<uses name="template"/>
</automotiveApp>
Provide an attribution icon
Be sure to add an attribution icon for media apps built using the Car App Library.
Support voice actions
Voice-enable your app to allow users to complete common actions hands-free.
See support voice actions for media for more detailed implementation
instructions. With a templated media app if you receive a voice command, you
don't need to update your MediaBrowserService
with search results. Instead,
consider adding an action in your media playback template to allow the user to
find more content based on that play or search query. Supporting voice commands
is required to meet the VC-1
quality guideline.
Create your Playback Template
The MediaPlaybackTemplate
displays media playback
information in your Car App Library media app. This template allows setting a
header with a title and customizable actions while the media information and
playback controls are populated by the host based off of the state of your app's
MediaSession
.
Figure 1:
MediaPlaybackTemplate
with a header action to open the queue
along the top.
This code example shows how to build an example playback template that sets a header action which allows the user to navigate to a screen with the queue of songs.
val playbackTemplate = MediaPlaybackTemplate.Builder()
.setHeader(
Header.Builder()
.setStartHeaderAction(Action.BACK)
.addEndHeaderAction(
Action.Builder()
.setTitle(model.context.getString(R.string.queue_button_title))
.setIcon(
CarIcon.Builder(
IconCompat.createWithResource(
model.context,
R.drawable.gs_queue_music_vd_theme_24,
))
.build())
.setOnClickListener(showQueueScreen())
.build())
.setTitle(model.context.getString(R.string.media_playback_view_title))
.build())
.build()
When you use MediaPlaybackTemplate
, register a
MediaSession
token using the MediaPlaybackManager
in your
CarAppService
. Failing to do so causes an error to be displayed when a
MediaPlaybackTemplate
is sent to the host.
import androidx.car.app.media.MediaPlaybackManager
…
override fun onCreateSession(sessionInfo: SessionInfo): Session {
return object : Session() {
…
init {
lifecycle.addObserver(
LifecycleEventObserver { _, event ->
if (event == ON_CREATE) {
val token = ... // MediaSessionCompat.Token
(carContext.getCarService(CarContext.MEDIA_PLAYBACK_SERVICE) as MediaPlaybackManager)
.registerMediaPlaybackToken(token)
}
...
}
)
}
}
}
.registerMediaPlaybackToken
is necessary for exposing media playback
information and controls to Android Auto. This is also important for the host to
create media specific notifications.
Organize media using templates
To organize media for browsing such as songs or albums, we recommend using the
SectionedItemTemplate
,
which lets you use the GridSection
and
RowSection
together to create layouts that mix lists of images
and text items.
Figure 2: A
SectionedItemTemplate
containing a RowSection
followed by a GridSection
Using SectionedItemTemplate inside a TabTemplate
One convenient way to categorize media within your app, is using the
SectionedItemTemplate
inside a
TabTemplate
.
val template =
SectionedItemTemplate.Builder()...build();
val tabTemplate =
TabTemplate.Builder(tabCallback)
.setTabContents(TabContents.Builder(template).build)
.setHeaderAction(Action.APP_ICON)
…
.build();
For more details about how to design your media app's user interface using these templates, see Media apps.
Navigating to the playback controls
When browsing through media it is important that the user is able to quickly
navigate to the MediaPlaybackTemplate
with minimal distraction. To meet the
MFT-1
quality requirement, your app must have a way to access
the MediaPlaybackTemplate
from all media browsing screens.
If you are using SectionedItemTemplate
you can achieve this by adding a
floating action button that navigates you to the media playback screen. For
other templates, a header action is another way to achieve this.