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

# Navigation camera

The Mapbox Navigation SDK for Android includes a set of tools that let you combine the current user location information with the active route geometry to continuously track user movement and frame upcoming maneuvers.

In the Navigation SDK, there are two parts to managing the camera: specifying a data souce and passing that data to the navigation camera. The SDK's [`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/) produces the data in form of map camera targets, and [`NavigationCamera`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera/-navigation-camera/) consumes and executes that data to determine the camera's behavior.

> **Note: Mapbox Maps SDK for Android**
> 
> This functionality uses the Mapbox Maps SDK for Android. When you install the Navigation SDK, the Maps SDK will also be installed. You do not need to install it separately.

## Specify the data source

The Navigation SDK exposes a [`ViewportDataSource`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-viewport-data-source/) interface and its default implementation of [`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/). The viewport data source produces two types of `CameraOptions` objects encapsulated in the [`ViewportData`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-viewport-data/) object:

-   **`cameraForFollowing`**: frames the user location in the following mode
-   **`cameraForOverview`**: frames the remaining part of the route in the overview mode

### Initialize data source

To initialize the default viewport data source, create an instance of `MapboxNavigationViewportDataSource` and pass it your map:

```kotlin
// initialize Viewport Data Source
viewportDataSource = MapboxNavigationViewportDataSource(mapboxMap)
```

### Provide data

For the viewport data source to produce meaningful camera positions, you need to provide the location, route, or route progress data. Do this by calling a set of methods with available data updates.

For route updates, use [`RoutesObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.directions.session/-routes-observer/):

```kotlin
private val routesObserver = RoutesObserver { routes ->
    if (routes.isNotEmpty()) {
        viewportDataSource.onRouteChanged(routes.first())
        viewportDataSource.evaluate()
    } else {
        viewportDataSource.clearRouteData()
        viewportDataSource.evaluate()
    }
}
```

For location updates, use [`LocationObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.trip.session/-location-observer/):

```kotlin
private val locationObserver = object : LocationObserver {
    override fun onRawLocationChanged(rawLocation: Location) {
        // not handled
    }
    override fun onEnhancedLocationChanged(
        enhancedLocation: Location,
        keyPoints: List<Location>
    ) {
        viewportDataSource.onLocationChanged(enhancedLocation)
        viewportDataSource.evaluate()
    }
}
```

For route progress updates, use [`RouteProgressObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.trip.session/-route-progress-observer/):

```kotlin
private val routeProgressObserver = RouteProgressObserver { routeProgress ->
    viewportDataSource.onRouteProgressChanged(routeProgress)
    viewportDataSource.evaluate()
}
```

Whenever you provide a new piece of data, remember to call [`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%2F1877948299) so that the camera targets stored in the `ViewportData` are regenerated and relevant observers are called. With the continuous stream of latest location and routing data the class will be able to keep producing relevant camera targets to best frame the available geometries.

> **Note: Initialize the viewport data source before usage**
> 
> By itself, the `MapboxNavigationViewportDataSource` has no access to location or route data and will initialize at coordinates `(0.0, 0.0)`. Make sure to manually initialize the source with the latest available user location update before executing any transitions.

The `MapboxNavigationViewportDataSource` can work with and without a route object, both for [free-drive and turn-by-turn](https://docs.mapbox.com/android/navigation/v2/guides/#types-of-navigation) navigation experiences. When the route reference is available, it will continuously change zoom level to frame the upcoming maneuver together with the user location. When there's no route, it will stay at a constant zoom level while tracking the user location.

> **Note: Clear route reference when switching between types of navigation**
> 
> Whenever an Active Guidance trip finishes, make sure to call [`MapboxNavigationViewportDataSource#clearRouteData`](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%2FclearRouteData%2F%23%2FPointingToDeclaration%2F%5D%2FFunctions%2F1877948299) and then `MapboxNavigationViewportDataSource#evaluate` to remove route and route progress context from camera targets calculations.

### Customize the data source

The viewport data source is one of the main contributors to how your navigation experience will be presented on the map.

#### Padding

You can provide padding for both the following and overview frames, which will make sure that framed geometries will be presented at the designated space on the map and not overlap with other UI elements, for example:

```kotlin
val pixelDensity = context.resources.displayMetrics.density
viewportDataSource.followingPadding = EdgeInsets(
    180.0 * pixelDensity,
    40.0 * pixelDensity,
    150.0 * pixelDensity,
    40.0 * pixelDensity
)
viewportDataSource.overviewPadding = EdgeInsets(
    140.0 * pixelDensity,
    40.0 * pixelDensity,
    120.0 * pixelDensity,
    40.0 * pixelDensity
)
```

Make sure to use pixel-density adjusted padding values to have a consistent experience on different devices.

##### Overview frame

The padded overview frame will contain the entirety of the route provided via `MapboxNavigationViewportDataSource#onRouteChanged` (or the rest of the current leg if `MapboxNavigationViewportDataSource#onRouteProgressChanged` is also available) and any additional points you've specified using `MapboxNavigationViewportDataSource#additionalPointsToFrameForOverview`.

##### Following frame

For the following frame, **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's location provided via `MapboxNavigationViewportDataSource#onLocationChanged`, if available. The first points positioning can be influenced by [`FollowingFrameOptions.maximizeViewableGeometryWhenPitchZero`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-following-frame-options/maximize-viewable-geometry-when-pitch-zero.html) when there are at least two points available for framing.

> **Note: Control the position of the user location indicator on screen**
> 
> When user location samples are provided to the viewport data source, you control the position of the user location indicator on screen by moving the bottom edge of the padding and changing the width of the padding.

> **Note: Geometries below bottom edge of the padding**
> 
> The focal point of the camera in following mode is placed on top of the user location indicator, which is positioned at the bottom edge of the padding so the SDK cannot frame any geometries that are below the bottom edge of the padding. Any geometries below the bottom edge are ignored from frame generation.

The frame will contain the remaining part of the current `LegStep` of the route provided via `MapboxNavigationViewportDataSource#onRouteChanged`. If the `RouteProgress` is not available, the frame will focus on the location sample from `MapboxNavigationViewportDataSource#onLocationChanged` with `FollowingFrameOptions.maxZoom` zoom and `FollowingFrameOptions.defaultPitch`.

#### Options

You can adjust the way location and geometries are framed within the padding by changing the `MapboxNavigationViewportDataSourceOptions`, which are accessible via [`MapboxNavigationViewportDataSource#options`](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/options.html). For example, to change the default pitch during following:

```kotlin
viewportDataSource.options.followingFrameOptions.defaultPitch = 35.0
viewportDataSource.evaluate()
```

To understand all possible camera behaviors, see the available properties for both [`FollowingFrameOptions`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-following-frame-options/) and [`OverviewFrameOptions`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data/-overview-frame-options/).

## Set up the navigation camera

[`NavigationCamera`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera/-navigation-camera/) is a class that simplifies management of the map's camera object in typical navigation scenarios. It ingests camera targets produced by the `ViewportDataSource` and executes map camera transitions to those targets.

> **Related content (example): [Example of Navigation Camera integration](https://github.com/mapbox/mapbox-navigation-android-examples/blob/main/app/src/main/java/com/mapbox/navigation/examples/standalone/camera/ShowCameraTransitionsActivity.kt)**
> 
> Learn how to integrate `NavigationCamera` together with the `MapboxNavigationViewportDataSource` and their data streams in a navigation app.

### Initialize navigation camera

To initialize the navigation camera, create an instance of `NavigationCamera` and pass it your map, camera, and viewport data source:

```kotlin
// initialize Navigation Camera
navigationCamera = NavigationCamera(
    mapboxMap,
    binding.mapView.camera,
    viewportDataSource
)
```

### Camera state

`NavigationCamera` maintains a state of any of the following:

```kotlin
enum class NavigationCameraState {
    IDLE,
    TRANSITION_TO_FOLLOWING,
    FOLLOWING,
    TRANSITION_TO_OVERVIEW,
    OVERVIEW
}
```

You can change the camera state at any time by calling either `requestNavigationCameraToFollowing()` or `requestNavigationCameraToOverview()`, and executing camera transitions.

```kotlin
navigationCamera.requestNavigationCameraToFollowing()
navigationCamera.requestNavigationCameraToOverview()
```

`NavigationCamera` does not produce any camera position values, the positions that the camera should transition to are generated by the `ViewportDataSource` interface. The default implementation of that interface is [described above](#specify-the-data-source).

> **Note: Provide data before executing transitions**
> 
> The default `MapboxNavigationViewportDataSource` initializes empty. Make sure to first provide the data to the viewport data source, check it, and only then request a `following` or `overview` state with `NavigationCamera`.

Once `NavigationCamera` is in a `following` or `overview` state, it will keep listening for updates from the viewport data source and execute transitions to new targets whenever the data source is evaluated.

To stop listening for updates, use `requestNavigationCameraToIdle()`:

```kotlin
navigationCamera.requestNavigationCameraToIdle()
```

## Debugging

> **Note (beta): Experimental feature**
> 
> This feature is experimental and subject to change.

Use [`MapboxNavigationViewportDataSourceDebugger`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavui-maps/com.mapbox.navigation.ui.maps.camera.data.debugger/-mapbox-navigation-viewport-data-source-debugger/) to attach a debugger to both `MapboxNavigationViewportDataSource` and `NavigationCamera` that will draw on top of the map the padding values and geometries that the viewport data source tries to frame.

```kotlin
val debugger = MapboxNavigationViewportDataSourceDebugger(
    context,
    mapView,
    layerAbove = "road-label"
).apply {
    enabled = true
}
viewportDataSource = MapboxNavigationViewportDataSource(
    mapView.getMapboxMap()
)
viewportDataSource.debugger = debugger
navigationCamera = NavigationCamera(
    mapView.getMapboxMap(),
    mapView.camera,
    viewportDataSource
)
navigationCamera.debugger = debugger
```

For the correct operation, the same exact instance of the `MapboxNavigationViewportDataSourceDebugger` has to be provided to both the `MapboxNavigationViewportDataSource` and `NavigationCamera`.