メインコンテンツまでスキップ
For the complete documentation index, see llms.txt.

Get Started with Android Auto

This guide shows you how to configure Android Auto features in a Android app using the Mapbox Navigation SDK for Android.

Prerequisites​

Before you begin, make sure you have:

Note

If you want to use Mapbox Maps in Android Auto without the Navigation SDK, refer to the Mapbox Android Auto Extension.

Configure Android Auto Support​

Step 1: Add Android Auto dependencies​

Add the Android Auto components module to your app-level build.gradle file. The library version matches the Navigation SDK version, ensuring compatibility:

build.gradle
dependencies {
...
implementation "com.mapbox.navigationcore:android-ndk27:3.34.2"
implementation "com.mapbox.navigationcore:android-auto-components-ndk27:3.34.2"
// if your app does not require 16 KB page size support, the default dependency without -ndk27 can be used
// implementation "com.mapbox.navigationcore:android-auto-components:3.34.2"
...
}

Step 2: Declare Android Auto support in your manifest​

Add the required elements to the <application> tag in your AndroidManifest.xml:

  1. Add the 3 required permissions to gain access to the user's location and allow the app to continue running even when the user navigates away from the app.
  2. Add metadata to declare support for Android Auto.
  3. Create a CarAppService with the appropriate intent filter to label this app as a navigation application.
<application>
...

<!-- Required permissions -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />

...

<!-- Metadata for Android Auto support -->
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />

<!-- CarAppService for navigation -->
<service
android:name=".car.MainCarAppService"
android:exported="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:foregroundServiceType="location">

<intent-filter>
<action android:name="androidx.car.app.CarAppService" />
<category android:name="androidx.car.app.category.NAVIGATION" />
</intent-filter>
</service>

...
</application>
Important

The automotive_app_desc resource is included by the Mapbox Navigation Android Auto SDK, so you don't need to create it yourself. Make sure to specify the correct category (androidx.car.app.category.NAVIGATION) or your app will be rejected by Google Play.

Implement CarAppService and Session​

Step 1: Create your CarAppService​

Create a CarAppService class that serves as the entry point for Android Auto:

car/MainCarAppService.kt
class MainCarAppService : CarAppService() {
override fun createHostValidator(): HostValidator {
if (BuildConfig.DEBUG) {
// Allows the Desktop Head Unit and any other development host.
return HostValidator.ALLOW_ALL_HOSTS_VALIDATOR
}
return HostValidator.Builder(applicationContext)
.addAllowedHosts(androidx.car.app.R.array.hosts_allowlist_sample)
.build()
}
override fun onCreateSession() = MainCarSession()
}

Step 2: Implement your Session​

The Session is a LifecycleOwner and the main component for managing your Android Auto experience. Create a MainCarSession class that sets up the map, navigation, and screens. This example creates the FREE_DRIVE screen if location permission is granted, or the NEEDS_LOCATION_PERMISSION screen otherwise.

car/MainCarSession.kt
package com.mapbox.navigation.examples.androidauto.car

import android.content.Intent
import android.content.res.Configuration
import androidx.car.app.Screen
import androidx.car.app.Session
import androidx.core.content.ContextCompat
import com.mapbox.android.core.permissions.PermissionsManager
import com.mapbox.maps.extension.androidauto.MapboxCarMap
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
import com.mapbox.navigation.examples.androidauto.CarAppSyncComponent
import com.mapbox.navigation.ui.androidauto.MapboxCarContext
import com.mapbox.navigation.ui.androidauto.deeplink.GeoDeeplinkNavigateAction
import com.mapbox.navigation.ui.androidauto.screenmanager.MapboxScreen
import com.mapbox.navigation.ui.androidauto.screenmanager.MapboxScreenFactory
import com.mapbox.navigation.ui.androidauto.screenmanager.MapboxScreenManager
import com.mapbox.navigation.ui.androidauto.screenmanager.prepareScreens
import com.mapbox.navigation.ui.androidauto.search.CarSearchMode

@OptIn(ExperimentalPreviewMapboxNavigationAPI::class)
class MainCarSession : Session() {

// Tie the car map to this session and register the SDK's built-in screens.
private val mapboxCarContext: MapboxCarContext = MapboxCarContext(lifecycle, MapboxCarMap())
.prepareScreens()
.apply {
// Replace the default settings screen with this example's voice guidance setting.
mapboxScreenManager[MapboxScreen.SETTINGS] = MapboxScreenFactory {
CarSettingsScreen(this)
}
}
.customize {
// Use SearchBox for place search and apply this example's buttons and route styling.
searchMode = CarSearchMode.SearchBox
actionsStripProvider = CarMapCustomization.actionStripProvider
routeLineRendererOptions = CarMapCustomization.routeLineRendererOptions()
}

private val carMapLifecycle = CarMapLifecycle(mapboxCarContext)

init {
// Keep the phone UI and car UI in sync as navigation state changes.
CarAppSyncComponent.getInstance().setCarSession(this)

// Let the helpers manage map rendering and trip/replay sessions as the car connects or disconnects.
lifecycle.addObserver(carMapLifecycle)
lifecycle.addObserver(CarTripSessionController(mapboxCarContext))
}

override fun onCreateScreen(intent: Intent): Screen {
// Show the permission screen if needed; otherwise use the selected navigation screen.
checkLocationPermissions()
val screenKey = MapboxScreenManager.current()?.key
checkNotNull(screenKey) { "The screen key should be set before the Screen is requested." }
val screen = mapboxCarContext.mapboxScreenManager.createScreen(screenKey)
// Queue behind root-screen installation so deeplink results stay on top.
ContextCompat.getMainExecutor(carContext).execute { handleGeoDeeplink(intent) }
return screen
}

override fun onCarConfigurationChanged(newConfiguration: Configuration) {
// Update the map style when the car switches between day and night mode.
carMapLifecycle.onCarConfigurationChanged()
}

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
// Handle new navigation requests while the car session is already running.
handleGeoDeeplink(intent)
}

private fun handleGeoDeeplink(intent: Intent) {
// Geo intents can come from voice requests such as "Navigate to a coffee shop".
if (PermissionsManager.areLocationPermissionsGranted(carContext)) {
GeoDeeplinkNavigateAction(mapboxCarContext).onNewIntent(intent)
}
}

private fun checkLocationPermissions() {
// Location permission must be granted on the phone before the car can use navigation.
PermissionsManager.areLocationPermissionsGranted(carContext).also { isGranted ->
val currentKey = MapboxScreenManager.current()?.key
if (!isGranted) {
MapboxScreenManager.replaceTop(MapboxScreen.NEEDS_LOCATION_PERMISSION)
} else if (currentKey == null || currentKey == MapboxScreen.NEEDS_LOCATION_PERMISSION) {
MapboxScreenManager.replaceTop(initialMapScreen())
}
}
}

// Car App API 7+ uses one unified screen for free drive, active guidance, and route preview.
// Older hosts use separate screens, starting with free drive.
private fun initialMapScreen(): String = if (carContext.supportsUnifiedNavigation()) {
MapboxScreen.NAVIGATION
} else {
MapboxScreen.FREE_DRIVE
}
}

The session code above handles MapboxNavigation on its own and assumes you are not using it elsewhere in your app. You can use the following minimal MainActivity.kt code to test this session (the android app must still request location permissions on the mobile device):

MainActivity.kt
package com.example.cleanandroidproject

import android.Manifest
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
var hasPermission by remember { mutableStateOf(false) }

val launcher = rememberLauncherForActivityResult(
ActivityResultContracts.RequestMultiplePermissions()
) { hasPermission = it.values.any { granted -> granted } }

Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
if (hasPermission) {
Text("Permission granted!")
} else {
Button(onClick = {
launcher.launch(arrayOf(
Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION
))
}) {
Text("Grant Location Permission")
}
}
}
}
}
}

If you are using MapboxNavigation in your mobile app, refer to the Manage State Between Car and App section below.

Once this app is installed on your device, connect it to Android Auto to see your navigation app, accept location permissions, and you will see the free drive map showing your current location.

Manage State Between Car and App​

The Android Auto extension integrates with the Jetpack Lifecycle Library, allowing you to share navigation state between your mobile app and car display.

Use MapboxNavigationApp for shared state​

The MapboxNavigationApp singleton manages the lifecycle of MapboxNavigation across your app and Android Auto session. This ensures:

  • Navigation state persists when switching between phone and car displays
  • Resources are properly managed and shared
  • Location updates and route progress continue seamlessly
// In your mobile app Activity
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// Set up MapboxNavigationApp once
if (!MapboxNavigationApp.isSetup()) {
MapboxNavigationApp.setup(
NavigationOptions.Builder(this)
.accessToken(getString(R.string.mapbox_access_token))
.build()
)
}

// Attach to the activity lifecycle
MapboxNavigationApp.attach(this)
}
}

The same MapboxNavigationApp instance is automatically used in your MainCarSession, ensuring seamless state management.

For more details, see the Initialize the SDK guide and Android Auto Lifecycle documentation.

Customize Your Experience​

The Android Auto components library provides default screens and experiences for common navigation scenarios. You can use these as-is or customize them for your specific needs.

Available default screens​

The library includes pre-built screens for:

Customization options​

You can customize the car experience in several ways:

  1. Custom screens: Extend or replace default screens using the MapboxScreenManager.
  2. Map styling: Customize map appearance through MapboxCarMapLoader
  3. Navigation options: Configure routing preferences, maneuver instructions, and more
  4. UI components: Adjust colors, fonts, and layout through Android Auto templates

Refer to the Mapbox Android Auto Extension for additional map customization examples.

Troubleshooting​

App not appearing in Android Auto

If your app doesn't show up in Android Auto:

  • Verify that the meta-data and CarAppService are correctly declared in your AndroidManifest.xml
  • Check that the category in your intent filter matches your app type (androidx.car.app.category.NAVIGATION)
  • Make sure your minSdk is 23 or higher
  • Try disconnecting and reconnecting your device to Android Auto
App not appearing in a car

Navigation apps must be distributed through Google Play before they are available in a car. Google enforces this rule for safety purposes.

Use a Google Play testing track to distribute your app to a test audience before a production release.

Location permissions not working

Android Auto apps must request location permissions from the mobile device:

  • Location permissions cannot be requested directly from the car display
  • Use the MapboxScreen.NEEDS_LOCATION_PERMISSION screen to prompt users to grant permissions on their phone
  • Make sure your mobile app properly requests and handles location permissions
Navigation state not syncing between phone and car

If navigation state isn't syncing:

  • Verify that you're using MapboxNavigationApp.attach() in both your mobile Activity and CarSession
  • Make sure MapboxNavigationApp.setup() is called before attaching to any lifecycle
  • Check that you're not creating multiple MapboxNavigation instances manually
この{Type}は役に立ちましたか?