Add Android Automotive OS support to your Android Auto project

If you already have a media app that works with Android Auto, you can add support for Android Automotive OS with just a few steps. Android Automotive OS allows users to install stand-alone apps onto their vehicle's infotainment system. To reach users who have a car with Android Automotive OS, you need to create a stand-alone app that is driver-optimized and separate from your phone app.

Android Automotive OS connects to your app using the same Media Browse Service that your phone app uses to connect to Android Auto.

Development overview

Adding Android Automotive OS support is simple and only requires a few steps:

  1. Create an automotive module
  2. Examine your manifest file
  3. Update your gradle dependencies
  4. (Optional) Add settings or sign-in activities

Design considerations

Android Automotive OS takes care of laying out the media content that it receives from your app's Media Browse Service. Like with Android Auto, this means that your app doesn't draw the UI and your app does not start any of your activities when a user triggers media playback.

However, if you are implementing Settings or Sign-in activities, these activities must be vehicle-optimized. You should 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 different parts of your app's project to enable support for Android Automotive OS.

Enable automotive features in Android Studio

To access features for building and testing for Android Automotive OS, you must be using Android Studio 3.5 Canary 11 or higher.

Then, follow these steps to enable automotive features:

  1. If the file does not already exist, create a studioFlags.xml file in one of the following locations, depending on your operating system:

    • Windows: %USERPROFILE%\.AndroidStudioPreview3.5\config\options
    • macOS: ~/Library/Preferences/AndroidStudioPreview3.5/options
    • Linux: ~/.AndroidStudioPreview3.5/config/options
  2. Add the following entry to the studioFlags.xml file:

    <application>
    <component name="StudioFlags">
      <option name="data">
        <map>
          <entry key="npw.templates.automotive" value="true" />
        </map>
      </option>
    </component>
    </application>
    

Create an automotive module

Some components of Android Automotive OS, such as the manifest, have platform-specific requirements, so you need to 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, select File > New > New Module.
  2. Select Automotive Module, then click Next.
  3. Provide an Application/Library name. This is the name that users see for your app on Android Automotive OS.
  4. Provide 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 100% of cars that use Android Automotive OS.

  7. You already have a Media Browse Service for Android Auto, so select Add No Activity, and then click Finish.

Examine your manifest file

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>

You'll notice some standard app information in the <application> element, but there's also a <uses-feature> element that declares support for Android Automotive OS. Also note that there are currently no activities declared in the manifest. If your app needs them, you can add a Settings or Sign-in activity, though those activities are triggered by the system using explicit intents, and they are the only activities that should ever be declared within the manifest for your Android Automotive OS app.

Update your gradle dependencies

We recommend that you keep your Media Browse 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 new automotive module to include your shared module with your Media Browse Service, as shown in the following snippet:

my-auto-module/build.gradle

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

Implement settings and sign-in activities for Android Automotive OS

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 allow you provide app functionality that isn't included in the Android Media APIs.

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.

Settings activity workflows

Your Settings activity can provide the user with different workflows. The following image shows how a user interacts with your Settings activity using Android Automotive OS:

Workflows for a Settings activity

Figure 1. Diagram of workflows for a Settings activity

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: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. 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.

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 you should use a dedicated Sign-in activity if your app cannot be used until a user signs in.

Sign-in activity workflow

The following image shows how a user interacts with your Sign-in activity using Android Automotive OS:

Workflows for a Sign-in activity

Figure 2. Diagram of workflows for a Sign-in activity

Require sign in at app start

To require a user to sign in using your Sign-in activity before they can use your app, your media browse service must do the following things:

  1. Set the media session's PlaybackState 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.
  2. Set the media session's PlaybackState error code to ERROR_CODE_AUTHENTICATION_EXPIRED. This tells Android Automotive OS that the user needs to authenticate.
  3. Set the media session's PlaybackState error message using the setErrorMessage() method. Because this error message is user-facing, the message must be localized for the user's current locale.
  4. Set the media session's PlaybackState extras using the setExtras() method. Include the following two keys:

    • android.media.extras.ERROR_RESOLUTION_ACTION_LABEL: A string that is displayed on the button that begins the sign-in workflow. Because this string is user-facing, it must be localized for the user's current locale.
    • android.media.extras.ERROR_RESOLUTION_ACTION_INTENT: A PendingIntent that directs the user to your Sign-in activity when the user taps the button referred to by the android.media.extras.ERROR_RESOLUTION_ACTION_LABEL.

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

Kotlin

val signInIntent = Intent(this, SignInActivity::class.java)
val signInActivityPendingIntent = PendingIntent.getActivity(this, 0,
    signInIntent, 0)
val extras = Bundle().apply {
    putString(
        "android.media.extras.ERROR_RESOLUTION_ACTION_LABEL",
        "Sign in"
    )
    putParcelable(
        "android.media.extras.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

Intent signInIntent = new Intent(this, SignInActivity.class);
PendingIntent signInActivityPendingIntent = PendingIntent.getActivity(this, 0,
    signInIntent, 0);
Bundle extras = new Bundle();
extras.putString(
    "android.media.extras.ERROR_RESOLUTION_ACTION_LABEL",
    "Sign in");
extras.putParcelable(
    "android.media.extras.ERROR_RESOLUTION_ACTION_INTENT",
    signInActivityPendingIntent);

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

After the user has successfully authenticated, your app must set the PlaybackState back to a state other than STATE_ERROR and then take the user back to Android Automotive OS by calling the activity's finish() method.

Implement your Sign-in activity

Google offers a variety of identity tools that you can use to help users sign in to your app in their cars. Some tools, such as Firebase Authentication, provide full-stack toolkits that can help you build customized authentication experiences. Other tools leverage a user's existing credentials or other technologies to help you build seamless sign-in experiences for users.

We recommend the following tools to help you build an easier sign-in experience for users that have previously signed in on another device:

  • Google Sign-in: If you've already implemented Google Sign-in for other devices (such as your phone app), you should also implement Google Sign-in for your Android Automotive OS app to support existing Google Sign-in users.
  • Autofill with Google: If users have opted into Autofill with Google on their other Android devices, their credentials are saved to the Google password manager. Then, when the user signs in to your Android Automotive OS app, Autofill with Google suggests relevant saved credentials. Using Autofill with Google requires no application development effort; however, application developers should optimize their apps for better quality results. Autofill with Google is supported by all devices running Android Oreo 8.0 (API level 26) or higher (including Android Automotive OS).

Handle sign-in protected actions

Some apps allow a user to access some actions anonymously, but require the user to sign in before they can perform other actions. For example, a user might be able to play music in an app before signing in, but they must sign in before they can skip a song.

In this case, when the user attempts to perform the restricted action (skipping a song), your app could suggest that user authenticate by issuing a non-fatal error. By using a non-fatal error, the system displays the message to the user without interrupting playback for the current media item. To implement non-fatal error handling, complete the following steps:

  1. Set the errorCode for the media session's PlaybackState to ERROR_CODE_AUTHENTICATION_EXPIRED. This tells Android Automotive OS that user needs to authenticate.
  2. Keep the state for the media session's PlaybackState as is—don't set it to STATE_ERROR. This is what tells the system that the error is non-fatal.
  3. Set the media session's PlaybackState extras using the setExtras() method. Include the following two keys:

    • android.media.extras.ERROR_RESOLUTION_ACTION_LABEL: A string that is displayed on the button that begins the sign-in workflow. Because this string is user-facing, it must be localized for the user's current locale.
    • android.media.extras.ERROR_RESOLUTION_ACTION_INTENT: A PendingIntent that directs the user to your Sign-in activity when the user taps the button referred to by the android.media.extras.ERROR_RESOLUTION_ACTION_LABEL.
  4. Retain the rest of the media session's PlaybackState state as is. This allows playback for the current media item to continue while the user decides whether to sign in or not.

Test your app for Android Automotive OS

You can use the Android Emulator to test how your driver-optimized app runs on an Android Automotive OS vehicle display. This section describes how to set up an Android Virtual Device (AVD) that you can use to test your app.

Edit your run configurations

Automotive OS apps are different other Android apps. Android Automotive OS interacts with your app using explicit intents and your Media Browse Service.

In order to test your app, verify that you have set your automotive module to not launch any activity by following these steps:

  1. In Android Studio, select Run > Edit Configurations.

    The Run/Debug Configurations dialog box.

  2. Select your automotive module from the list of modules in your app.

  3. Under Launch Options > Launch, select Nothing.

  4. Click Apply, and then click OK.

Add system images

Before you can create AVDs that match specific manufacturer hardware, you need to add system images for these devices through the Android Studio SDK Manager. Then, when you're creating an AVD, you can download these system images to use with the AVD.

Follow these steps to add a system image for the Polestar 2:

  1. In Android Studio, select Tools > SDK Manager.
  2. Click the SDK Update Sites tab.
  3. Click Add Add icon.
  4. Enter the following Name and URL, then click OK:

    Name: Polestar 2 System Image

    URL: https://developer.polestar.com/sdk/polestar2-sys-img.xml

  5. Click Apply, then click OK.

Create a car AVD and run the emulator

Follow these steps to create an Android Virtual Device (AVD) that represents an Android Automotive OS vehicle and then use that AVD to run the emulator:

  1. In Android Studio, select Tools > AVD Manager.
  2. Click Create Virtual Device.
  3. From the Select Hardware dialog, select Automotive, and then select a device and click Next.
  4. Select a system image that targets Automotive, such as Android 9.0 (Automotive), and click Next.
  5. Name your AVD and select any other options that you want to customize and then click Finish.
  6. From tool window bar, select your Android Automotive OS AVD as your deployment target.
  7. Click Run Run icon.