> ## 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.

# Manage data and OTA costs

<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">Managing data and OTA costs is only available with the Navigate license.</p>

This guide provides strategies to reduce the size of the HERE SDK and enhance its runtime performance by minimizing the amount of data that needs to be loaded or processed.

## Configure OCM layers to minimize data load

Setting a layer configuration involves specifying a list of feature items. Only the features in this list will be enabled; all others will be disabled. To disable a single feature, ensure all other desired features are included in the list, or they will be automatically disabled as well.

Several features of the HERE SDK are stored in the OCM map data format (Optimized Client Maps).

Utilizing the `LayerConfiguration`, you can control:

* The amount of map data loaded into the cache during online panning of the `MapView`.
* The volume of data downloaded when adding a new `Region` for offline use.

For instance, if turn-by-turn navigation is not utilized within an application, the corresponding feature configuration `NAVIGATION` can be omitted. This adjustment results in less data being downloaded into the cache while panning the `MapView`. Moreover, the size of the data downloaded when adding a new `Region` will be considerably reduced.

As of now, the below features can be specified. The table also shows which features are enabled, by default:

<HTMLBlock>
  {`
  <center><p>
  <table style="width:500">
    <tr>
      <th style="vertical-align:top">Feature</th>
      <th style="vertical-align:top">Enabled</th>
      <th style="vertical-align:top">Description</th>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>DETAIL_RENDERING</code></td>
      <td style="vertical-align:top">Yes</td>
      <td style="vertical-align:top">Additional rendering details like buildings. Only used for the <code>MapView</code>. When not set, the data will be excluded when downloading offline regions or prefetching areas that contain such data. However, during online usage such data may still be downloaded into the cache and shown.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>NAVIGATION</code></td>
      <td style="vertical-align:top">Yes</td>
      <td style="vertical-align:top">Map data that is used for map matching during navigation. When not set, navigation may not work properly when being used online or offline.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>OFFLINE_SEARCH</code></td>
      <td style="vertical-align:top">Yes</td>
      <td style="vertical-align:top">Map data that is used to search. When not set, the <code>OfflineSearchEngine</code> may not work properly when being used.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>OFFLINE_SEARCH_GLOBAL</code></td>
      <td style="vertical-align:top">No</td>
  <td style="vertical-align:top">Offers improved map data for offline search with better performance and memory footprint. Extends the search range and allows searching for places beyond the search center. It is recommended to disable <code>offlineSearch</code> when using this feature to avoid downloading unnecessary layers. Curently, only installed regions are supported. Cached or prefetched map data is not yet supported.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>OFFLINE_ROUTING</code></td>
      <td style="vertical-align:top">Yes</td>
      <td style="vertical-align:top">Map data that is used to calculate routes. When not set, the <code>OfflineRoutingEngine</code> may not work properly when being used.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>TRUCK</code></td>
      <td style="vertical-align:top">Yes</td>
      <td style="vertical-align:top">Map data that is used to calculate truck routes. When not set, the <code>OfflineRoutingEngine</code> may not work properly when being used to calculate truck routes. It is also used for map matching during truck navigation. When not set, truck navigation may not work properly when being used offline. Online truck navigation will still work when the device has an online connection.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>LANDMARKS_3D</code></td>
      <td style="vertical-align:top">Yes</td>
      <td style="vertical-align:top">Map data that is used to render textured 3D landmarks. When not set, the data will be excluded when downloading offline regions or prefetching areas that contain such data. When the <code>LANDMARKS</code> layer is set to be visible for a <code>MapScene</code>, 3D landmarks will still be visible during online usage.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>JUNCTION_VIEW_3X4</code>, <code>JUNCTION_VIEW_16X9</code></td>
      <td style="vertical-align:top">No</td>
      <td style="vertical-align:top">3D visuals for complex junctions. This asset data can be used to show SVG images during guidance. If enabled, downloaded regions will include junction view images to be used with the corresponding <code>JunctionViewWarning</code> event. This could be useful to download the assets before starting a trip. If not enabled, the required data will be downloaded when needed. Each image can occupy up to 15 MB. Note that future releases of the HERE SDK will optimize the size by reducing the level of realism. By default, the layer is not enabled.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>JUNCTION_SIGN_3X4</code>, <code>JUNCTION_SIGN_4X3</code>, <code>JUNCTION_SIGN_3X5</code>, <code>JUNCTION_SIGN_5X3</code>, <code>JUNCTION_SIGN_16X9</code></td>
      <td style="vertical-align:top">No</td>
      <td style="vertical-align:top">Signpost visuals. This asset data can be used to show SVG images during guidance. If enabled, downloaded regions will include junction view images to be used with the corresponding <code>SignpostWarning</code> event. If not enabled, the required data will be downloaded when needed. Each image can occupy up to 300 KB. If not enabled, the required data will be downloaded when needed. By default, the layer is not enabled.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>RENDERING</code></td>
      <td style="vertical-align:top">Yes</td>
      <td style="vertical-align:top">A basic set of rendering features such as Carto POIs. As a base layer, this feature cannot be disabled.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>RDS_TRAFFIC</code></td>
      <td style="vertical-align:top">No</td>
      <td style="vertical-align:top">Map data that provides traffic broadcast functionality using RDS-TMC format. It should be used when there is no internet connection, so that the routing module can utilize traffic data coming over the radio channel to create routes with the <code>OfflineRoutingEngine</code>.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>EV</code></td>
      <td style="vertical-align:top">No</td>
      <td style="vertical-align:top">Offline map data for EV charging stations.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>TRUCK_SERVICE_ATTRIBUTES</code></td>
      <td style="vertical-align:top">No</td>
      <td style="vertical-align:top">Enables truck related attributes to be returned by <code>OfflineSearchEngine</code>.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>FUEL_STATION_ATTRIBUTES</code></td>
      <td style="vertical-align:top">No</td>
      <td style="vertical-align:top">Enables fuel attributes to be returned by <code>OfflineSearchEngine</code>.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>OFFLINE_BUS_ROUTING</code></td>
      <td style="vertical-align:top">No</td>
      <td style="vertical-align:top">Map data that is used to calculate bus routes. When not set, the <code>OfflineRoutingEngine</code> may not be able to calculate routes with <code>BusOptions</code>.</td>
    </tr>
    <tr>
      <td style="vertical-align:top"><code>TERRAIN</code></td>
      <td style="vertical-align:top">No</td>
      <td style="vertical-align:top">Map data that is used to represent topographical data.</td>
    </tr>
  </table>
  </p></center>
  `}
</HTMLBlock>

Note that each of the listed features relates to one or more OCM layer groups. The names of the OCM layer groups can be seen per feature in the API Reference. However, for most use cases knowing the related OCM layer name is not relevant.

In addition, there are two layers, `ADAS` and `EHORIZON` (Electronic Horizon), that are currently not relevant for use with the HERE SDK and can be ignored for now. By default, they are already disabled.

Only the `LayerConfiguration` that was set globally when a `Region` was first downloaded or cached is used. To update the `LayerConfiguration` for an already downloaded region, either delete and re-download the region or initialize the `MapUpdater` again and call `mapUpdater.updateCatalog(..)`.

If a feature is disabled, required data for that feature will not occupy space in the cache or as part of a `Region` download. That feature cannot be used offline. Sometimes an error may occur - for example, when trying to use the `OfflineSearchEngine` although `OFFLINE_SEARCH` has been disabled. Find more details below.

> #### Note
>
> Engines like the `SearchEngine` or the `RoutingEngine` will never make use of cached or downloaded map data. Only the `OfflineSearchEngine` and `OfflineRoutingEngine` will use such data if the related features have not been disabled. For example, if you are sure that your app fully operates online, it is safe to disable the offline search feature. However, if you want to ensure that an app can also search for POIs when there is a temporary connection loss, you may want to switch to the `OfflineSearchEngine` when such a loss is detected - and therefore, you should not disable the related feature.

As listed above, for some disabled features, a device may still download corresponding data when a device has online connectivity and the feature is needed. For example, when the "LANDMARKS\_3D" feature is disabled, but the corresponding `MapScene` layer is enabled, then the device will still download the needed textures to render a 3D landmark when it becomes visible in the `MapView` viewport.

For all listed features from above - except for `OFFLINE_SEARCH` and `OFFLINE_ROUTING`, the HERE SDK will first check if the needed data is available in the cache. If not found there, it will look if there is a downloaded `Region` for offline use. If not found, the HERE SDK will try to download the needed data over the air. For `OFFLINE_SEARCH` and `OFFLINE_ROUTING` the behavior will be the same, but no data will be requested over the air.

## Set a LayerConfiguration

At first, specify the desired layer configuration:

```java Java
// With this layer configuration we enable only the listed layers.
// All the other layers including the default layers will be disabled.
ArrayList<LayerConfiguration.Feature> features = new ArrayList<>();
features.add(LayerConfiguration.Feature.DETAIL_RENDERING);
features.add(LayerConfiguration.Feature.RENDERING);
features.add(LayerConfiguration.Feature.OFFLINE_SEARCH);
LayerConfiguration layerConfiguration = new LayerConfiguration();
layerConfiguration.enabledFeatures = features;
```

```kotlin Kotlin
// With this layer configuration we enable only the listed layers.
// All the other layers including the default layers will be disabled.
val features = ArrayList<LayerConfiguration.Feature>()
features.add(LayerConfiguration.Feature.DETAIL_RENDERING)
features.add(LayerConfiguration.Feature.RENDERING)
features.add(LayerConfiguration.Feature.OFFLINE_SEARCH)
val layerConfiguration = LayerConfiguration()
layerConfiguration.enabledFeatures = features
```

Set the created `layerConfiguration` object to `SDKOptions` and initialize the HERE SDK as usual.

```java Java
AuthenticationMode authenticationMode = AuthenticationMode.withKeySecret(accessKeyID, accessKeySecret);
SDKOptions options = new SDKOptions(authenticationMode);
options.layerConfiguration = layerConfiguration;
// Now use this SDKOptions for initializing a new SDKNativeEngine instance.
```

```kotlin Kotlin
val authenticationMode = AuthenticationMode.withKeySecret(
    accessKeyID, accessKeySecret
)
val options = SDKOptions(authenticationMode)
options.layerConfiguration = layerConfiguration
// Now use this SDKOptions for initializing a new SDKNativeEngine instance.
```

## Update the layer configuration

Layer configurations can be updated any time by setting new `SDKOptions` to create a new instance of a `SdkNativeEngine`.

Call `mapUpdater.retrieveCatalogsUpdateInfo(..)` to query the list of all catalogs that have newer versions available. This will apply a new `LayerConfiguration` which will overwrite the previous one. Now, from the list of all catalogs use each `CatalogUpdateInfo` to perform a map update via `mapUpdater.updateCatalog(catalogUpdateInfo, CatalogUpdateProgressListener())`. When you are using a `MapView`, then you also need to reinitialize all engines including the `SdkNativeEngine` and the `MapView`.

> #### Note

> When calling `mapUpdater.updateCatalog(..)` and no regions have been downloaded, this method will update only the map cache. If no updates are available, the `MapUpdateProgressListener.onComplete()` callback will be invoked immediately with a `MapLoaderError`. The map data cache adheres to the LRU (Least Recently Used) eviction policy, so any updates will exclusively apply to newly downloaded data and not retroactively to existing cached data. For immediate cache invalidation, users can manually clear the cache. Otherwise, stale cache data may still be accessed by the HERE SDK, for example, when using the `OfflineSearchEngine`.

To apply a changed `LayerConfiguration` it is recommended to use the same code you use to check for map updates. Just make sure to perform the code on a new `MapUpdater` instance. An example implementation of `checkForMapUpdates()` can be found in the [map update](android-offline-maps-update.md#check-for-map-updates) guide.

Note that it is the developer's responsibility to decide when to perform the update. The async update process, also called "normalization", may take time depending on how many regions have been installed.

### Update the layer configuration when using a MapView

To enable or disable a layer configuration at runtime when showing a `MapView`, calling `mapUpdater.updateCatalog(..)` is not sufficient. All engines, including `SdkNativeEngine` and `MapView`, must be reinitialized.

Example:

1. Start with reinitialization of the HERE SDK and set a new layer configuration.

```java Java
try {
    AuthenticationMode authenticationMode = AuthenticationMode.withKeySecret(accessKeyID, accessKeySecret);
    SDKOptions options = new SDKOptions(authenticationMode);
    options.layerConfiguration = layerConfiguration;
    // Invoking makeSharedInstance will invalidate any existing references to the previous instance of SDKNativeEngine.
    // It will also destroy the previous SDKNativeEngine.
    SDKNativeEngine.makeSharedInstance(context, options);
    // Update the current MapView instance to recreate the rendering surface that was invalidated by the invocation of makeSharedInstance.
    updateMapView(savedInstanceState);
    // Reinitialize the map updater and perform feature update internally to "normalize" the new layer configuration.
    // Normalization, in this context, is the process of aligning the currently downloaded layer group configuration in the map data with the requested one.
    // Layer groups that are not in the requested layer configuration are removed and layer groups that were added to the requested configuration are downloaded.
    initMapUpdater(SDKNativeEngine.getSharedInstance());

    // Reinitialize other necessary engines as required.

} catch (InstantiationErrorException e) {
    throw new RuntimeException("Reinitialization failed: " + e.error.name());
} catch (Exception e) {
    e.printStackTrace();
}
```

```kotlin Kotlin
try {
    val authenticationMode = AuthenticationMode.withKeySecret(
        accessKeyID, accessKeySecret
    )
    val options = SDKOptions(authenticationMode)
    options.layerConfiguration = layerConfiguration

    // Invoking makeSharedInstance will invalidate any existing references to the previous instance of SDKNativeEngine.
    // It will also destroy the previous SDKNativeEngine.
    SDKNativeEngine.makeSharedInstance(context, options)

    // Update the current MapView instance to recreate the rendering surface that was invalidated by the invocation of makeSharedInstance.
    updateMapView(savedInstanceState)

    // Reinitialize the map updater and perform feature update internally to "normalize" the new layer configuration.
    // Normalization, in this context, is the process of aligning the currently downloaded layer group configuration in the map data with the requested one.
    // Layer groups that are not in the requested layer configuration are removed and layer groups that were added to the requested configuration are downloaded.
    initMapUpdater(SDKNativeEngine.getSharedInstance())

    // Reinitialize other necessary engines as required.

} catch (e: InstantiationErrorException) {
    throw RuntimeException("ReInitialization of HERE SDK failed: " + e.error.name)
} catch (e: Exception) {
    e.printStackTrace()
}
```

2. Update the current `MapView` instance to recreate the rendering surface that was invalidated by the invocation of `makeSharedInstance()`.

```java Java
private void updateMapView(Bundle savedInstanceState) {
    // Needs to be called after recreation of SDKNativeEngine, even when savedInstanceState is null.
    // Otherwise, the map view will keep using the previous SDKNativeEngine instance.
    mapView.onCreate(savedInstanceState);
    // Since mapview.onCreate() results in a new rendering surface, the map scene must be reloaded to ensure proper rendering.
    mapView.getMapScene().loadScene(MapScheme.NORMAL_DAY, new MapScene.LoadSceneCallback() {
        @Override
        public void onLoadScene(@Nullable MapError mapError) {
            ...
        }
    });
}
```

```kotlin Kotlin
private fun updateMapView(savedInstanceState: Bundle?) {
    // Needs to be called after recreation of SDKNativeEngine, even when savedInstanceState is null.
    // Otherwise, the map view will keep using the previous SDKNativeEngine instance.
    mapView.onCreate(savedInstanceState)

    // Since mapview.onCreate() results in a new rendering surface, the map scene must be reloaded to ensure proper rendering.
    mapView.mapScene.loadScene(
        MapScheme.NORMAL_DAY
    ) { mapError ->
        ....
    }
}
```

3. Reinitialize the `MapUpdater` and use it to update the catalogs.

```java Java
private void initMapUpdater(SDKNativeEngine sdkNativeEngine) {
    MapUpdater.fromEngineAsync(sdkNativeEngine, new MapUpdaterConstructionCallback() {
        @Override
        public void onMapUpdaterConstructe(@NonNull MapUpdater mapUpdater) {
            OfflineMapsExample.this.mapUpdater = mapUpdater;
            // Checks and updates in cases of map feature configuration changes.
            // Perform the map update ...
        }
    });
}
```

```kotlin Kotlin
private fun initMapUpdater(sdkNativeEngine: SDKNativeEngine) {
    MapUpdater.fromEngineAsync(sdkNativeEngine, object : MapUpdaterConstructionCallback {
        override fun onMapUpdaterConstructe(mapUpdater: MapUpdater) {
            this@OfflineMapsExample.mapUpdater = mapUpdater
            // Checks and updates in cases of map feature configuration changes.
            // Perform the map update ...
        }
    })
}
```

To see a possible implementation of how to update a `LayerConfiguration` and perform map data updates, refer to the `OfflineMaps` example app on GitHub, provided in [Java](https://github.com/heremaps/here-sdk-examples/blob/master/examples/latest/navigate/android/Java/OfflineMaps) and [Kotlin](https://github.com/heremaps/here-sdk-examples/tree/master/examples/latest/navigate/android/Kotlin/OfflineMapsKotlin).

## Implicit prefetch features for online use

In addition to `layerConfiguration.enabledFeatures`, you can also set `layerConfiguration.implicitlyPrefetchedFeatures`.

* `enabledFeatures` will enable all layers from the list when downloading regions for offline use.
* `implicitlyPrefetchedFeatures` will enable all layers from the list when downloading map content into the map cache, for example, when panning the `MapView` during online use.

By default, the following features are enabled for implicit prefetching:

* `DETAIL_RENDERING`
* `NAVIGATION`
* `OFFLINE_SEARCH`
* `OFFLINE_ROUTING`
* `RENDERING`
* `TRUCK`

To customize implicit prefetching, use the `implicitlyPrefetchedFeatures` field in `LayerConfiguration`.

Below, we show how to set the same features for both online and offline use:

```java Java
ArrayList<LayerConfiguration.Feature> features = new ArrayList<>();
features.add(LayerConfiguration.Feature.DETAIL_RENDERING);
features.add(LayerConfiguration.Feature.RENDERING);
features.add(LayerConfiguration.Feature.OFFLINE_SEARCH);
LayerConfiguration layerConfiguration = new LayerConfiguration();
layerConfiguration.enabledFeatures = features;
layerConfiguration.implicitlyPrefetchedFeatures = features;
```

```kotlin Kotlin
// With this layer configuration we enable only the listed layers.
// All the other layers including the default layers will be disabled.
val features = ArrayList<LayerConfiguration.Feature>()
features.add(LayerConfiguration.Feature.DETAIL_RENDERING)
features.add(LayerConfiguration.Feature.RENDERING)
features.add(LayerConfiguration.Feature.OFFLINE_SEARCH)
val layerConfiguration = LayerConfiguration()
layerConfiguration.enabledFeatures = features
layerConfiguration.implicitlyPrefetchedFeatures = features
```

When configuring `LayerConfiguration`, you can enable the same set of features for both online and offline use by assigning the same list of features to both `enabledFeatures` and `implicitlyPrefetchedFeatures`. This ensures consistency in feature availability regardless of whether the application is operating online or offline.

In order to disable `implicitlyPrefetchedFeatures`, assign an empty list to `layerConfiguration.implicitlyPrefetchedFeatures`. Disabling implicit prefetching for certain features reduces network consumption, but may limit offline capabilities. Cached map data already downloaded will not be removed immediately.

Here are some examples of how to configure `implicitlyPrefetchedFeatures`:

* If your primary goal is to minimize network usage during online operations, set an empty list to `layerConfiguration.implicitlyPrefetchedFeatures`. This ensures only minimal required map data is downloaded while panning or interacting with the `MapView`. The trade-off is that less data in the cache will not allow you to use offline features, unless you have the needed regions installed.

* If your application requires offline routing, but you do not know which regions to download in advance, enable only the `OFFLINE_ROUTING` implicit feature. This reduces the amount of downloaded data when panning the map in online mode, but you can still try to use the `OfflineRoutingEngine` on the cached data. Note that there is no guarantee that enough data has been cached. If you want to make sure to have enough data, it is recommended to install the needed regions.

* If your application requires offline routing while being [radio-silent](android-offline-maps.md#use-the-global-offline-switch), enable only the `OFFLINE_ROUTING` implicit feature as mentioned above and additionally set it as a `PassThroughFeature` via `SDKNativeEngine`.