Skip to main content

Get started

Review the Google developer documentation to learn how to develop apps for Android Auto. You should also review the functionality checklist to make sure your app meets the Google Play requirements. This guide will help you add Mapbox Navigation to a new or existing app. It will also refer you to other documentation when necessary. If you are looking to use Mapbox Maps in Android Auto without Mapbox Navigation, refer to the Mapbox Android Auto Extension.

Feel free to request changes, or open pull requests.

1. Set up MAPBOX_DOWNLOADS_TOKEN

Refer to the Mapbox Navigation SDK install guide to get permission to download SDKs. If you have already set up a MAPBOX_DOWNLOADS_TOKEN, you can skip this step.

2. Make sure minSdk 23+

Android Auto is only compatible with phones running Android 6.0 (API level 23) or higher.

android {
defaultConfig {
minSdk 23
...
}

3. Add the dependency

Add the library dependency to your build.gradle. The library version matches Navigation SDK version, they have the same release cadence. This way, you should not worry about versions compatibility, alight versions of the both SDK's and that would work.

dependencies {
implementation "com.mapbox.navigation:android-auto-components:3.1.0-rc.1"
}

4. Add your meta-data and CarAppService

You need to add elements to the application in your AndroidManifest.xml. The meta-data specifies support for Android Auto or Android Automotive. You do not need to add the automotive_app_desc because it is included by the Mapbox Navigation Android Auto SDK. The CarAppService has an intent-filter to specify the category of your app. If you specify the wrong meta-data or category, your app will be rejected by Google Play.

<!-- metadata if your app supports Android Auto -->
<meta-data
android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc" />

<!-- metadata if your app supports Android Automotive -->
<meta-data
android:name="com.android.automotive"
android:resource="@xml/automotive_app_desc" />

<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>
class MainCarAppService : CarAppService() {
override fun createHostValidator() = HostValidator.ALLOW_ALL_HOSTS_VALIDATOR

override fun onCreateSession() = MainCarSession()
}

5. Managing state between the car and app

When integrating Android Auto with your application, an issue you are likely to face, is determining when the car or app is in use. Luckily, the car and app have something in common, The Jetpack Lifecycle Library. To create Lifecycle aware services, we have introduced MapboxNavigationApp. This is built on top of the Lifecycle. It is recommended to set up MapboxNavigation as explained in Initialize the SDK guide before following the steps outlined below. Also, refer to Android Auto Lifecycle documentation for questions about Session and Screen Lifecycle.

6. Implement your Session

The Session is a LifecycleOwner and serves as the entry point for Android Auto. This is where you can create experiences that fit your domain and complete the functionality checklist.

  • Set up the MapboxCarMap
  • Set up MapboxNavigationApp
  • Prepare the MapboxScreenManager
  • Create an experience for accepting location permissions
  • Update the Map style when the configuration changes
  • Parse onNewIntent for voice activated navigation

The following are working examples. Use them as a guide to create your own experiences.

The following is an example of what your Session can look like.

class MainCarSession : Session() {

// Create the MapboxCarContext and MapboxCarMap. You can use them to build
// your own customizations.
private val carMapLoader = MapboxCarMapLoader()
private val mapboxCarMap = MapboxCarMap().registerObserver(carMapLoader)
private val mapboxCarContext = MapboxCarContext(lifecycle, mapboxCarMap)

init {
// Attach the car lifecycle to MapboxNavigationApp.
// You do not need to detach because it will interally detach when the lifecycle is detroyed.
// But you will need to unregister any observer that was registered within the car lifecycle.
MapboxNavigationApp.attach(lifecycleOwner = this)

// Prepare a screen graph for the session. If you want to customize
// any screens, use the MapboxScreenManager.
mapboxCarContext.prepareScreens()

// At any point you can customize the MapboxCarOptions available.
mapboxCarContext.customize {
// You need to tell the car notification which app to open when a
// user taps it.
notificationOptions = MapboxCarNotificationOptions.Builder()
.startAppService(MainCarAppService::class.java)
.build()
}

lifecycle.addObserver(object : DefaultLifecycleObserver {
override fun onCreate(owner: LifecycleOwner) {
// Ensure MapboxNavigationApp has an access token and a application context.
// This can also be done in Application.onCreate. Use the isSetup condition in case the
// options have been set by a separate lifecycle event, like an Activity onCreate.
if (!MapboxNavigationApp.isSetup()) {
MapboxNavigationApp.setup(
NavigationOptions.Builder(carContext)
.accessToken(Utils.getMapboxAccessToken(carContext))
.build()
)
}

// Once a CarContext is available, pass it to the MapboxCarMap.
mapboxCarMap.setup(carContext, MapboxInitOptions(context = carContext))
}

override fun onDestroy(owner: LifecycleOwner) {
// The car session is destroyed you so should remove any observers. This
// will ensure every MapboxCarMapObserver.onDetached is called.
mapboxCarMap.clearObservers()
}
})
}

override fun onCreateScreen(intent: Intent): Screen {
// You can control the MapboxScreenManager from a mobile device, in which case you will
// want to get the first screen from there. Most of the MapboxScreens require location
// permission and the default NEEDS_LOCATION_PERMISSION will assume location permissions
// are requested from a mobile app.
val firstScreenKey = if (PermissionsManager.areLocationPermissionsGranted(carContext)) {
MapboxScreenManager.current()?.key ?: MapboxScreen.FREE_DRIVE
} else {
MapboxScreen.NEEDS_LOCATION_PERMISSION
}

// Use the MapboxScreenManager to keep track of the screen stack.
return mapboxCarContext.mapboxScreenManager.createScreen(firstScreenKey)
}

override fun onCarConfigurationChanged(newConfiguration: Configuration) {
// Notify a map loader of the dark mode style change
carMapLoader.updateMapStyle(carContext.isDarkMode)
}

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)

// Use the GeoDeeplinkNavigateAction or GeoDeeplinkParser to parse
// incomming intents and change the navigation screen
GeoDeeplinkNavigateAction(mapboxCarContext).onNewIntent(intent)
}
}

7. Customize your experience

To provide a default experience for Android Auto, we have prepared default Screens with default experiences. See the screenshot available in the following sections, that should give you an idea for what is included inside this library. You are free to use what is available. If you are unable to build your custom experience, make requests so we can build an SDK that helps you build with Mapbox!

Was this page helpful?