-
Notifications
You must be signed in to change notification settings - Fork 320
1.0 Navigation SDK Migration Guide
“The Mapbox Navigation SDK” is actually comprised of two SDKs that can be used to integrate navigation into your Android project:
- The Navigation SDK. This is where core logic lives for generating routes, tracking route progress, delivering turn-by-turn instructions, and other actions related to Directions API information.
- The Navigation UI SDK. Built on top of the Navigation SDK, the Navigation UI SDK consumes data from the Navigation SDK and arranges it in default UI components that have various customizable options.
This guide provides basic information on the 1.0 version of the Navigation SDK and how to adjust your Android project from using a pre-1.0 version of the Navigation SDK, to using a version that’s 1.0 or higher. Not all of the Navigation SDK’s new 1.0 features are covered in this guide. This guide assumes what parts of the Navigation SDK would be in a simple and barebones navigation Android project.
Read the 1.0 Navigation SDK’s entire documentation at http://docs.mapbox.com/android/beta/navigation/overview
The 1.0 release of the SDK debuts code for a vastly more straightforward way of building a navigation experience. The SDK brings completely new features, including:
-
a higher accuracy location engine that functions even in low GPS quality scenarios such as tunnels or overpasses.
-
free drive capabilities. Also known as passive navigation, drivers can now navigate in a mode without a destination entered.
-
a comprehensive modular and extensible architecture exposing stable and performant APIs that are hard to misuse, allowing your developers options to integrate custom analytics or a custom router. As long as these modules follow the API definitions, they can be customized and easily integrated.
The 1.0 Navigation SDK is written 100% in Kotlin. This is a change from how the pre-1.0 versions were written in Java.
- https://kotlinlang.org/docs/reference/java-interop.html#calling-java-code-from-kotlin and https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html have helpful information on Java and Kotlin interoperability.
Please see https://docs.mapbox.com/android/beta/navigation/overview/#installation for the most up-to-date instructions on installing the 1.0 Navigation SDK.
The Mapbox Android Navigation team has decided to bump the minimum Android SDK version to 19 for the 1.0 SDK. Please make sure that your project’s minSdkVersion is set to 19 or higher in your application-level build.gradle file.
android {
defaultConfig {
...
minSdkVersion 19
…
…
}
}Please see the Navigation SDK for Android's section for more information on pricing and billing. Depending on what you're building with the 1.0 Navigation SDK for Android, your project may be eligible for alternative pricing options.
NavigationOptions is the 1.0 version of the pre-1.0 MapboxNavigationOptions class. NavigationOptions has a Builder class and you can use the Builder class to explore what methods are available for setting specific options such as your preferred units to use for distance and time.
val navigationOptions = NavigationOptions.Builder()
.distanceFormatter(MapboxDistanceFormatter.builder()
.withRoundingIncrement(Rounding.INCREMENT_FIFTY)
.withUnitType(VoiceUnit.METRIC)
.build(this))
.timeFormatType(TWELVE_HOURS)
.build()Once created, the NavigationOptions object should be used as a method parameter when initializing the MapboxNavigation class.
More information about the NavigationOptions class can be found at https://docs.mapbox.com/android/beta/navigation/overview/#set-navigationoptions.
Creating a MapboxNavigation object is the first step in interacting with and customizing a navigation session. It's used to request routes, register various Navigation SDK observers, and make other navigation-related decisions. It needs a context object as well as a valid Mapbox access token.
Create and use only one instance of this class in your project.
val navigation = MapboxNavigation.defaultNavigationOptions(context, MAPBOX_ACCESS_TOKEN)Alternatively, use the MapboxNavigation's constructor if you'd like to set the various options yourself:
val mapboxNavigation = MapboxNavigation(
applicationContext,
mapboxNavigationOptions,
LocationEngineProvider.getBestLocationEngine(this)
)Don’t forget to call mapboxNavigation.onDestroy() in the lifecycle onDestroy() part of your Android project.
override fun onDestroy() {
super.onDestroy()
mapboxNavigation.onDestroy()
}More information about the MapboxNavigation class can be found at https://docs.mapbox.com/android/beta/navigation/overview/#create-a-mapboxnavigation-object
After you’ve created a mapboxNavigation object, you can use its requestRoutes() method. The method requires a built RouteOptions object. The RouteOptions class has convenient methods for setting the various route parameters that can be found at https://docs.mapbox.com/api/navigation/#directions. Despite the many builder methods, only accessToken, origin, and destination are required to build a valid route request.
mapboxNavigation.requestRoutes(
RouteOptions.builder()
.accessToken(MAPBOX_TOKEN)
.coordinates(mutableListOf(originPoint, destinationPoint))
.geometries(RouteUrl.GEOMETRY_POLYLINE6)
.profile(RouteUrl.PROFILE_DRIVING)
.build()
)More information at https://docs.mapbox.com/android/beta/navigation/overview/route-generation/#request-a-route
The mapboxNavigation.requestRoutes() method’s only required parameter is the built RouteOptions object. An optional second parameter is a RoutesRequestCallback interface object. The 1.0 Navigation SDK’s RoutesRequestCallback interface provides methods that inform you about the route request status.
val routesReqCallback = object : RoutesRequestCallback {
override fun onRoutesReady(routes: List<DirectionsRoute>) {
}
override fun onRoutesRequestFailure(throwable: Throwable, routeOptions: RouteOptions) {
}
override fun onRoutesRequestCanceled(routeOptions: RouteOptions) {
}
}You’ll typically want navigationMapboxMap to draw the first route returned inside of onRoutesReady():
private val routesReqCallback = object : RoutesRequestCallback {
override fun onRoutesReady(routes: List<DirectionsRoute>) {
if (routes.isNotEmpty()) {
navigationMapboxMap?.drawRoute(routes[0])
}
}
override fun onRoutesRequestFailure(throwable: Throwable, routeOptions: RouteOptions) {
}
override fun onRoutesRequestCanceled(routeOptions: RouteOptions) {
}
}More information at https://docs.mapbox.com/android/beta/navigation/overview/route-generation/#route-request-status
Use the 1.0 Navigation SDK’s RouteObserver interface if you want to know when the routes list has changed. Registering a RouteObserver interface object via mapboxNavigation.registerRouteObserver(routeObserver) is one way to do it. Alternatively, you can implement the interface, register the interface with mapboxNavigation.registerRouteObserver(this), and override the interface’s single method.
private val routeObserver = object : RouteObserver {
override fun onRoutesChanged(routes: List<DirectionsRoute>) {
navigationMapRoute?.addRoutes(routes)
}
}More information at https://docs.mapbox.com/android/beta/navigation/overview/route-generation/#changed-routes
ProgressChangeListener is the pre-1.0 interface callback for receiving information about where the device is along the directions route in turn-by-turn navigation mode.
RouteProgressObserver is the 1.0 Navigation SDK’s equivalent interface. This new interface only has one method, which is onRouteProgressChanged(). The interface still returns a RouteProgress object.
private val routeProgressObserver = object : RouteProgressObserver {
override fun onRouteProgressChanged(routeProgress: RouteProgress) {
}
}Alternatively, you can implement the interface, register the interface with mapboxNavigation.registerRouteProgressObserver(this), and override the interface’s method.
Don’t forget to unregister the interface!
override fun onStop() {
super.onStop()
mapView.onStop()
mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
}More information at https://docs.mapbox.com/android/beta/navigation/overview/route-progress/
FasterRouteObserver is the 1.0 Nav SDK’s way to listen to the retrieval of a faster DirectionsRoute.
The observer object:
private val fasterRouteObserver = object : FasterRouteObserver {
override fun restartAfterMillis() = FasterRouteObserver.DEFAULT_INTERVAL_MILLIS
override fun onFasterRoute(
currentRoute: DirectionsRoute,
alternatives: List<DirectionsRoute>,
isAlternativeFaster: Boolean
) {
}
}Attach the observer interface:
mapboxNavigation.attachFasterRouteObserver(fasterRouteObserver)Don’t forget to detach the observer interface!
override fun onStop() {
super.onStop()
mapView.onStop()
mapboxNavigation.detachFasterRouteObserver()
}More information at https://docs.mapbox.com/android/beta/navigation/overview/faster-route
1.0 introduces a new interface listener to use for receiving device location updates. The LocationObserver’s two methods will fire whenever the device changes location. If you’re using the Navigation UI SDK, you don’t have to use the LocationObserver interface for a standard 1.0 Navigation SDK setup. The Navigation UI SDK automatically handles displaying the device location puck on the map. The Navigation SDK doesn't include any UI pieces at all, except for the sticky foreground notification.
The LocationObserver interface is optional and is available in case you want to track device location yourself and do anything with the returned Location object’s coordinates or altitude values.
private val locationObserver = object : LocationObserver {
override fun onRawLocationChanged(rawLocation: Location) {
}
override fun onEnhancedLocationChanged(
enhancedLocation: Location,
keyPoints: List<Location>
) {
}
}Register the observer with the MapboxNavigation object:
mapboxNavigation.registerLocationObserver(locationObserver)Don’t forget to unregister the interface!
override fun onStop() {
super.onStop()
mapView.onStop()
mapboxNavigation.unregisterLocationObserver(locationObserver)
}If you use the LocationObserver interface, be sure to also pass false through the LocationComponent’s useDefaultLocationEngine() method so that you can eventually pass the onEnhancedLocationChanged() callback’s Location object to the LocationComponent. Once you pass the Location object, the Navigation SDK will use the LocationComponent to move the device location puck to the appropriate place on the map and make other adjustments.
mapboxMap.setStyle(Style.MAPBOX_STREETS) { style ->
locationComponent = mapboxMap.locationComponent.apply {
activateLocationComponent(
LocationComponentActivationOptions.builder(this, style)
.useDefaultLocationEngine(false)
.build()
)
cameraMode = CameraMode.TRACKING
isLocationComponentEnabled = true
}
}Passing the LocationComponent the Location object returned by LocationObserver:
private val locationObserver = object : LocationObserver {
override fun onRawLocationChanged(rawLocation: Location) {
}
override fun onEnhancedLocationChanged(
enhancedLocation: Location,
keyPoints: List<Location>
) {
locationComponent?.forceLocationUpdate(rawLocation)
}
}More information at https://docs.mapbox.com/android/beta/navigation/overview/device-location
Again, not all of the Navigation SDK’s new features are covered in this migration guide. This guide makes assumptions about what parts of the Navigation SDK a simple and barebones navigation project will use.
Read the Navigation SDK’s complete documentation at http://docs.mapbox.com/android/beta/navigation/overview.
If you’ve got any questions, please reach out to the Mapbox team via https://github.com/mapbox/mapbox-navigation-android/issues/new.