メインコンテンツまでスキップ

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.17.1"
implementation "com.mapbox.navigationcore:android-auto-components-ndk27:3.17.1"
// 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.17.1"
...
}

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

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.example.cleanandroidproject.car

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import androidx.annotation.RequiresPermission
import androidx.car.app.Screen
import androidx.car.app.Session
import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner
import com.mapbox.maps.MapInitOptions
import com.mapbox.maps.extension.androidauto.MapboxCarMap
import com.mapbox.navigation.ui.androidauto.map.MapboxCarMapLoader
import com.mapbox.navigation.base.options.NavigationOptions
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
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.MapboxScreenManager
import com.mapbox.navigation.ui.androidauto.screenmanager.prepareScreens
import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
import com.mapbox.navigation.core.MapboxNavigation

/**
* MainCarSession manages the lifecycle of your Android Auto app.
* This is the entry point for your app when it runs in Android Auto.
*/
class MainCarSession : Session() {

// MapboxCarMapLoader handles loading and rendering of the map in Android Auto
private val carMapLoader = MapboxCarMapLoader()

// MapboxCarMap provides the map surface for Android Auto
private val mapboxCarMap = MapboxCarMap().registerObserver(carMapLoader)

// MapboxCarContext integrates Mapbox Navigation with Android Auto lifecycle
private val mapboxCarContext = MapboxCarContext(lifecycle, mapboxCarMap)

// Navigation observer handles starting/stopping trip sessions when attached/detached
private val navigationObserver = object : MapboxNavigationObserver {
@RequiresPermission(allOf = [Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION])
override fun onAttached(mapboxNavigation: MapboxNavigation) {
// Start the trip session to begin receiving location updates
mapboxNavigation.startTripSession()
}

override fun onDetached(mapboxNavigation: MapboxNavigation) {
// Stop the trip session when detached to save battery
mapboxNavigation.stopTripSession()
}
}

init {
// Prepare the screen navigation graph for Android Auto
mapboxCarContext.prepareScreens()

lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {
// Initialize MapboxNavigationApp if not already setup
if (!MapboxNavigationApp.isSetup()) {
MapboxNavigationApp.setup(
NavigationOptions.Builder(carContext)
.build()
)
}

// Attach the car lifecycle to MapboxNavigationApp
// This ensures navigation state is managed with the car session
MapboxNavigationApp.attach(owner)

// Register the navigation observer to handle trip session lifecycle
MapboxNavigationApp.registerObserver(navigationObserver)

// Setup the MapboxCarMap with SHARED context mode
// SHARED context is required when using Android Auto widgets
mapboxCarMap.setup(
carContext,
MapInitOptions(
context = carContext,
mapOptions = com.mapbox.maps.MapOptions.Builder()
.contextMode(com.mapbox.maps.ContextMode.SHARED)
.build()
)
)
}

override fun onDestroy(owner: LifecycleOwner) {
// Clean up: unregister observer and detach from navigation
MapboxNavigationApp.unregisterObserver(navigationObserver)
MapboxNavigationApp.detach(owner)
mapboxCarMap.clearObservers()
}
})
}

/**
* Create the initial screen based on location permission status.
* Returns either the FREE_DRIVE screen or a permission request screen.
*/
override fun onCreateScreen(intent: Intent): Screen {
// Check if location permission is granted
val firstScreenKey = if (isLocationPermissionGranted()) {
// If permission granted, show the Free Drive navigation screen
MapboxScreenManager.current()?.key ?: MapboxScreen.FREE_DRIVE
} else {
// If permission not granted, show permission request screen
MapboxScreen.NEEDS_LOCATION_PERMISSION
}

// Create and return the screen using MapboxScreenManager
return mapboxCarContext.mapboxScreenManager.createScreen(firstScreenKey)
}

/**
* Handle new intents, including geo deeplinks for navigation.
* This enables voice-activated navigation ("Navigate to...")
*/
@OptIn(com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI::class)
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
// Handle geo deeplinks (e.g., geo:latitude,longitude)
GeoDeeplinkNavigateAction(mapboxCarContext).onNewIntent(intent)
}

/**
* Helper function to check if location permission is granted.
*/
private fun isLocationPermissionGranted(): Boolean {
return carContext.checkSelfPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) ==
PackageManager.PERMISSION_GRANTED
}
}

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
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}は役に立ちましたか?