Building for Android Auto

AndroidAndroid AutoAutomotiveUX
Share on LinkedIn

Android Auto isn't your phone app on a bigger screen. Google enforces template-based UI through the Android for Cars App Library — you pick from a fixed set of layouts, populate them with data, and handle user actions through callbacks. No RecyclerView, no custom Compose, no floating action buttons. I built a POI app for Auto and spent the first week fighting the templates before realizing the constraint is the feature: it forces you to design for glances and voice, which is exactly what driving demands.

Supported app categories

Category Library Custom UI
Navigation Navigation SDK Full map control
Point of interest Car App Library Templates only
IoT Car App Library Templates only
Media Media3 / MediaBrowser System-provided media UI

If your app doesn't fit these categories, it doesn't belong on Auto. Google rejected an early version of a productivity app I consulted on — "task manager" isn't a supported category.

Project setup

Add the Car App Library dependency:

dependencies {
    implementation("androidx.car.app:app:1.4.0")
    implementation("androidx.car.app:app-projected:1.4.0")  // phone-as-projected
}

Declare your car app service in the manifest:

<service
    android:name=".CarAppService"
    android:exported="true">
    <intent-filter>
        <action android:name="androidx.car.app.CarAppService" />
        <category android:name="androidx.car.app.category.POI" />
    </intent-filter>
    <meta-data
        android:name="androidx.car.app.minCarApiLevel"
        android:value="1" />
</service>

Your CarAppService creates sessions that host screens:

class CarAppService : SessionCarAppService() {
    override fun createSession(): Session = object : Session() {
        override fun onCreateScreen(intent: Intent): Screen = PlaceListScreen(carContext)
    }
}

Template-based screens

Every screen extends Screen and returns a Template:

class PlaceListScreen(carContext: CarContext) : Screen(carContext) {
    override fun onGetTemplate(): Template {
        val places = repository.getNearbyPlaces()
        return ListTemplate.Builder()
            .setTitle("Nearby")
            .setHeaderAction(Action.APP_ICON)
            .setSingleList(
                ItemList.Builder().apply {
                    places.forEach { place ->
                        addItem(
                            Row.Builder()
                                .setTitle(place.name)
                                .addText(place.address)
                                .setOnClickListener {
                                    screenManager.push(PlaceDetailScreen(carContext, place))
                                }
                                .build()
                        )
                    }
                }.build()
            )
            .build()
    }
}

Available templates: ListTemplate, GridTemplate, PaneTemplate, MessageTemplate, SearchTemplate, TabTemplate, PlaceListMapTemplate. Pick the one that fits — you can't combine them freely.

Navigation apps are different

Navigation apps use the Navigation SDK with full map rendering — a completely separate API surface. If you're building turn-by-turn directions, start with the Navigation SDK documentation, not the Car App Library. POI and media apps are simpler; navigation is its own specialization.

Testing with DHU

Install the Desktop Head Unit from SDK Manager (Android Auto Desktop Head Unit Emulator):

# Connect phone via USB with USB debugging
adb forward tcp:5277 tcp:5277
~/Library/Android/sdk/extras/google/auto/desktop-head-unit

Or run headless for CI (limited — mostly smoke testing):

./desktop-head-unit --headless

Test with both touch and rotary input modes. Many real car head units are rotary-only — if you design for touch, you'll ship broken UX for a large segment.

Distraction optimization

Google enforces driver distraction rules programmatically:

Use ParkedOnlyOnClickListener for actions that require attention:

.setOnClickListener(
    ParkedOnlyOnClickListener.create {
        // Only fires when car is parked
        showComplexSettings()
    }
)

Play Store submission

Before publishing:

  1. Run the Android Auto test suite (available in Play Console)
  2. Test on DHU with touch and rotary modes
  3. Verify your app category matches your manifest declaration
  4. Include Auto screenshots in your Play Store listing

Auto apps go through an additional review beyond standard Play review.

Navigation and session lifecycle

Car apps have strict lifecycle rules — the system kills your app aggressively:

override fun onStop() {
    // Save navigation state — user may return hours later
    sessionStorage.save(currentScreen, scrollPosition)
}

override fun onStart() {
    // Restore or show fresh content if stale > 24h
}

ScreenManager stack depth is limited. Don't push 10 screens deep — flatten to tab-like navigation where possible. Back always returns to root browse screen.

Car hardware fragmentation

Test matrix beyond DHU:

Input Vehicles Test focus
Touch Newer vehicles Large targets, swipe vs tap
Rotary BMW, Mazda, older Focus order, no hover states
Hybrid Many 2024+ models Both input modes in same app

Rotary input requires explicit focus — Compose for Auto handles much of this, but custom components need Modifier.focusable() and visible focus indicators.

Media vs messaging vs navigation apps

Template selection depends on category:

Declaring wrong category in manifest causes Play rejection. Match template usage to declared automotive_app_desc.xml categories.

Production checklist

Car OEM skins vary font sizes dramatically — test your templates at smallest and largest system font scale before Play submission to avoid truncated action labels.

Common production mistakes

Teams get auto app development wrong in predictable ways:

Shipping auto app development on Android fails quietly when you test only on flagship devices, skip process-death scenarios, or assume minSdk behavior matches latest API docs. Emulator-only validation misses OEM-specific battery optimizations and background execution limits.

Resources

Frequently asked questions

What app types does Android Auto support?

Android Auto supports navigation (full custom map), point of interest (lists and details), internet of things (device control), and media apps (via Media3/MediaBrowserService). You cannot port a standard phone UI — all non-navigation apps must use the Android for Cars App Library templates with strict layout and interaction constraints.

How do you test Android Auto apps without a car?

Use the Desktop Head Unit (DHU) emulator included in the Android SDK. Connect your phone running the debug build via ADB, or run the DHU in standalone mode with an emulator image. Google also provides an Android Auto test suite app for compatibility validation before Play Store submission.

What are the main Android Auto design constraints?

No custom layouts — use provided templates (List, Grid, Pane, Message, etc.). Maximum item counts per template. No scrolling text, no complex gestures, no keyboard input while driving. All interactions must be completable via rotary controller or voice. Distraction optimization is enforced at the framework level.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →