> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/android/ja/navigation/v2/llms.txt)

# Migrate to v2

Mapbox Navigation SDK for Android v2 is a major new version of the SDK. To install the latest version of the SDK, follow [the installation instructions](https://docs.mapbox.com/android/ja/navigation/v2/guides/get-started/install/) and use this guide to update your application from v1 to v2.

> **Note (warning): Pricing changes for v2**
> 
> Upgrading to v2 of the Navigation SDK for Android will change your pricing model. See the [pricing page](https://www.mapbox.com/pricing/#navigation) for details.

## Requirements

Like in v1, the Mapbox Navigation SDK for Android v2 is compatible with applications that:

-   Use the [Android SDK 21](https://developer.android.com/studio/releases/platforms#5.0) or higher.
-   Use Java 8 for `sourceCompatibility` and `targetCompatibility`, as shown in the [installation guide](https://docs.mapbox.com/android/ja/navigation/v2/guides/get-started/install/).

## Artifacts

### v1

In v1 there were two artifacts to choose from:

-   `com.mapbox.navigation:core:{version}`: To use the Navigation SDK without pre-built UI components.
-   `com.mapbox.navigation:ui:{version}`: To use the Navigation SDK with pre-built UI components, which also includes `navigation:core` as a dependency.

### v2

In Navigation SDK v2, all features are available under one Maven artifact: `com.mapbox.navigation:android:{version}`.

Besides the one grouping artifact, there are also multiple granular ones that you can pick-and-choose if you're not planning to use all the features and want to reduce the binary size of your application:

-   `com.mapbox.navigation:core` offers all the core localization features from v1.
-   `com.mapbox.navigation:ui-maps` offers the route line and arrow APIs, navigation camera, building highlight and extrusion, extended visual guidance, and other tools and features that integrate with the Mapbox Maps SDK.
-   `com.mapbox.navigation:ui-maneuver` offers the maneuver view and its APIs that replace v1's `InstructionView`.
-   `com.mapbox.navigation:ui-tripprogress` offers the trip progress view and APIs that replace v1's `SummaryBottomSheet`.
-   `com.mapbox.navigation:ui-voice` offers all necessary APIs to play voice instructions.
-   `com.mapbox.navigation:ui-speedlimit` offers the speed limit view and its APIs that replace v1's `SpeedLimitView`.

> **Related content (guide): [Modularization](https://docs.mapbox.com/android/ja/navigation/v2/guides/get-started/modularization/)**
> 
> Read more about leveraging the Navigation SDK v2's modular architecture.

## Dependencies

### Maps SDK

In v2, the Navigation SDK upgrades to Mapbox Maps SDK v10. Maps SDK v10 offers 3D maps and improved performance.

Maps SDK v10 is also a **[SEMVER major](https://semver.org/) release with breaking API changes.** If the application you are migrating uses a map, make sure you read the [Maps SDK migration guide](https://docs.mapbox.com/android/ja/maps/guides/old-versions/migrate-to-v10/) before reading the navigation-specific content below.

> **Related content (guide): [Migrate to v10](https://docs.mapbox.com/android/ja/maps/guides/old-versions/migrate-to-v10/)**
> 
> Upgrade your application from the Mapbox Maps SDK for Android v9 to v10.

## Kotlin

The Navigation SDK v2 is written 100% in [Kotlin](https://kotlinlang.org/), the official language recommended by Google for Android development. This is a change from how the previous versions were a mix of Java and Kotlin.

### Java support

While the Mapbox Navigation SDK for Android is built with Kotlin, Kotlin is 100% interoperable with Java. Applications with a Java codebase can interact properly with the public APIs exposed by Mapbox SDKs for Android.

For information on Java and Kotlin interoperability see the offical Kotlin docs:

-   [Calling Java from Kotlin](https://kotlinlang.org/docs/reference/java-interop.html#calling-java-code-from-kotlin)
-   [Calling Kotlin from Java](https://kotlinlang.org/docs/reference/java-to-kotlin-interop.html)

If you experience any issues using the Mapbox Navigation SDK for Android with Java, [contact us](https://support.mapbox.com/hc/en-us).

## Core components in v2

Core localization components in the Navigation SDK v2 are mostly unchanged architecturally, but introduce a couple breaking changes that improve the experience or clarify the behavior of the SDK to streamline the integration.

The following symbols were removed, renamed, or changed:

-   [Requesting a route](#request-a-route) with `MapboxNavigation#requestRoutes` no longer automatically sets the result as the primary route.
-   `MapboxNavigation#defaultNavigationOptionsBuilder` [has been removed](#navigation-options).
-   `OnboardRouterOptions` [was renamed](#navigation-options) to `RoutingTilesOptions`.
-   [The default directory for caches changed](#predictive-caching) from `APP_FOLDER/Offline/api.mapbox.com/$tilesVersion/tiles` to `APP_FOLDER/mbx_nav/tiles/api.mapbox.com`.

### Request a route

[`MapboxNavigation#requestRoutes`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core/-mapbox-navigation/#%5Bcom.mapbox.navigation.core%2FMapboxNavigation%2FrequestRoutes%2F%23com.mapbox.api.directions.v5.models.RouteOptions%23com.mapbox.navigation.base.route.RouterCallback%2FPointingToDeclaration%2F%5D%2FFunctions%2F-1786801705) no longer automatically sets the result as the primary route for the navigation experience. This means that **you should call [`MapboxNavigation#setRoutes`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core/-mapbox-navigation/#%5Bcom.mapbox.navigation.core%2FMapboxNavigation%2FsetRoutes%2F%23kotlin.collections.List%5Bcom.mapbox.api.directions.v5.models.DirectionsRoute%5D%23kotlin.Int%2FPointingToDeclaration%2F%5D%2FFunctions%2F-1786801705) with a result when calling `MapboxNavigation#requestRoutes`.**

This change allows for dispatching and managing multiple route requests concurrently, including canceling with [`MapboxNavigation#cancelRouteRequest`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core/-mapbox-navigation/#%5Bcom.mapbox.navigation.core%2FMapboxNavigation%2FcancelRouteRequest%2F%23kotlin.Long%2FPointingToDeclaration%2F%5D%2FFunctions%2F-1786801705).

#### v1

```kotlin
mapboxNavigation?.requestRoutes(
    RouteOptions.builder().applyDefaultParams()
        .accessToken(Utils.getMapboxAccessToken(applicationContext))
        .coordinates(originLocation.toPoint(), null, latLng.toPoint())
        .profile(DirectionsCriteria.PROFILE_DRIVING_TRAFFIC)
        .build(),
    routesReqCallback
)

private val routesReqCallback = object : RoutesRequestCallback {
    override fun onRoutesReady(routes: List<DirectionsRoute>) {
        if (routes.isNotEmpty()) {
            directionRoute = routes[0]
            navigationMapboxMap?.drawRoute(routes[0])
            startNavigation.visibility = View.VISIBLE
        } else {
            startNavigation.visibility = View.GONE
        }
    }

    override fun onRoutesRequestFailure(throwable: Throwable, routeOptions: RouteOptions) {
        // Handle error
    }

    override fun onRoutesRequestCanceled(routeOptions: RouteOptions) {
        // Handle cancelation
    }
}
```

#### v2

```kotlin
val routeOptions = RouteOptions.builder()
    .applyDefaultNavigationOptions()
    .applyLanguageAndVoiceUnitOptions(this)
    .coordinates(
        origin = origin,
        destination = destination
    )
    .layersList(listOf(mapboxNavigation.getZLevel(), null))
    .build()
mapboxNavigation.requestRoutes(
    routeOptions,
    object : RouterCallback {
        override fun onRoutesReady(
            routes: List<DirectionsRoute>,
            routerOrigin: RouterOrigin
        ) {
            mapboxNavigation.setRoutes(routes)
        }

        override fun onFailure(
            reasons: List<RouterFailure>,
            routeOptions: RouteOptions
        ) {
            // no impl
        }

        override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) {
            // no impl
        }
    }
)
```

> **Related content (guide): [Route generation](https://docs.mapbox.com/android/ja/navigation/v2/guides/turn-by-turn-navigation/route-generation/)**
> 
> Read more about requesting routes using the Navigation SDK v2.

### Navigation options

`MapboxNavigation#defaultNavigationOptionsBuilder` has been removed. In v2, the [`NavigationOptions`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core/-mapbox-navigation/#%5Bcom.mapbox.navigation.core%2FMapboxNavigation%2FnavigationOptions%2F%23%2FPointingToDeclaration%2F%5D%2FProperties%2F-1786801705) class now contains all the right defaults out of the box.

The `OnboardRouterOptions` class was renamed to [`RoutingTilesOptions`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-base/com.mapbox.navigation.base.options/-routing-tiles-options/) to better reflect the purpose. If you are using a custom base URI, dataset, or version of the tiles, those are now separate fields in the builder rather than a single URI path.

### Predictive caching

The default directory for caching navigation tiles changed:

-   **v1:** `APP_FOLDER/Offline/api.mapbox.com/$tilesVersion/tiles`
-   **v2:** `APP_FOLDER/mbx_nav/tiles/api.mapbox.com`

Caches from previous versions of the Navigation SDK are not compatible with v2.

When migrating make sure you have cleaned up the old navigation tiles cache folder to reclaim disk space:

-   Delete any folders used for caching with previous versions of the SDK including the default one.
-   `OnboardRouterOptions` enables you to specify a path where navigation tiles will be saved. If a custom directory was used, you should remove it, too.
    -   Be sure to configure the custom path *before* starting a free drive or an active guidance session if you don't want to use the default location.

> **Related content (guide): [Offline: Predictive caching](https://docs.mapbox.com/android/ja/navigation/v2/guides/advanced/offline/#predictive-caching)**
> 
> Read more about how predictive caching works in the Navigation SDK v2.

## UI components in v2

The general approach to UI components changed in v2. It exposes direct access to the *data* that powers pre-built UI components (`View`s) so you can either render that data in a Mapbox-designed UI component or a custom one. Read more in the [Approach to UI components](#approach-to-ui-components) section below.

The following v1 symbols were removed in v2:

-   The [drop-in UI provided by `NavigationView`](#navigationview-was-removed) is not available in v2.
-   The `MapRouteLineInitializedCallback` is not available in v2.

The following v1 symbols were replaced in v2:

-   `InstructionView` was replaced by the [maneuvers interface](#instructionview-was-replaced).
-   `SummaryBottomSheet` was replaced by the [trip progress interface](#summarybottomsheet-was-replaced).
-   `NavigationMapRoute` was replaced by the [route line and route arrow interfaces](#navigationmaproute-was-replaced).
-   `NavigationSpeechPlayer` was replaced by the [voice interface](#).
-   `BuildingExtrusionHighlightLayer` and `BuildingFootprintHighlightLayer` were replaced by the [buildings interface](#buildinghighlightlayer-was-replaced).
-   `GuidanceViewImageProvider` and `GuidanceViewListener` were replaced by the [junction view interface](#guidanceviewimageprovider-and-guidanceviewlistener-were-replaced).
-   `SpeedLimitView` was replaced by the [speed limit interface](#speedlimitview-was-replaced).

### Approach to UI components

Unlike in the Navigation SDK v1, where the views were exposed with no access to data, the v2 UI components now focus on separating the data transformation logic (preparing for presentation) from the actual presentation layer that updates the app's UI elements. You can now access APIs specifically catered to give you access to the data, prepared using raw data points from core modules. Based on the data retrieved from these APIs, you can choose to render it either on a Mapbox-designed `View` or your on custom view.

This separation requires additional synchronization on the app level, but gives you greater control over the user experience as your app scales. In v2 you now have control over the UI components' lifecycle to better fit them into more complex setups. This is also true for UI components that interact directly with the Mapbox `Map`. The presentation data is prepared separately from the `Map` itself, and you can dispatch updates at the correct time, depending on the `Map`'s placement in the view hierarchy and its lifecycle.

### `NavigationView` was removed

The `NavigationView` class, which provided a complete drop-in UI for turn-by-turn navigation, was removed in v2.

In v2 there are more opportunities for customization. You can now build your own UI for turn-by-turn navigation using our pre-built UI components, your own custom UI components, or some combination of the two.

#### v1

**XML layout:**

```xml
<com.mapbox.navigation.ui.NavigationView
    android:id="@+id/navigationView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />
```

**Activity:**

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    navigationView.onCreate(savedInstanceState)
    navigationView.initialize(this)
}
```

#### v2

In v2, you will need to add specific views to your layout file individually and pass data to those components manually. See the [Turn-by-turn navigation: User interface](https://docs.mapbox.com/android/ja/navigation/v2/guides/turn-by-turn-navigation/user-interface/) guide and the [Add a complete turn-by-turn experience](https://docs.mapbox.com/android/ja/navigation/v2/examples/turn-by-turn-experience/) example to see all the available Mapbox-designed UI components and how to fit them together.

> **Related content (guide): [Turn-by-turn navigation: User interface](https://docs.mapbox.com/android/ja/navigation/v2/guides/turn-by-turn-navigation/user-interface/)**
> 
> Build a user interface for a turn-by-turn navigation experience using the Mapbox Navigation SDK for Android's pre-built UI components.

> **Related content (example): [Add a complete turn-by-turn experience](https://docs.mapbox.com/android/ja/navigation/v2/examples/turn-by-turn-experience/)**
> 
> Render a complete turn-by-turn experience using all relevant Navigation SDK APIs and pre-built UI components.

### `InstructionView` was replaced

In v2, the maneuvers interface replaces v1's `InstructionView`.

The maneuvers interface has several components that are responsible for updating the current maneuver instructions with banner-related data. [`MapboxManeuverView`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maneuver/com.mapbox.navigation.ui.maneuver.view/-mapbox-maneuver-view/) allows you to quickly integrate the maneuver instructions in your app by passing it data from `MapboxManeuverApi`. But, you can also access the component parts of `MapboxManeuverView` individually to create a custom experience.

You can also instantiate and invoke [`MapboxManeuverApi`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maneuver/com.mapbox.navigation.ui.maneuver.api/-mapbox-maneuver-api/) independent of `MapboxManeuverView` to retrieve the data and render it on a custom maneuver view.

#### v1

**Drop-in UI**: This UI component was included in v1's pre-built UI (`NavigationView`). In v2 you will have to add this UI component manually.

**`InstructionView` component**: If you used the `InstructionView` directly in v1, your implementation likely looks something like this:

**XML layout:**

```xml
<com.mapbox.navigation.ui.instruction.InstructionView
    android:id="@+id/instructionView"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:gravity="top"
    android:visibility="invisible"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:visibility="visible" />
```

**Activity:**

```kotlin
// Update the instruction view when route progress changes.
private val routeProgressObserver = object : RouteProgressObserver {
    override fun onRouteProgressChanged(routeProgress: RouteProgress) {
        instructionView.updateDistanceWith(routeProgress)
    }
}
// Update the instruction view when banner instructions change.
private val bannerInstructionObserver = object : BannerInstructionsObserver {
    override fun onNewBannerInstructions(bannerInstructions: BannerInstructions) {
        instructionView.updateBannerInstructionsWith(bannerInstructions)
    }
}
```

#### v2

To replace `InstructionView`, add `MapboxManeuverView` to your layout and update data using `MapboxManeuverApi`:

**XML layout:**

```xml
<com.mapbox.navigation.ui.maneuver.view.MapboxManeuverView
    android:id="@+id/maneuverView"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:visibility="gone"
    android:layout_marginStart="8dp"
    android:layout_marginEnd="8dp"
    android:layout_marginTop="8dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent" />
```

**Activity:**

```kotlin
// Define distance formatter options
val distanceFormatterOptions = mapboxNavigation.navigationOptions.distanceFormatterOptions

// Create an instance of the MapboxManeuverApi
private val maneuverApi = MapboxManeuverApi(
    MapboxDistanceFormatter(distanceFormatterOptions)
)

// Get a list of maneuvers every time route progress changes and
// display the updated maneuver data the ManeuverView
private val routeProgressObserver = RouteProgressObserver { progress ->
    val maneuvers = maneuverApi.getManeuvers(progress)
    maneuvers.fold(
        { error -> 
            // handle error
        },
        {
            maneuverView.renderManeuvers(maneuvers)
        }
    )
}
```

For more details on adding the maneuvers UI component to your application, follow the instructions in the [Maneuver instructions](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/maneuver/) guide.

> **Related content (guide): [Maneuver instructions](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/maneuver/)**
> 
> Read more about how maneuver instructions work in the Navigation SDK v2.

> **Related content (example): [Render maneuver instructions for a route](https://docs.mapbox.com/android/ja/navigation/v2/examples/show-maneuvers/)**
> 
> Draw maneuver instructions using the Maneuver API and `MapboxManeuverView`.

### `SummaryBottomSheet` was replaced

In v2, the trip progress interface replaces v1's `SummaryBottomSheet`.

The trip progress interface has several components that are responsible for updating trip related data on to the screen. [`MapboxTripProgressView`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-tripprogress/com.mapbox.navigation.ui.tripprogress.view/-mapbox-trip-progress-view/) allows you to quickly display trip-related data in your app by passing it data from `MapboxTripProgressApi`.

For more customized requirements you can use the [`MapboxTripProgressApi`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-tripprogress/com.mapbox.navigation.ui.tripprogress.api/-mapbox-trip-progress-api/) to retrieve the data and render it on your custom trip progress view.

#### v1

**Drop-in UI**: This UI component was included in v1's pre-built UI (`NavigationView`). In v2 you will have to add this UI component manually.

**`SummaryBottomSheet` component**: If you used the `SummaryBottomSheet` directly in v1, your implementation likely looks something like this:

**XML layout:**

```xml
<com.mapbox.navigation.ui.summary.SummaryBottomSheet
    android:id="@+id/summaryBottomSheet"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:visibility="gone"
    app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior" />
```

**Activity:**

```kotlin
private val routeProgressObserver = object : RouteProgressObserver {
    override fun onRouteProgressChanged(routeProgress: RouteProgress) {
        summaryBottomSheet.update(routeProgress)
    }
}
```

#### v2

To replace `SummaryBottomSheet`, add `MapboxTripProgressView` to your layout and update data using `MapboxTripProgressApi`:

**XML layout:**

```xml
<com.mapbox.navigation.ui.tripprogress.view.MapboxTripProgressView
    android:id="@+id/tripProgressView"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:visibility="gone"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />
```

**Activity:**

```kotlin
// Get notified with progress along the currently active route.
private val routeProgressObserver = RouteProgressObserver { progress ->
    val tripProgress = tripProgressApi.getTripProgress(progress)
    binding.tripProgressView.render(tripProgress)
}

```

For more details on adding the trip progress UI component to your application, follow the instructions in the [Trip progress](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/trip-progress/) guide.

> **Related content (guide): [Trip progress](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/trip-progress/)**
> 
> Read more about how the trip progress component works in the Navigation SDK v2.

> **Related content (example): [Render trip progress information](https://docs.mapbox.com/android/ja/navigation/v2/examples/show-trip-progress/)**
> 
> Draw trip progress information using the Trip Progress API and `MapboxTripProgressView`.

### `NavigationMapRoute` was replaced

In v1, the `NavigationMapRoute` class included both a route line and route arrow indicating the next maneuver. In v2, you can interact with the route line and route arrow interfaces directly and independently. The `MapRouteLineInitializedCallback` is not available in v2.

In v2, [`MapboxRouteLineView`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.route.line.api/-mapbox-route-line-view/) allows you to quickly integrate a route line into your app by passing it data from [`MapboxRouteLineApi`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.route.line.api/-mapbox-route-line-api/) and rendering it on the `MapView`. You can also instantiate and invoke `MapboxRouteLineApi` independent of `MapboxRouteLineView` to retrieve relevant data and render a custom route line.

In v2, [`MapboxRouteArrowView`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.route.arrow.api/-mapbox-route-arrow-view/) allows you to quickly integrate a route arrow into your app by passing it data from [`MapboxRouteArrowApi`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.route.arrow.api/-mapbox-route-arrow-api/) and rendering it on the `MapView`. You can also instantiate and invoke `MapboxRouteArrowApi` independent of `MapboxRouteArrowView` to retrieve relevant data and render a custom arrow.

#### v1

**Drop-in UI**: These UI components were included in v1's pre-built UI (`NavigationView`). In v2 you will have to add these UI components manually.

**`NavigationMapRoute` class**: If you used the `NavigationMapRoute` class directly in v1, your implementation likely looks something like this:

**XML layout:**

```xml
<com.mapbox.mapboxsdk.maps.MapView
    android:id="@+id/mapView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />
```

**Activity:**

```java
navigationMapRoute = NavigationMapRoute.Builder(mapView, mapboxMap, this)
    .withVanishRouteLineEnabled(true)
    .withMapboxNavigation(mapboxNavigation)
    .build()
fun onMapReady(mapboxMap: MapboxMap) {
  if (activeRoute != null) {
      final List<DirectionsRoute> routes = listOf(activeRoute)
      navigationMapRoute.addRoutes(routes)
  }
}

private val routesReqCallback = object : RoutesRequestCallback {
    override fun onRoutesReady(routes: List<DirectionsRoute>) {
      if (!routes.isEmpty()) {
        activeRoute = routes.get[0]
        navigationMapRoute.addRoutes(routes)
      }
    }
}
```

#### v2

To replace `NavigationMapRoute`, add `MapboxRouteLineView` to your layout and update data using `MapboxRouteLineApi`:

**XML layout:**

```xml
<com.mapbox.maps.MapView
    android:id="@+id/mapView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />
```

**Activity:**

```kotlin
// Initialize route line view to draw arrows on the map
val mapboxRouteLineOptions = MapboxRouteLineOptions.Builder(this)
    .withRouteLineBelowLayerId("road-label")
    .build()
routeLineApi = MapboxRouteLineApi(mapboxRouteLineOptions)
routeLineView = MapboxRouteLineView(mapboxRouteLineOptions)

// Initialize maneuver arrow view to draw arrows on the map
val routeArrowOptions = RouteArrowOptions.Builder(this)
    .withAboveLayerId(TOP_LEVEL_ROUTE_LINE_LAYER_ID)
    .build()
}
routeArrowApi = MapboxRouteArrowApi()
routeArrowView = MapboxRouteArrowView(routeArrowOptions)

// Whenever route progress is updated, generate the route arrow to
// represent the next maneuver, update data, and pass it to the view
// class to visualize the updates on the map.
private val routeProgressObserver = RouteProgressObserver { routeProgress ->
    val arrowUpdate = routeArrowApi.addUpcomingManeuverArrow(routeProgress)
    mapboxMap.getStyle()?.apply {
        // Render the result to update the map.
        routeArrowView.renderManeuverUpdate(this, arrowUpdate)
    }
}

// Whenever the route data changes, draw the route line on the map.
private val routesObserver: RoutesObserver = RoutesObserver { routeUpdateResult ->
    // Wrap the DirectionRoute objects and pass them to the MapboxRouteLineApi
    // to generate the data necessary to draw the route(s) on the map.
    val routeLines = routeUpdateResult.routes.map { RouteLine(it, null) }
    routeLineApi.setRoutes(
        routeLines
    ) { value ->
        // The MapboxRouteLineView expects a non-null reference to
        // the map style. The data generated by the call to the
        // MapboxRouteLineApi above must be rendered by the
        // MapboxRouteLineView in order to visualize the changes
        // on the map.
        mapboxMap.getStyle()?.apply {
            routeLineView.renderRouteDrawData(this, value)
        }
    }
}
```

> **Note: Removed MapRouteLineInitializedCallback**
> 
> The `MapRouteLineInitializedCallback` is not available in v2.As soon as you call `MapboxRouteLineView#render`, the layers are added to the map synchronously, so this is the moment after which you can reference them for z-positioning other runtime layers. You can check [`RouteLayerConstants`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.route/-route-layer-constants/) for layer IDs. Also, you may call [`MapboxRouteLineView#initializeLayers`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.route.line.api/-mapbox-route-line-view/#%5Bcom.mapbox.navigation.ui.maps.route.line.api%2FMapboxRouteLineView%2FinitializeLayers%2F%23com.mapbox.maps.Style%2FPointingToDeclaration%2F%5D%2FFunctions%2F-1109541742) in advance to initialize the layers manually.

For more details on adding the route line and route arrow UI components to your application including alternative routes and vanishing route lines, follow the instructions in the [Route line](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/route-line/) and [Route arrow](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/route-arrow/) guides.

> **Related content (guide): [Route line](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/route-line/)**
> 
> Read more about how route lines work in the Navigation SDK v2.

> **Related content (guide): [Route arrow](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/route-arrow/)**
> 
> Read more about how the new route arrow component works in the Navigation SDK v2.

> **Related content (example): [Draw route lines on a map](https://docs.mapbox.com/android/ja/navigation/v2/examples/render-route-line/)**
> 
> Draw route lines on a map using the route line and route arrow APIs and the related `MapboxRouteLineView` and `MapboxRouteArrowView`.

### `Building*HighlightLayer` was replaced

In v1, there were two separate classes, `BuildingExtrusionHighlightLayer` and `BuildingFootprintHighlightLayer`, for highlighting a specific building footprint `Polygon` or extruding a footprint as a 3D building shape. In v2, the functionality associated with those classes is now handled by a single buildings interface.

In v2, [`MapboxBuildingView`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.building.view/-mapbox-building-view/) allows you to quickly integrate building-related data in your app by passing it data from [`MapboxBuildingsApi`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.building.api/-mapbox-buildings-api/) and rendering it on the `MapView`.

You can also instantiate and invoke `MapboxBuildingsApi` independent of `MapboxBuildingView` to retrieve the data and render it on your custom building view.

#### v1

**Drop-in UI**: Building highlighting was included in v1's pre-built UI (`NavigationView`). In v2 you will have to add these UI components manually.

**`BuildingExtrusionHighlightLayer` or `BuildingFootprintHighlightLayer` class**: If you used the `BuildingExtrusionHighlightLayer` or `BuildingFootprintHighlightLayer` class directly in v1, your implementation likely looks something like this:

**XML layout:**

```xml
<com.mapbox.mapboxsdk.maps.MapView
    android:id="@+id/mapView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />
```

**Activity:**

```kotlin
override fun onRouteProgressChanged(routeProgress: RouteProgress) {
    // Show the building extrusion when the device is a certain
    // number of meters away from the end of the DirectionsRoute.
    if (routeProgress.distanceRemaining < 250f) {
        mapboxMap.getStyle {
            // Initialize the Nav UI SDK's BuildingExtrusionHighlightLayer class.
            val buildingExtrusionHighlightLayer = BuildingExtrusionHighlightLayer(mapboxMap)

            buildingExtrusionHighlightLayer.queryLatLng = highlightQueryLatLng

            buildingExtrusionHighlightLayer.updateVisibility(true)
        }
    }
}
```

#### v2

To replace `BuildingExtrusionHighlightLayer` or `BuildingFootprintHighlightLayer`, add `MapView` to your layout and update data using `MapboxBuildingsApi`:

**XML layout:**

```xml
<com.mapbox.maps.MapView
    android:id="@+id/mapView"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintBottom_toBottomOf="parent" />
```

**Activity:**

```kotlin
val buildingView = MapboxBuildingView()
val buildingApi = MapboxBuildingsApi(mapboxMap)

// The callback contains a list of buildings returned as
// a result of querying the MapboxMap. If no buildings
// are available, the list is empty.
private val callback = MapboxNavigationConsumer<Expected<BuildingError, BuildingValue>> { expected ->
    expected.fold(
        {
          // Handle error
        },
        { value ->
            mapboxMap.getStyle { style ->
                buildingView.highlightBuilding(style, value.buildings)
            }
        }
    )
}

private val arrivalObserver: ArrivalObserver = object : ArrivalObserver {
    override fun onFinalDestinationArrival(routeProgress: RouteProgress) {
        buildingApi.queryBuildingOnFinalDestination(routeProgress, callback)
    }

    override fun onNextRouteLegStart(routeLegProgress: RouteLegProgress) {
        mapboxMap.getStyle { style ->
            buildingView.removeBuildingHighlight(style)
        }
    }

    override fun onWaypointArrival(routeProgress: RouteProgress) {
        buildingApi.queryBuildingOnWaypoint(routeProgress, callback)
    }
}
```

For more details on adding highlighted buildings to your application, follow the instructions in the [Building highlights](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/buildings/) guide.

> **Related content (guide): [Building highlights](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/buildings/)**
> 
> Read more about how building highlights work in the Navigation SDK v2.

> **Related content (example): [Render building extrusion on arrival](https://docs.mapbox.com/android/ja/navigation/v2/examples/show-building-extrusions/)**
> 
> Use the example to render building extrusions on arrival using building API and MapboxBuildingView.

### `SpeedLimitView` was replaced

In v2, the speed limit interface replaces v1's `SpeedLimitView`.

The speed limit interface includes several components that are responsible for rendering and updating speed limit information on to the screen. [`MapboxSpeedLimitView`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-speedlimit/com.mapbox.navigation.ui.speedlimit.view/-mapbox-speed-limit-view/) allows you to quickly display speed limit information in your app by passing it data from [`MapboxSpeedLimitApi`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-speedlimit/com.mapbox.navigation.ui.speedlimit.api/-mapbox-speed-limit-api/).

You can also instantiate and invoke `MapboxSpeedLimitApi` independent of `MapboxSpeedLimitView` to retrieve relevant data and render a custom speed limit component.

#### v1

**Drop-in UI**: This UI component was included in v1's pre-built UI (`NavigationView`). In v2 you will have to add this UI component manually.

**`SpeedLimitView` component**: If you used the `SpeedLimitView` class directly in v1, your implementation likely looks something like this:

**XML layout:**

```xml
<com.mapbox.navigation.ui.speed.SpeedLimitView
    android:id="@+id/speedLimitView"
    android:layout_width="60dp"
    android:layout_height="60dp"
    android:layout_marginTop="16dp"
    android:layout_marginStart="16dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintStart_toStartOf="parent" />
```

**Activity:**

```kotlin
private val mapMatcherResultObserver = object : MapMatcherResultObserver {
    override fun onNewMapMatcherResult(mapMatcherResult: MapMatcherResult) {
        ifNonNull(mapMatcherResult.speedLimit) {
            speedLimitView.setSpeedLimit(it)
        } ?: speedLimitView.hide()
    }
}
```

#### v2

To replace `SpeedLimitView`, add `MapboxSpeedLimitView` to your layout and update data using `MapboxSpeedLimitApi`:

**XML layout:**

```xml
<com.mapbox.navigation.ui.speedlimit.view.MapboxSpeedLimitView
    android:id="@+id/speedLimitView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginBottom="16dp"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintBottom_toBottomOf="parent">
```

**Activity:**

```kotlin
// The data in the MapboxSpeedLimitView is formatted by different
// formatting implementations. Below is the default formatter using
// default options but you can use your own formatting classes.
val speedLimitFormatter =  SpeedLimitFormatter(this)

// API used for formatting speed limit related data.
val speedLimitApi = MapboxSpeedLimitApi(speedLimitFormatter)

// Gets notified with location updates.
private val locationObserver = object : LocationObserver {
    override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) {
        val speedLimitValue = speedLimitApi.updateSpeedLimit(locationMatcherResult.speedLimit)
        binding.speedLimitView.render(speedLimitValue)
    }
}
```

For more details on adding the speed limit UI component to your application, follow the instructions in the [Speed limit](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/speed-limit/) guide.

> **Related content (guide): [Speed limit](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/speed-limit/)**
> 
> Read more about how the speed limit component works in the Navigation SDK v2.

> **Related content (example): [Render speed limit for a route](https://docs.mapbox.com/android/ja/navigation/v2/examples/show-speed-limit/)**
> 
> Render the speed limit of the current road using the Speed Limit API and MapboxSpeedLimitView.

### `GuidanceViewImageProvider` and `GuidanceViewListener` were replaced

In v2, the junction view interface replaces v1's `GuidanceViewImageProvider` and `GuidanceViewListener`.

The junction view interface has several components that are responsible for updating the junction data and displaying it on the screen. [`MapboxJunctionView`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.guidance.junction.view/-mapbox-junction-view/) allows you to quickly integrate junction views in your app.

For more customized requirements you can use the [`MapboxJunctionApi`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.guidance.junction.api/-mapbox-junction-api/) to retrieve the data and render it on your own.

### `NavigationSpeechPlayer` was replaced

In v2, the voice interface replaces v1's `NavigationSpeechPlayer`. There's no replacement for v1's `VoiceInstructionLoader` in v2.

The voice interface involves the a few components for playing prompt and detailed voice instructions. Use the [`MapboxSpeechApi`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-voice/com.mapbox.navigation.ui.voice.api/-mapbox-speech-api/) to generate an announcement based on `VoiceInstructions` objects. Then pass the resulting object to the[`MapboxVoiceInstructionsPlayer`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-voice/com.mapbox.navigation.ui.voice.api/-mapbox-voice-instructions-player/), a text-to-speech engine implementation, to be played. It will use either the `VoiceInstructionsFilePlayer` or `VoiceInstructionsTextPlayer` speech player depending on if a synthesized speech mp3 is provided or not.

#### v1

**Drop-in UI**: This interface was included in v1's pre-built UI (`NavigationView`). In v2 you will have to add it to your application manually.

**`NavigationSpeechPlayer` component**: If you used `NavigationSpeechPlayer` directly in v1, your implementation likely looks something like this:

**Activity:**

```kotlin
private lateinit var speechPlayer: NavigationSpeechPlayer

override fun onMapReady(mapboxMap: MapboxMap) {
  ...
  initializeSpeechPlayer()
}

private fun initializeSpeechPlayer() {
    val cache = Cache(File(application.cacheDir, VOICE_INSTRUCTION_CACHE), 10 * 1024 * 1024)
    val voiceInstructionLoader =
        VoiceInstructionLoader(application, Mapbox.getAccessToken(), cache)
    val speechPlayerProvider =
        SpeechPlayerProvider.Builder(
            application, Locale.US.language, true, voiceInstructionLoader
        ).build()
    speechPlayer = NavigationSpeechPlayer(speechPlayerProvider)
}

override fun onNewVoiceInstructions(voiceInstructions: VoiceInstructions) {
    speechPlayer.play(voiceInstructions)
}
```

#### v2

To replace `NavigationSpeechPlayer`:

**Activity:**

```kotlin
private lateinit var speechApi: MapboxSpeechApi
private lateinit var voiceInstructionsPlayer: MapboxVoiceInstructionsPlayer

speechApi = MapboxSpeechApi(
    this,
    getString(R.string.mapbox_access_token),
    Locale.US.language
)
voiceInstructionsPlayer = MapboxVoiceInstructionsPlayer(
    this,
    getString(R.string.mapbox_access_token),
    Locale.US.language
)

private val voiceInstructionsObserver =       
  VoiceInstructionsObserver { voiceInstructions ->
    speechApi.generate(voiceInstructions, speechCallback)
}

private val speechCallback =
  MapboxNavigationConsumer<Expected<SpeechError, SpeechValue>> { expected ->
      expected.fold(
          { error ->
              // play the instruction via fallback text-to-speech engine
              voiceInstructionsPlayer.play(
                  error.fallback,
                  voiceInstructionsPlayerCallback
              )
          },
          { value ->
              // play the sound file from the external generator
              voiceInstructionsPlayer.play(
                  value.announcement,
                  voiceInstructionsPlayerCallback
              )
          }
      )
}

private val voiceInstructionsPlayerCallback =
  MapboxNavigationConsumer<SpeechAnnouncement> { value ->
      // remove already consumed file to free-up space
      speechApi.clean(value)
}
```

For more details on adding voice instructions to your application, follow the instructions in the [Voice instructions](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/voice/) guide.

> **Related content (guide): [Voice instructions](https://docs.mapbox.com/android/ja/navigation/v2/guides/ui-components/voice/)**
> 
> Read more about how voice instructions work in the Navigation SDK v2.

> **Related content (example): [Play voice instructions for a route](https://docs.mapbox.com/android/ja/navigation/v2/examples/play-voice-instructions/)**
> 
> Use the example to play voice instructions using Speech API and Voice Instruction Player.

## Navigation camera

The Mapbox Maps SDK v10 removes the `CameraMode`s that were part of the `LocationComponent` and used to order the map camera to follow the location puck. In v2, the concepts of updating the puck's position and updating the camera's position are completely decoupled.

With Maps SDK v10, all camera properties can be manipulated independently and in parallel, so there is no limit to how you can build a custom system that tracks the puck's position in navigation scenarios. This wasn't the case with Maps SDK v9 and earlier that was the cause for the introduction of `CameraMode`s that aren't needed anymore.

The Navigation SDK v2 still allows you to integrate a camera system that tracks the puck's location and this is where [`NavigationCamera`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera/-navigation-camera/) and the concept of the [`ViewportDataSource`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-viewport-data-source/) are introduced.

`NavigationCamera` is a class that tries to simplify management of the Map's camera object in typical navigation scenarios, maintains a state ([`IDLE`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.state/-navigation-camera-state/-i-d-l-e/), [`FOLLOWING`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.state/-navigation-camera-state/-f-o-l-l-o-w-i-n-g/), or [`OVERVIEW`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.state/-navigation-camera-state/-o-v-e-r-v-i-e-w/)), and executes camera transitions. `NavigationCamera` does not produce any camera position values, the positions that the camera should transition to are generated by the `ViewportDataSource` interface. Mapbox also provides a default [`MapboxNavigationViewportDataSource`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-mapbox-navigation-viewport-data-source/) implementation that produces opinionated camera positions based on the inputted data.

The new `NavigationCamera` also replaces the legacy Navigation SDK implementations of `DynamicCamera` and `SimpleCamera` that were wrappers on top of the Maps SDK `CameraMode`s.

Below, see a few common uses of v1 `LocationComponent` camera usage examples and how they can be recreated or improved with the `NavigationCamera` and the `MapboxNavigationViewportDataSource`.

### Initialize the camera

#### v2

```kotlin
viewportDataSource = MapboxNavigationViewportDataSource(mapView.getMapboxMap())
navigationCamera = NavigationCamera(
    mapView.getMapboxMap(),
    mapView.getCameraAnimationsPlugin(),
    viewportDataSource
)
```

### Start tracking user location

#### v1

```kotlin
// Transition to the last known location sample that the
// LocationComponent knows (or do nothing if not available)
locationComponent.setCameraMode(cameraMode)
```

#### v2

```kotlin
// Provide the MapboxNavigationViewportDataSource with
// location data
viewportDataSource.onLocationChanged(location)
viewportDataSource.evaluate()

// Then initialize the `FOLLOWING` state
navigationCamera.requestNavigationCameraToFollowing()
```

In v2, the location can be obtained from the navigation's `LocationObserver` if the trip session has already been started (`MapboxNavigation#startTripSession`), or from any `LocationEngine` instance. You can also fetch the initial data directly from the [`LocationComponentPlugin`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin.locationcomponent/-location-component-plugin/)'s [`LocationProvider`](https://docs.mapbox.com/android/maps/api/latest/mapbox-maps-android/com.mapbox.maps.plugin.locationcomponent/-location-provider/).

### Track user location with bearing-matching location

#### v1

Any location update pushed to the `LocationComponent` after setting the `CameraMode` would update the camera.

#### v2

```kotlin
// Update the viewport data source to trigger a camera
// update when NavigationCamera is in a FOLLOWING state.
viewportDataSource.onLocationChanged(location)
viewportDataSource.evaluate()
```

### Track user location with locked bearing

#### v1

```kotlin
// Tracking user location while having the camera
// pointing to the north was a separate state.
locationComponent.setCameraMode(CameraMode.TRACKING_GPS_NORTH)
```

#### v2

```kotlin
// To detach the camera's bearing from the location
// use the property overrides.
viewportDataSource.followingBearingPropertyOverride(0.0)
viewportDataSource.evaluate()
```

In v2, when `followingBearingPropertyOverride` is initialized, the `MapboxNavigationViewportDataSource` will not change the value of the overridden property. This means that now you can not only lock the camera's bearing to the north while tracking but also to any other value.

To reset back to location bearing matching, clear the override.

```kotlin
viewportDataSource.followingBearingPropertyOverride(null)
viewportDataSource.evaluate()
```

### Change the zoom level, pitch, or padding

Zoom level, pitch, and padding manipulation operations have the same `before` and `now` changes, only the property name changes. Let's take zoom as an example.

#### v1

The zoom level could be changed via the `locationComponent.zoomWhileTracking` tracking method. The method only worked if `CameraMode` was already set to one of the tracking modes, otherwise, the request failed.

The zoom level could also be changed by overriding the `com.mapbox.navigation.ui.camera.Camera#zoom` method and recomputing the value that Navigation SDK requested.

#### v2

Now, the zoom level control can either be controlled by the `MapboxNavigationViewportDataSource` which will have a constant zoom level when in a free-drive mode (when there is no route present) and a dynamic zoom level when we're in an active guidance session, or overridden and controlled manually.

To let the default viewport data source manage the zoom when in an active guidance session, provide an active route via the:

```kotlin
viewportDataSource.onRouteChanged(route)
```

This is often used with the `RoutesObserver`:

```kotlin
private val routesObserver = object : RoutesObserver {
    override fun onRoutesChanged(routes: List<DirectionsRoute>) {
        if (routes.isNotEmpty()) {
            viewportDataSource.onRouteChanged(routes.first())
            viewportDataSource.evaluate()
        } else {
            viewportDataSource.clearRouteData()
            viewportDataSource.evaluate()
        }
    }
}
```

And provide the `RouteProgress` via:

```kotlin
viewportDataSource.onRouteProgressChanged(routeProgress)
```

This is often used with the `RouteProgressObserver`:

```kotlin
private val routeProgressObserver = object : RouteProgressObserver {
    override fun onRouteProgressChanged(routeProgress: RouteProgress) {
        viewportDataSource.onRouteProgressChanged(routeProgress)
        viewportDataSource.evaluate()
    }
}
```

When a route and progress are available, the viewport data source will always try to produce camera positions that best frame the upcoming maneuvers together with the user's location from `viewportDataSource.onLocationChanged(location)`.

But you can also always manually control the zoom level by overriding the zoom property:

```kotlin
viewportDataSource.followingZoomPropertyOverride(16.5)
viewportDataSource.evaluate()
```

### Clear route data

Remember to call `viewportDataSource.clearRouteData()` whenever the active route is cleared to prevent the default viewport data source from trying to frame the route's geometry that's not visible anymore. For example:

```kotlin
val routesObserver = object : RoutesObserver {
    override fun onRoutesChanged(routes: List<DirectionsRoute>) {
        if (routes.isNotEmpty()) {
            viewportDataSource.onRouteChanged(routes.first())
            viewportDataSource.evaluate()
        } else {
            viewportDataSource.clearRouteData()
            viewportDataSource.evaluate()
        }
    }
}
mapboxNavigation.registerRoutesObserver(routesObserver)
```

### Add padding

The default `MapboxNavigationViewportDataSource` does not apply any padding. You can apply the padding for framed geometries with:

```kotlin
viewportDataSource.followingPadding(padding)
viewportDataSource.evaluate()
```

and

```kotlin
viewportDataSource.overviewPadding(padding)
viewportDataSource.evaluate()
```

### Control puck's position on screen

When in the `FOLLOWING` state, the first point of the framed geometry list will be placed at the bottom edge of this padding, centered horizontally. This typically refers to the user location provided by the `viewportDataSource.onLocationChanged(location)`, if available.

Controlling the position of the puck on screen does not happen via the map's padding value anymore, but by the padding provided to the `viewportDataSource.followingPadding`. Make sure to read the inline documentation of the property.

### Camera transition collisions and navigation gestures management

Both the legacy `CameraMode`s and the new `NavigationCamera` assume full ownership of the camera object while not idle. This means that by design, any outside transition (like `MapboxMap#easeTo` and others) would compete with the internal transitions of the navigation camera features.

#### v1

Whenever any other transition was scheduled `CameraMode` would fallback to `NONE` but you could use the `LocationComponentOptions#trackingGesturesManagement` to prevent gestures like double-tap to zoom in, two-tap to zoom out, or quick sale from breaking the tracking state.

#### v2

By default, the `NavigationCamera` only falls back to the `IDLE` state when another transition interrupts the navigation camera's scheduled transition. But, in practice, developers should use the `CameraAnimationsLifecycleListener` to avoid competing transitions.

Mapbox provides two default implementations of that interface:

-   [`NavigationBasicGesturesHandler`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.lifecycle/-navigation-basic-gestures-handler/), which requests the `NavigationCamera` to `IDLE` whenever any outside transition or gesture interaction happens.
-   [`NavigationScaleGestureHandler`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.lifecycle/-navigation-scale-gesture-handler/), which requests the `NavigationCamera` to `IDLE` whenever any outside transition happens but allows for executing navigation gestures described above, same as `LocationComponentOptions#trackingGesturesManagement` did in the past.

You can enable those implementations by registering the lifecycle listeners:

```kotlin
mapView.getCameraAnimationsPlugin().addCameraAnimationsLifecycleListener(
    NavigationScaleGestureHandler(
        context,
        navigationCamera,
        mapView.getMapboxMap(),
        mapView.gestures,
        mapView.location,
        object : NavigationScaleGestureActionListener {
            override fun onNavigationScaleGestureAction() {
                viewportDataSource.options.followingFrameOptions.zoomUpdatesAllowed = false
            }
        }
    ).apply { initialize() }
)
```

### Manage zoom level updates after gesture interaction

When an allowed scale gesture interaction happens and the zoom level changes, the navigation camera would try to reset that zoom level back to the opinionated value computed via the default viewport data source provider as soon as another [`MapboxNavigationViewportDataSource#evaluate`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-mapbox-navigation-viewport-data-source/#%5Bcom.mapbox.navigation.ui.maps.camera.data%2FMapboxNavigationViewportDataSource%2Fevaluate%2F%23%2FPointingToDeclaration%2F%5D%2FFunctions%2F-1109541742) is called. To prevent that, notice the:

```kotlin
object : NavigationScaleGestureActionListener {
    override fun onNavigationScaleGestureAction() {
        viewportDataSource.options.followingFrameOptions.zoomUpdatesAllowed = false
    }
}
```

above. This prevents the viewport data source from producing any zoom values after the gesture interaction happens. Reset the [`followingFrameOptions.zoomUpdatesAllowed`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-following-frame-options/) value whenever appropriate to restore the dynamic (or overridden) zoom level updates.

### Route overview

#### v1

The `CameraMode`s did not offer any means of showing the overview of the route in the context of the position of the puck. The legacy Navigation SDK APIs did have a concept of an overview, but it also did not take into account the current user's location.

#### v2

`NavigationCamera` offers an `OVERVIEW` state available via [`navigationCamera.requestNavigationCameraToOverview()`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera/-navigation-camera/#%5Bcom.mapbox.navigation.ui.maps.camera%2FNavigationCamera%2FrequestNavigationCameraToOverview%2F%23com.mapbox.navigation.ui.maps.camera.transition.NavigationCameraTransitionOptions%23com.mapbox.navigation.ui.maps.camera.transition.NavigationCameraTransitionOptions%23com.mapbox.navigation.ui.maps.camera.transition.TransitionEndListener%3F%2FPointingToDeclaration%2F%2C+com.mapbox.navigation.ui.maps.camera%2FNavigationCamera%2FrequestNavigationCameraToOverview%2F%23kotlin.Function1%5Bcom.mapbox.navigation.ui.maps.camera.transition.NavigationCameraTransitionOptions.Builder%2Ckotlin.Unit%5D%23kotlin.Function1%5Bcom.mapbox.navigation.ui.maps.camera.transition.NavigationCameraTransitionOptions.Builder%2Ckotlin.Unit%5D%23com.mapbox.navigation.ui.maps.camera.transition.TransitionEndListener%3F%2FPointingToDeclaration%2F%5D%2FFunctions%2F-1109541742). When paired with the `MapboxNavigationViewportDataSource`, the overview state will always frame the whole route, or if the `RouteProgress` is also being provided it will frame the part of the route that is remaining. Here's how an overview with padding can be requested:

```kotlin
private val routesObserver = object : RoutesObserver {
    override fun onRoutesChanged(routes: List<DirectionsRoute>) {
        if (routes.isNotEmpty()) {
            viewportDataSource.onRouteChanged(routes.first())
            viewportDataSource.overviewPadding = overviewEdgeInsets
            viewportDataSource.evaluate()
            navigationCamera.requestNavigationCameraToOverview()
        } else {
            viewportDataSource.clearRouteData()
            viewportDataSource.evaluate()
        }
    }
}
```

Then, on each `RouteProgress` update, the camera position will be recalculated to only frame the rest of the route:

```kotlin
private val routeProgressObserver = object : RouteProgressObserver {
    override fun onRouteProgressChanged(routeProgress: RouteProgress) {
        viewportDataSource.onRouteProgressChanged(routeProgress)
        viewportDataSource.evaluate()
    }
}
```

### Frame other points

#### v1

`CameraMode`s did not allow for framing any arbitrary points in the camera's frame. We had to rely on the location and zoom level to manipulate what's visible on the map.

#### v2

The `MapboxNavigationViewportDataSource` allows for passing an arbitrary list of points and the API will make sure that all points are visible in the frame together with the provided location and route (if present), as long as the zoom level property is not overridden. Additional points that you'd like to be captured in the camera's frame can be passed via:

```kotlin
viewportDataSource.additionalPointsToFrameForFollowing(points)
viewportDataSource.evaluate()
```

This can be powerful when paired with bearing manipulation, like:

```kotlin
val center = mapboxMap.cameraState.center
viewportDataSource.additionalPointsToFrameForFollowing(listOf(lookAtPoint))
viewportDataSource.followingBearingPropertyOverride(
    TurfMeasurement.bearing(center, lookAtPoint)
)
viewportDataSource.evaluate()
```

In active guidance mode, the above operation would frame the current location, the upcoming maneuver, the `lookAtPoint` but also changes the bearing of the camera to head towards that new point.

### Options

Make sure to browse through the `MapboxNavigationViewportDataSource.options` and read about customization to the generated camera positions and how you can tweak the algorithms and change the user experience.

## Mapbox Electronic Horizon

> **Note (beta): Mapbox Electronic Horizon is in public beta**
> 
> The Mapbox Electronic Horizon feature of the Mapbox Navigation SDK is in public beta and is subject to changes, including its pricing. Use of the feature is subject to the beta product restrictions in the [Mapbox Terms of Service](https://www.mapbox.com/legal/tos). Mapbox reserves the right to end any free tier or free evaluation offers at any time and require customers to place an order to purchase the Mapbox Electronic Horizon feature, regardless of the level of use of the feature.

The electronic horizon API was changed. You can use both `callbacks` and `direct calls` to get the electronic horizon data. With callbacks you get only the most important data, which can be more efficient and save resources. If you need additional data (for example: `edge metadata`, `edge shape`, `road object metadata`, etc.) you can make a direct call.

> **Related content (guide): [Electronic horizon](https://docs.mapbox.com/android/ja/navigation/v2/guides/advanced/electronic-horizon/)**
> 
> Read more about how electronic horizon works in the Navigation SDK v2.