> ## Documentation Index
> Fetch the complete documentation index at: https://docs.here.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Offline routing features

<style>
  {`
    .beta-banner {
      color: #000000;
      background: linear-gradient(270deg, #65EBE2 0%, #6B9CFF 100%);
      font-weight: bold;
      padding: 5px;
      font-family: FiraGo, sans-serif;
    }
  `}
</style>

<p className="beta-banner">Offline maps are only available with the Navigate license.</p>

In addition to the online-only `RoutingEngine`, there is also an equivalent for offline use cases available: the `OfflineRoutingEngine`. This offline version is designed to offer the same robust routing capabilities as its online counterpart, ensuring seamless navigation even without an internet connection.

> #### Note
>
> You can only calculate routes on already cached or preloaded offline maps data. When you use only cached map data, it may happen that not all tiles are loaded for the lower zoom levels. In that case, no route can be found until also the lower zoom levels are loaded - even if you see the map. With offline maps this cannot happen and the required map data is guaranteed to be available for the downloaded region. Therefore, it is recommended to not rely on cached map data.

The `OfflineRoutingEngine` can be constructed in the same straightforward manner as the `RoutingEngine`:

```java
private RoutingInterface routingEngine;
private RoutingEngine onlineRoutingEngine;
private OfflineRoutingEngine offlineRoutingEngine;

...

try {
    onlineRoutingEngine = new RoutingEngine();
} catch (InstantiationErrorException e) {
    throw new RuntimeException("Initialization of RoutingEngine failed: " + e.error.name());
}

try {
    // Allows to calculate routes on already downloaded or cached map data.
    offlineRoutingEngine = new OfflineRoutingEngine();
} catch (InstantiationErrorException e) {
    throw new RuntimeException("Initialization of OfflineRoutingEngine failed: " + e.error.name());
}
```

> #### Note
>
> Transit routes (via `TransitRoutingEngine`) and EV routes (`RoutingOptions` with `ElectricVehicleOptions`) are not yet supported and only work online. The `OfflineRouteEngine` will fail with `RoutingError.INVALID_PARAMETER` in case of unsupported transport modes.

The `OfflineRoutingEngine` provides the same interfaces as the `RoutingEngine`, but the results may slightly differ as the results are taken from already downloaded or cached map data instead of initiating a new request to a HERE backend service.

This way the data may be, for example, older compared to the data you may receive when using the `RoutingEngine`. On the other hand, this class provides results faster - as no online connection is necessary.

However, the resulting routes contain only an empty list of maneuvers. If you need to get maneuvers during guidance, you can get them directly from the `Navigator` or `VisualNavigator` via the provided `nextManeuverIndex`. This is shown in the [Navigation](android-navigation) section.

All available interfaces of the `OfflineRoutingEngine` are also available in the `RoutingEngine` and both engines adopt the same interface. This makes it easy to switch between both engine instances as we will show below.

> #### Note
>
> To get a quick overview of how all of this works, you can take a look at the offline [RoutingExample](https://github.com/heremaps/here-sdk-examples/blob/master/examples/latest/navigate/android/Java/RoutingHybrid/app/src/main/java/com/here/routinghybrid/RoutingExample.java) class. It contains all code snippets shown below and it is part of the "RoutingHybrid" example app you can find on [GitHub](https://github.com/heremaps/here-sdk-examples/blob/master/examples/latest/navigate/android).

Below we show how to switch between `OfflineRoutingEngine` and `RoutingEngine`. For example, when you are on the go, it can happen that your connection is temporarily lost. In such a case it makes sense to calculate routes on the already cached or downloaded map data with the `OfflineRoutingEngine`.

To do so, first you need to check if the device has lost its connectivity. As a second step you can use the preferred engine:

```java
// Sets the OfflineRoutingEngine as main engine when the device is not connected, otherwise this will set the
// RoutingEngine that requires connectivity.
private void setRoutingEngine() {
    if (isDeviceConnected()) {
        routingEngine = onlineRoutingEngine;
    } else {
        routingEngine = offlineRoutingEngine;
    }
}
```

Now, you can execute the same code on the current `routingEngine` instance, as shown in the previous sections above.

When you no longer need the `OfflineRoutingEngine` instance, it is recommended to call its `dispose()` method to cancel any pending requests and shut it down for proper resource cleanup.

> #### Note
>
> If the device is offline, the online variant will not find routes and will report an error. Vice versa, when the device is online, but no cached or preloaded map data is available for the area you want to use, the offline variant will report an error as well.

Note that the code for `isDeviceConnected()` to check if the device is online or not is left out here. You may use a third-party API for this or try to make an actual connection - and when that fails, you can switch to the `OfflineRoutingEngine` - or the other way round: you can try offline routing first to provide a fast experience for the user, but when no map data is available, you can try online.

> #### Note
>
> You can find the "RoutingHybrid" example app on [GitHub](https://github.com/heremaps/here-sdk-examples/blob/master/examples/latest/navigate/android/Java/RoutingHybrid).