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

# Route updates and rerouting

The Navigation SDK has built-in logic to make sure your users are on the best route as traffic conditions change or the user goes off route. This includes:

-   **Off-route detection** to get users back on track if they have strayed from the current route.
-   **Route refresh** to make sure the current route is still a viable route.
-   **Alternative routes** to offer users alternative routes as available.

## Off-route detection

The Navigation SDK detects when a device strayed from a route it was navigating. When a device is determined to be off route, the SDK automatically requests a redirected route by default. If the reroute request is successful, the new route will be delivered via [`RoutesObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.directions.session/-routes-observer/).

If you want to customize your application's behavior when a user goes off route, you can observe the event using `OffRouteObserver` or control what triggers an off-route event using `NavigationRerouteController`.

### Observe off-route events

The [`OffRouteObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.trip.session/-off-route-observer/) interface provides a boolean whenever the Navigation SDK is in turn-by-turn navigation and is off route. When the device is determined to be off route, the Navigation SDK will automatically request a new route.

To listen for changes in the off-route state, create the `OffRouteObserver` interface object:

```kotlin
val offRouteObserver = object : OffRouteObserver {
    override fun onOffRouteStateChanged(offRoute: Boolean) {
      // do something when the off route state changes
    }
}
```

> **Note**
> 
> This interface doesn't work with free-drive mode because it requires that the user is following a defined route.

Then, register the `OffRouteObserver` object with [your already-instantiated `MapboxNavigation` object](https://docs.mapbox.com/android/ja/navigation/v2/guides/get-started/initialization/#create-the-mapboxnavigation-object).

```kotlin
override fun onStart() {
	super.onStart()
	mapView.onStart()
    mapboxNavigation.registerOffRouteObserver(offRouteObserver)
}
```

Don't forget to unregister the `OffRouteObserver` interface:

```kotlin
override fun onStop() {
	super.onStop()
  	mapView.onStop()
  	mapboxNavigation.unregisterOffRouteObserver(offRouteObserver)
}
```

### Customize off-route triggers

To customize the conditions that trigger off-route conditions, you can provide a custom [`NavigationRerouteController`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.reroute/-navigation-reroute-controller/):

```kotlin
mapboxNavigation.setRerouteController(object : NavigationRerouteController {
    // set the conditions that will trigger off-route conditions
})
```

Or, you can disable off-route detection entirely by passing `null`:

```kotlin
mapboxNavigation.setRerouteController(null)
```

### Observe changes to reroute states

Whether you are using the default triggers or a custom `NavigationRerouteController`, the controller produces reroute state updates that can be listened to with the [`RerouteStateObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.reroute/-reroute-controller/-reroute-state-observer/):

```kotlin
mapboxNavigation.getRerouteController()?.registerRerouteStateObserver(object : RerouteStateObserver {
    // do something when the reroute state changes
})
```

> **Note**
> 
> The default reroute controller does not retry if the reroute fails. You can create a custom `NavigationRerouteController` if you would like to retry the reroute request if the first request fails.

## Route refresh

Traffic conditions along a route can change while you're navigating, causing the initial route information to be out of date. The Navigation SDK can refresh a route to make sure your users stay on track as they progress along a route.

Route refresh interval is configured with the [`RouteRefreshOptions.intervalMillis`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-base/com.mapbox.navigation.base.route/-route-refresh-options/#%5Bcom.mapbox.navigation.base.route%2FRouteRefreshOptions%2FintervalMillis%2F%23%2FPointingToDeclaration%2F%5D%2FProperties%2F42535876) parameter. By default, the SDK will refresh the current route every five minutes, and if the refresh request is successful, an updated route will be delivered via [`RoutesObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.directions.session/-routes-observer/).

> **Note**
> 
> The Navigation SDK will only refresh a route when `RouteOptions.enableRefresh` is true.

## Alternative routes

Traffic conditions along a route can change while you're navigating, causing the initial route to no longer be as fast as it was when you departed. The Navigation SDK can provide alternative routes to make sure your users are on the best route.

The Navigation SDK is continuously looking for route alternatives and triggers request based on two internal conditions:

1.  Passing a fork point with an existing alternative route - the existing alternative becomes invalid and the Navigation SDK requests new alternative routes.
2.  There are no tracked alternative routes - the Navigation SDK requests alternatives with the interval [`RouteAlternativesOptions.intervalMillis`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-base/com.mapbox.navigation.base.route/-route-alternatives-options/#%5Bcom.mapbox.navigation.base.route%2FRouteAlternativesOptions%2FintervalMillis%2F%23%2FPointingToDeclaration%2F%5D%2FProperties%2F42535876) until it gets successful response with valid alternatives, default interval is 5 minutes.

New routes will be delivered via [`NavigationRouteAlternativesObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.routealternatives/-navigation-route-alternatives-observer/).

> **Note**
> 
> The Navigation SDK will only look for alternative routes when the device is traveling along a route in turn-by-turn navigation mode and there is at least one [`NavigationRouteAlternativesObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.routealternatives/-navigation-route-alternatives-observer/).

### Observe alternative route events

The Navigation SDK's [`NavigationRouteAlternativesObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.routealternatives/-navigation-route-alternatives-observer/on-route-alternatives.html) interface alerts you when the Navigation SDK detects alternative routes. The observer is also called when user passes the fork intersection with an alternative route, making the alternative invalid and ready to be cleaned up. In the code snippet below:

-   `routeProgress` is the current route's progress.
-   `alternatives` is a list of alternative routes, can be empty.
-   `routerOrigin` describes which router was used to get alternative routes.

```kotlin
val routeAlternativesObserver = object : NavigationRouteAlternativesObserver {
	override fun onRouteAlternatives(routeProgress: RouteProgress, alternatives: List<NavigationRoute>, routerOrigin: RouterOrigin) 
    {
        val newRoutes = mutableListOf<NavigationRoute>().apply {
            add(routeProgress.navigationRoute)
            addAll(alternatives)
        }
        mapboxNavigation.setNavigationRoutes(newRoutes)
    }

    override fun onRouteAlternativesError(error: RouteAlternativesError) {
    }    
}
```

Attach the `NavigationRouteAlternativesObserver` object to [your already-instantiated `MapboxNavigation` object](https://docs.mapbox.com/android/ja/navigation/v2/guides/get-started/initialization/#create-the-mapboxnavigation-object).

```kotlin
mapboxNavigation.registerRouteAlternativesObserver(routeAlternativesObserver)
```

You can compare alternative routes with the original one to choose the route to navigate on (for example, `route.duration` can be used to find the fastest one). If you want to use one of the alternative routes, pass the list to [`MapboxNavigation`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core/-mapbox-navigation/) with [`mapboxNavigation.setNavigationRoutes(routes)`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core/-mapbox-navigation/set-navigation-routes.html).

Don't forget to unregister the `NavigationRouteAlternativesObserver` interface to stop requesting alternative routes:

```kotlin
override fun onStop() {
	super.onStop()
	mapView.onStop()
	mapboxNavigation.unregisterRouteAlternativesObserver(routeAlternativesObserver)
}
```

### Trigger an alternative route

The SDK requests for alternative routes automatically, but you can also trigger an alternative route request at any given time using `requestAlternativeRoutes()`. This can be helpful if you want a specific event or user action to trigger an alternative route request outside the regular interval defined by `RouteAlternativesOptions.intervalMillis`.

```kotlin
mapboxNavigation.requestAlternativeRoutes()
```

## Updated route lines on the map

When a reroute event occurs it's important the route line on the map gets updated to communicate the route change to the user.

It's common to have a [`RoutesObserver`](https://docs.mapbox.com/android/navigation/v2/api/2.22.2/libnavigation-core/com.mapbox.navigation.core.directions.session/-routes-observer/) registered in an activity or fragment. This observer gets called when the route has changed. You can update the route line in this observer to keep the line on the map in sync with the route used by core navigation.

```kotlin
private val routesObserver: RoutesObserver = RoutesObserver { routes ->
	val routeLines = routes.map { RouteLine(it, null) }
	routeLineApi.setRoutes(routeLines) { result ->
		routeLineView.renderRouteDrawData(mapStyle, result)
	}
}
```

If you're not using a `RoutesObserver` in this way, another way to update the map is by using a `RouteProgressObserver`. The `RouteProgress` has a reference to the route being navigated.

```kotlin
val routeProgressObserver = RouteProgressObserver { routeProgress ->
	val routeLines = routes.map { RouteLine(it, null) }
	routeLineApi.setRoutes(routeLines) { result ->
		routeLineView.renderRouteDrawData(mapStyle, result)
	}
}
```