Add Android Automotive OS support to your media app

Android Automotive OS lets users install apps in the car. To reach users on this platform, you need to distribute a driver-optimized app that is compatible with Android Automotive OS. You can reuse almost all the code and resources in your Android Auto app, but you must create a separate build that meets the requirements on this page.

Development overview

Adding Android Automotive OS support only requires a few steps, as described in the sections that follow:

  1. Enable automotive features in Android Studio.
  2. Create an automotive module.
  3. Update your Gradle dependencies.
  4. Optionally, Implement settings and sign-in activities.
  5. Optionally, Read media host hints.

Design considerations

Android Automotive OS takes care of laying out the media content that it receives from your app's media browser service. This means that your app doesn't draw the UI and doesn't start any of your activities when a user triggers media playback.

If you are implementing settings or sign-in activities, these activities must be vehicle-optimized. Refer to the Design guidelines for Android Automotive OS while designing those areas of your app.

Set up your project

You need to set up several parts of your app's project to enable support for Android Automotive OS.

Enable automotive features in Android Studio

Use Android Studio 4.0 or higher to ensure that all Automotive OS features are enabled.

Create an automotive module

Some components of Android Automotive OS, such as the manifest, have platform-specific requirements. Create a module that can keep the code for these components separate from other code in your project, such as the code used for your phone app.

Follow these steps to add an automotive module to your project:

  1. In Android Studio, click File > New > New Module.
  2. Select Automotive Module, then click Next.
  3. Enter an Application/Library name. This is the name that users see for your app on Android Automotive OS.
  4. Enter a Module name.
  5. Adjust the Package name to match your app.
  6. Select API 28: Android 9.0 (Pie) for the Minimum SDK, and then click Next.

    All cars that support Android Automotive OS run on Android 9 (API level 28) or higher, so selecting this value targets all compatible cars.

  7. Select No Activity, and then click Finish.

After creating your module in Android Studio, open the AndroidManifest.xml in your new automotive module:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.media">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" />

    <uses-feature
        android:name="android.hardware.type.automotive"
        android:required="true" />

</manifest>

The <application> element has some standard app information as well as a <uses-feature> element that declares support for Android Automotive OS. Note that there are no activities declared in the manifest.

If you implement settings or sign-in activities, add them here. These activities are triggered by the system using explicit intents and are the only activities you declare within the manifest for your Android Automotive OS app.

After adding any settings or sign-in activities, complete your manifest file by setting the <application> element's android:appCategory attribute to "audio".

<application
  ...
  android:appCategory="audio" />

Declare feature requirements

All apps built for Android Automotive OS must meet certain requirements to be distributed using Google Play. See Meet Google Play feature requirements for more information.

Declare media support for Android Automotive OS

Use the following manifest entry to declare that your app supports Android Automotive OS:

<application>
    ...
    <meta-data android:name="com.android.automotive"
        android:resource="@xml/automotive_app_desc"/>
    ...
</application>

This manifest entry refers to an XML file that declares the automotive capabilities that your app supports.

To indicate that you have a media app, add an XML file named automotive_app_desc.xml to the res/xml/ directory in your project. Include the following content in this file:

<automotiveApp>
    <uses name="media"/>
</automotiveApp>

Intent filters

Android Automotive OS uses explicit intents to trigger activities in your media app. Don't include any activities that have CATEGORY_LAUNCHER or ACTION_MAIN intent filters in the manifest file.

Activities like the one in the following example usually target a phone or some other mobile device. Declare these activities in the module that builds the phone app, not in the module that builds your Android Automotive OS app.

<activity android:name=".MyActivity">
    <intent-filter>
        <!-- You can't use either of these intents for Android Automotive OS -->
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
        <!--
        In their place, you can include other intent filters for any activities
        that your app needs for Android Automotive OS, such as settings or
        sign-in activities.
        -->
    </intent-filter>
</activity>

Update your Gradle dependencies

We recommend that you keep your media browser service in a separate module that you share between your phone app and your automotive module. If you're using this approach, you need to update your automotive module to include the shared module, as shown in the following snippet:

my-auto-module/build.gradle

Groovy

buildscript {
    ...
    dependencies {
        ...
        implementation project(':shared_module_name')
    }
}

Kotlin

buildscript {
    ...
    dependencies {
        ...
        implementation(project(":shared_module_name"))
    }
}

Implement settings and sign-in activities

In addition to your media browser service, you can also provide vehicle-optimized settings and sign-in activities for your Android Automotive OS app. These activities let you provide app functionality that isn't included in the Android Media APIs.

Only implement these activities if your Android Automotive OS app needs to let users sign in or specify app settings. These activities aren't used by Android Auto.

Activity workflows

The following diagram shows how a user interacts with your settings and sign-in activities using Android Automotive OS:

Workflows for Settings and Sign-in activities

Figure 1. Settings and sign-in activity workflows.

Discourage distractions in your settings and sign-in activities

To ensure your settings and sign-in activities are only available for use while the user's vehicle is parked, verify that the <activity> element(s) don't include the following <meta-data> element. Your app will be rejected during review if such an element is present.

<!-- NOT ALLOWED -->
<meta-data
  android:name="distractionOptimized"
  android:value="true"/>

Add a settings activity

You can add a vehicle-optimized settings activity so that users can configure settings for your app in their car. Your settings activity can also provide other workflows, like signing in or out of a user's account or switching user accounts. Remember that this activity is only triggered by an app running on Android Automotive OS. Phone apps connected to Android Auto don't use it.

Declare a settings activity

You must declare your settings activity in your app's manifest file, as shown in the following code snippet:

<application>
    ...
    <activity android:name=".AppSettingsActivity"
              android:exported="true"
              android:theme="@style/SettingsActivity"
              android:label="@string/app_settings_activity_title">
        <intent-filter>
            <action android:name="android.intent.action.APPLICATION_PREFERENCES"/>
        </intent-filter>
    </activity>
    ...
</application>

Implement your settings activity

When a user launches your app, Android Automotive OS detects the settings activity that you declared and displays an affordance, such as an icon. The user can tap or select this affordance using their car's display to navigate to the activity. Android Automotive OS sends the ACTION_APPLICATION_PREFERENCES intent that tells your app to start your settings activity.

The rest of this section shows how you can adapt code from the Universal Android Music Player (UAMP) sample app to implement a settings activity for your app.

To begin, download the sample code:

# Clone the UAMP repository
git clone https://github.com/android/uamp.git

# Fetch the appropriate pull request to your local repository
git fetch origin pull/323/head:NEW_LOCAL_BRANCH_NAME

# Switch to the new branch
git checkout NEW_LOCAL_BRANCH_NAME

To implement your activity, follow these steps:

  1. Copy the automotive/automotive-lib folder into your automotive module.
  2. Define a preferences tree as in automotive/src/main/res/xml/preferences.xml.
  3. Implement a PreferenceFragmentCompat that your settings activity displays. See the SettingsFragment.kt and SettingsActivity.kt files in UAMP and the Android Settings guide for more information.

As you implement your settings activity, consider these best practices for using some of the components in the Preference library:

  • Have no more than two levels of depth below the main view in your settings activity.
  • Don't use a DropDownPreference. Use a ListPreference instead.
  • Organizational components:
  • Include a key and title in all the following components. You can also include a summary, an icon, or both:
    • Preference
      • Customize the logic in the onPreferenceTreeClick() callback of your PreferenceFragmentCompat implementation.
    • CheckBoxPreference
      • Can have summaryOn or summaryOff instead of summary for conditional text.
    • SwitchPreference
      • Can have summaryOn or summaryOff instead of summary for conditional text.
      • Can have switchTextOn or switchTextOff.
    • SeekBarPreference
      • Include a min, max, and defaultValue.
    • EditTextPreference
      • Include dialogTitle, positiveButtonText, and negativeButtonText.
      • Can have one or both of dialogMessage and dialogLayoutResource.
    • com.example.android.uamp.automotive.lib.ListPreference
      • Derives mostly from ListPreference.
      • Used to display a single-choice list of Preference objects.
      • Must have an array of entries and corresponding entryValues.
    • com.example.android.uamp.automotive.lib.MultiSelectListPreference
      • Derives mostly from MultiSelectListPreference
      • Used to display a multiple-choice list of Preference objects.
      • Must have an array of entries and corresponding entryValues.

Add a sign-in activity

If your app requires a user to sign in before they can use your app, you can add a vehicle-optimized sign-in activity that handles signing in and out of your app. You can also add sign-in and sign-out workflows to a settings activity, but use a dedicated sign-in activity if your app can't be used until a user signs in. Remember that this activity is only triggered by an app running on Android Automotive OS. Phone apps connected to Android Auto don't use it.

Require sign in at app start

To require a user to sign in before they can use your app, your media browser service must do the following things:

  1. In your service's onLoadChildren() method, send null result using the sendResult() method.
  2. Set the media session's PlaybackStateCompat to STATE_ERROR using the setState() method. This tells Android Automotive OS that no other operations can be performed until the error has been resolved.
  3. Set the media session's PlaybackStateCompat error code to ERROR_CODE_AUTHENTICATION_EXPIRED. This tells Android Automotive OS that the user needs to authenticate.
  4. Set the media session's PlaybackStateCompat error message using the setErrorMessage() method. Because this error message is user-facing, localize it for the user's current locale.
  5. Set the media session's PlaybackStateCompat extras using the setExtras() method. Include the following two or three keys:

The following code snippet shows how your app can require the user to sign in before using your app:

Kotlin

import androidx.media.utils.MediaConstants

val signInIntent = Intent(this, SignInActivity::class.java)
val signInActivityPendingIntent = PendingIntent.getActivity(this, 0,
    signInIntent, 0)
val extras = Bundle().apply {
    putString(
        MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_LABEL,
        "Sign in"
    )
    putParcelable(
        MediaConstants.PLAYBACK_STATE_EXTRAS_KEY_ERROR_RESOLUTION_ACTION_INTENT,
        signInActivityPendingIntent
    )
}

val playbackState = PlaybackStateCompat.Builder()
        .setState(PlaybackStateCompat.STATE_ERROR, 0, 0f)
        .setErrorMessage(
            PlaybackStateCompat.ERROR_CODE_AUTHENTICATION_EXPIRED,
            "Authentication required"
        )
        .setExtras(extras)
        .build()
mediaSession.setPlaybackState(playbackState)

Java

import androidx.media.utils.MediaConstants;

Intent signInIntent