# Engines
Explore the fundamentals of working with HERE SDK engines, including their integration with or without a map view, initialization options, and efficient management of the map cache.
## How to work with engines
The HERE SDK contains several modules - or engines as we call them - to execute specific tasks such as calculating a route with the `RoutingEngine` or requesting search results via the `SearchEngine`. There are many more engines you can use with the HERE SDK and you can read more about them in the dedicated chapters below. However, most engines share common concepts that makes it easier to use them. For example:
* All engines execute their tasks asynchronously and receive their results on the main thread.
* All engines share similar interfaces, callbacks and error handling.
* It is possible to start multiple instances of an engine in parallel.
* An online connection is required.
Below you can find an overview of the most common engines in the HERE SDK:
* `SearchEngine`: Includes all functionality to search for places, suggestions and locations including geocoding and reverse geocoding.
* `OfflineSearchEngine` (only available for Navigate): The offline version of search that makes request locally using already downloaded map data.
* `RoutingEngine` / `TransitRoutingEngine`: Allows to calculate routes including various options and transport types.
* `OfflineRoutingEngine` (only available for Navigate): The offline version that calculates a route using already downloaded map data.
* `LocationEngine` (only available for Navigate): An advanced HERE positioning solution.
* `ConsentEngine` (only available for Navigate): A supportive engine that helps to aggregate the user's consent before using, for example, the `LocationEngine`.
* `Navigator` / `VisualNavigator` (only available for Navigate): Although not having 'engine' in its name, these classes act as an engine and control all functionality around turn-by-turn navigation.
* `DynamicRoutingEngine` (only available for Navigate): An engine that periodically searches for shorter or faster routes based on the current traffic situation. This can be useful during guidance to notify drivers on route alternatives.
* `TrafficEngine`: An engine that allows to search for traffic incidents.
* `MapDownloader` / `MapUpdater` / `RoutePrefetcher` (only available for Navigate): These classes perform downloads or updates of map data and mark a vital part of any application that supports an offline mode.
* `VenueEngine` (only available for Navigate): Specialized engines to support the integration of private venues into your apps.
* `SDKNativeEngine`: Is required to setup credentials programmatically and allows a few other advanced settings.
* `MapView`: A view to visualize map data. Not really an engine, but listed here for completeness.
Note that all HERE SDK engines, except for the `SDKNativeEngine`, can operate independently from each other and require HERE credentials to request data.
> #### Note
>
> The HERE SDK does not verify credentials at instantiation time. This only happens once a feature is used that requires authentication. In case of a failure, you will get a dedicated error message. For example, the `SearchEngine` will reply with a `SearchError.AUTHENTICATION_FAILED` error. Other engines provide similar error codes.
>
> Not all credentials will work for all features. If the credentials are invalid, the logs contain `[ERROR]` messages with a text similar to `Failed to get the authentication token: Authentication failed, error code: 1`. This indicates that the credentials are not accepted when using a service. If you want to ensure that your credentials are set up correctly, use a feature with a specialized engine and check if the engine replies with an error value.
Any engine can be created using a parameterless constructor. Example:
```java
try {
searchEngine = new SearchEngine();
} catch (InstantiationErrorException e) {
throw new RuntimeException("Initialization of SearchEngine failed: " + e.error.name());
}
```
Using this default constructor requires that the HERE SDK is already initialized and that a shared instance of the `SDKNativeEngine` was set either directly by calling `SDKNativeEngine.setSharedInstance(sdkNativeEngine)` or implicitly by calling `SDKNativeEngine.makeSharedInstance(context, options)`.
For rare use case scenarios, you can use an overloaded constructor that takes an individually created instance of the `SDKNativeEngine` - as shown in the below section.
> #### Note
>
> It is possible to initialize an engine during the `Application`'s `onCreate()` lifecycle. Any other point in time is also fine. For example, another good place to initialize an engine may be in an `Activity`'s `onCreate()`-method.
Some engines, such as the `RoutingEngine`, `TransitRoutingEngine`, and `OfflineRoutingEngine`, provide a `dispose()` method that can be called to clean up resources. For example, to cancel pending requests when their instances are no longer in use.
## Use engines with or without a map view
Engines do not need a map view to operate. Therefore it is possible to run an engine on its own, without any map view added to your application. This way, you can build an app solely around a specific engine. With or without a map view - the procedure to create a new engine is exactly the same. Just make sure to initialize the HERE SDK beforehand.
## Initialization options
The HERE SDK can be initialized with various options that can be set either directly for the `SDKNativeEngine` or when initializing the engine with `SDKOptions`.
None of the options are persisted - unless otherwise notes in the API Reference: this means, whenever you initialize the HERE SDK again, the previous options have to be set again if you want to keep them.
The same applies to options you can set for the various feature engines or when using a feature such as the `RoutingEngine` to calculate a `Route` with, for example, `RoutingOptions`.
The HERE SDK itself needs to be initialized manually. To learn more, see [Integrate the HERE SDK](https://docs.here.com/here-sdk/docs/integrate-here-sdk).
* If your app immediately wants to show a map view after app start, then for most use cases it's sufficient to follow the [Integrate the HERE SDK](https://docs.here.com/here-sdk/docs/integrate-here-sdk) guide. However:
* If your app needs to show a map view at a later point in time or if you want to delay initialization, then it is also possible to initialize the HERE SDK at a later point in time.
These are the steps to initialize the HERE SDK:
1. Deactivate the deprecated `InitProvider` (this step will become obsolete with HERE SDK 4.15.0).
2. Initialize the HERE SDK by creating `SDKOptions` and use them to create a new `SDKNativeEngine`.
The creation of the `SDKNativeEngine` and other engines such as the `SearchEngine` happens synchronously in a negligible amount of time.
You can initialize the HERE SDK in two ways:
* Create a shared instance of the `SDKNativeEngine` with `SDKNativeEngine.makeSharedInstance(context, options)`.
* Create individual instances of the `SDKNativeEngine` via `SDKNativeEngine(context, options)`.
By calling `SDKNativeEngine.makeSharedInstance(context, options)` you create a shared instance of the `SDKNativeEngine` that can be used by the HERE SDK. This singleton approach allows easy creation of engines such as the `SearchEngine`, because you can use the default constructor (`SearchEngine()`) that requires no parameters. Internally, the `SearchEngine` will use the shared instance of the `SDKNativeEngine` you have created at initialization time. Therefore, when you re-initialize the HERE SDK, also all engines that have been created using the parameterless constructor, need to be created again.
> #### Note
>
> In case of re-initialization, also a `MapView` instance needs to be initialized again by calling its `onCreate(..)` method. The state of a `MapView` becomes invalid, when the `SDKNativeEngine` is disposed. Call `mapView.isValid()` to determine if the `MapView` is initialized correctly.
Alternatively, for rare use cases, you can set an individual `SDKNativeEngine` instance for each of the feature engines:
```java
SearchEngine searchEngine = new SearchEngine(sdkNativeEngine);
```
In general, it should not be necessary to initialize the `SDKNativeEngine` multiple times. Only one shared instance can be set at a time, which happens implicitly when calling `SDKNativeEngine.makeSharedInstance(context, options)`. Alternatively, you can use the available constructor to create an instance of the `SDKNativeEngine` directly: if you create multiple instances individually, then no shared instance is set - and each feature engine needs to be created with an instance of a `SDKNativeEngine` as constructor parameter - like shown above. This way you can use feature engines such as the `SearchEngine` or the `RoutingEngine` with different instances of the `SDKNativeEngine` that can hold different `SDKOptions`.
Note that any individual instance can be set explicitly as shared instance by calling `SDKNativeEngine.setSharedInstance(sdkNativeEngine)`. Attention: in this case, make sure to `dispose()` any previous instance by calling `SDKNativeEngine.getSharedInstance().dispose()`. Note that this is not necessary when creating a global instance by calling `SDKNativeEngine.makeSharedInstance(context, options)` - for convenience, this call internally disposes any previously shared instance.
> #### Note
>
> For most use cases it is not recommended to create multiple instances: in case of doubt, we recommend to initialize the HERE SDK only via `SDKNativeEngine.makeSharedInstance(context, options)` as shown in the [Integrate the HERE SDK](https://docs.here.com/here-sdk/docs/integrate-here-sdk) topic. It is possible to use this initialization method each time the HERE SDK is needed and to dispose the `SDKNativeEngine` thereafter: for example, for each `Activity`. However, for most cases it can be more efficient if the HERE SDK is initialized only once during the lifetime of an application.
Multiple `SDKNativeEngine` instances can’t have the same access key ID and the cache path is ensured to be unique per access key ID. If a second instance is created with an access key ID that is already in use, then an `InstantiationException` is thrown: as a rule of thumb, when you need multiple instances, you also need a distinct set of credentials for each.
> #### Note
>
> The access key ID part of your credentials is tied to the cache path. When credentials are changed at runtime, it may look like that the previous cache is gone, but it still exists and it is not cleared automatically after disposing the `SDKNativeEngine` or after setting new credentials. Since new credentials have been set, the cache path has just been changed. For example, when the previous credentials are restored, the previous cache can be used again.
More information on the cache can be found [below](#work-with-the-map-cache).
## Initialization and Android permissions
Usually, it is good practice to initialize the HERE SDK not before all permissions have been granted.
The HERE SDK does not require any permission handling on application-side when only showing a map view. It automatically merges the below permissions to the `AndroidManifest.xml`:
```xml
```
Optionally, in the `AndroidManifest.xml` file, you can add inside the top-level `manifest` element the above permissions to be explicit about the required permissions.
> #### Note
>
> These permissions are not sensitive and are immediately granted upon installation by the system - they are always needed, as the HERE SDK needs to have a working internet connection. It is not a requirement to handle these permissions and there are no HERE SDK specific requirements on how to handle permissions.
However, a user can deny any permission after installation via the device's app settings. Therefore it is recommended to add permission handling to your app to notify the user upon app launch.
The accompanying example apps show how this can be done utilizing a [convenience class](https://github.com/heremaps/here-sdk-examples/blob/master/examples/latest/navigate/android/Java/HERESDKUnits/here-sdk-units-core/src/main/java/com/here/sdk/units/core/utils/PermissionsRequestor.java) to keep you away from the boiler plate code. Note that the details are encapsulated as AAR created by the [HERESDKUnits](https://github.com/heremaps/here-sdk-examples/tree/master/examples/latest/navigate/android/Java/HERESDKUnits) app. Of course, you can handle the permissions for your own application in a different way - or even decide to omit it: note that if no internet connection is available, most HERE SDK services will indicate this with an appropriate error message.
> #### Note (for **HERE SDK for Android Navigate**)
>
> For some HERE SDK features, like HERE Positioning, you need additional permissions. See the dedicated [Positioning](https://docs.here.com/here-sdk/docs/get-locations) section on how to handle them.
## Work with the map cache
To better support online and offline use cases, the HERE SDK supports caching of downloaded vector map data. This happens in the background. While interacting with the map, prefetching or using navigation with or without a map view, the data is stored locally on the device and can be accessed even when the device loses connection or operates in an offline mode.
> #### Note
>
> The HERE SDK stores arbitrary data as part of map tiles. Therefore, even without displaying a map view, the map cache will be utilized. For instance, during navigation, all necessary data is stored in the map cache within map tiles. However, it's important to note that not all licenses support features such as prefetching and navigation.
The integrated map caching mechanism supports the standard vector based map schemes - satellite images and other raster tiles are also cached, but in a different cache that is not configurable.
Please note that the amount of cached data is limited and will be overwritten with new map data while using the map. In most cases, this is sufficient to give the user the impression of a faster start-up time - as no additional data must be downloaded when you start an app again at the same location as before.
When the cache is full, a least recently used [LRU](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_\(LRU\)) strategy is applied.
**Change path and cache size**
* An absolute cache path and maximum size can be specified when manually initializing the HERE SDK using `SDKOptions`. Check the [Engines](#engines) section for more details.
* Via `SDKOptions` you can specify the desired `cacheSizeInBytes` to define the upper bound of the cache in bytes. Make sure to query the available disk space on the device with the available platform APIs.
There can be a separate cache defined for [customer raster layers](https://docs.here.com/here-sdk/docs/custom-map-styles#add-custom-raster-layers).
This is how you can clear the map cache:
```java
SDKCache.fromEngine(SDKNativeEngine.getSharedInstance()).clearCache(error -> {
if (error != null) {
// ...
}
});
```
Note that disposing the shared instance of the `SDKNativeEngine` does not clear the cache.
By setting an empty string as cache path, you keep the default cache path - which is also accessible via `context.getCacheDir().getPath()` or `SDKNativeEngine.getSharedInstance().getOptions().cachePath`. By default, when creating new `SDKOptions`, the default cache path is used.
### Work with map cache in Navigate
> #### Note
>
> Since turn-by-turn navigation requires caching, a valid cache path is mandatory when creating a `SDKNativeEngine`.
You can update the map cache to a newer map version - independently of offline maps. By calling `mapUpdater.performMapUpdate()` the map cache will be updated to a newer version (if available) - even if never any `Region` was installed. If offline maps are available, then they will be updated together with the map cache, like before. If offline maps are installed later after the cache has been updated, the same map version will be used. It is not possible to use different versions for the map cache and offline maps.
In order to get the latest map data while panning the map view, you can check if an update is available and then install it. If no offline `Region` maps are installed, this takes only a few seconds. The `MapVersionHandle` indicates the currently used map version.
> #### Note
>
> If you do a fresh install of an application, then not necessarily the latest map version is used. Usually, each HERE SDK release is shipped with a specific map version. However, when you are using a (custom) `CatalogConfiguration`, then it is possible to specify the map version that should be used right after installation of an app, for example, by specifying the latest map version in the `DesiredCatalog`.
More information on the map version, the cache and offline maps can be found in the [Offline Maps](https://docs.here.com/here-sdk/docs/offline-maps) section.
> #### Note
>
> Via `SDKOptions` you can also specify a time when the cache should expire. If you set the time to 0, then this will prevent an app to store data into the cache. If no offline regions have been installed, then - when the device has lost connectivity - no map is visible until the device gets online again. Note that this will not enable you to always see the latest and greatest map data: for this, you would still need to check if a map update is available.
### Questions and answers around the map cache
#### Navigate
* **What is a map tile?** Map tiles are stored in the map cache. A map tile contains data relevant for search and routing, as well as vector data for the visual representation. It is stored in the [Optimized Client Map (OCM)](/optimized-client-map/docs/readme) format. Map tiles are available for different zoom levels. A map tile may contain different data, depending on the zoom level.
* **How long are map tiles cached?** Map tiles are only evicted when the cache is full - there is no staleness of old tiles and no automatic deletion of old tiles based on time. Note that this does not apply for satellite images (see below).
* **What is the eviction policy of the cache?** The HERE SDK uses a LRU (least recently used tile) logic to evict the tiles when the map cache becomes full. There is no sophisticated logic to evict, for example, tiles that are farther away from the current location - as it is not foreseeable which areas of the world the user might visit next. However, the map cache is not session-specific, its data from the last time the device was used, that is from the last power cycle, is still there the next time the app is used. Note that the cache is specific per app, not per device.
* **What is the impact of missing data in the map cache?** Usually, the map cache is never assumed to be complete and there can be always tiles missing for a surrounding area. This is because map tiles get loaded only on demand while they are rendered. When there are tiles missing from the map cache then, for example, the `OfflineSearchEngine` will not find POIs or road names that are part of the missing tiles and the HERE Rendering Engine cannot render such data. Also, the `OfflineRoutingEngine` might fail - unless it finds a route around the missing tiles.
#### Explore
* **What is a map tile?** Map tiles are stored in the map cache. A map tile contains data relevant for search and routing, as well as vector data for the visual representation. Map tiles are available for different zoom levels. A map tile may contain different data, depending on the zoom level.
* **How long are map tiles cached?** Map tiles cannot be used after one day and will be evicted. New images are downloaded earliest after one day based on a LRU strategy.
#### Explore and Navigates
* **What is the eviction policy of the cache?** The HERE SDK uses a LRU (least recently used tile) logic to evict the tiles after one day. The map cache is not session-specific, its data from the last time the device was used, that is from the last power cycle, is still there the next time the app is used. Note that the cache is specific per app, not per device.
* **What is the size of the map cache?** The size of the map cache can be changed by the application. Use at least 256 MB (default). Values above 512 MB or 1 GB are recommended.
For turn-by-turn navigation (which is available e.g. for `Navigate`), map tiles of zoom level 14 are needed, which equals a circle of roughly 2 km. However, this can vary a bit from location to location.
* **Is any previously cached map tile searchable offline?** Yes, it's always searchable with the `OfflineSearchEngine`. However, sometimes not every map tile contains the same search results for every zoom level. Note that the `OfflineSearchEngine` is not available for every license.
* **Is only one map tile cached at a time?** Yes, only one tile at a time may be added unless its location is on the edge of two tiles. Depending on the zoom level, rendering of the map view will require several tiles - this is not happening automatically and only when the zoom level changes.
* **Are satellite images cached?** Yes. When the satellite map scheme is set, the corresponding imagery is also cached, but satellite images cannot be used after one day and will be evicted. New images are downloaded earliest after one day based on a LRU strategy.
* **Is there always a "base map" available, such as a globe view?** The HERE SDK downloads automatically the world tiles, that is the top most zoom level tiles for the globe. This means that there is always a map available for the globe with a very limited amount of information for rendering purposes. The shapes of countries and continents are visible and capitols are shown with text labels.
* **Is the cache auto-cleared?** No, a full cache is only cleared based on a LRU strategy (see above). If tiles have not been fully downloaded due to a connectivity interruption, these tiles are preserved and the download continues when connectivity resumes.
* **If connectivity is available, will a whole route be cached in advance?** No, this is not happening automatically. However, you can use the `RoutePrefetcher` to download map data into the cache along the route corridor. Look into the turn-by-turn navigation section for more details. Note that the `RoutePrefetcher` is not available for every license.