Quickstart

Request access

Offline functionality for the Maps SDK and Navigation SDK for Android is only available upon request. Contact Sales to get started.

The Navigation SDK offers a complete navigation experience, including the ability to work with offline maps. Offline maps allow users to search for destinations, plan routes, and navigate even without an internet connection.

The offline maps are divided into map regions. A map region can be any geographical area: a city such as Amsterdam, an area inside a country such as North Holland, a country such as The Netherlands, or a region such as Benelux.

You can choose to update or install any map region so that the data is available to other components of the SDK for offline use. When used offline, the Navigation SDK only uses data from the map regions that are installed on the device.

In this guide, we will walk you through the process of setting up and using offline maps in your application.

Prerequisites

Before proceeding, ensure that you do the following:

  • Gain access: Go to repositories.tomtom.com and log in with your account. Expand the user menu in the top-right corner, and select “Edit profile” → “Generate an Identity Token”. Copy the generated token and use it to specify your credentials in your project gradle.properties file:

    • Replace user_name_placeholder with the login username or email you use for repositories.tomtom.com .
    • Replace identity_token_placeholder with the generated identity token.
    repositoryUsername=user_name_placeholder
    repositoryIdentityToken=identity_token_placeholder
  • Project configuration: Add a maven block to your settings.gradle file to specify the credentials and the URI for repositories.tomtom.com .

    dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
    google()
    mavenCentral()
    maven {
    credentials {
    username = repositoryUsername
    password = repositoryIdentityToken
    }
    url = uri("https://repositories.tomtom.com/artifactory/maven")
    }
    }
    }
  • Offline setup package: This package should contain a map, a keystore, a map access license token, and an API key for map updates.

  • Project setup: Configure your project according to the instructions provided in the Project setup guide .

Adding dependencies

Add the following module dependency in the build.gradle.kts of your application module and synchronize the project.

implementation("com.tomtom.sdk.datamanagement:nds-store:1.26.4")
implementation("com.tomtom.sdk.datamanagement:nds-store-updater:1.26.4")

Storing the offline map on a device

The offline setup package includes a map and a keystore. To ensure proper access, store these files on the device in a way that allows the application to access them. You can choose to embed the files as part of the application’s assets or save them in a cloud space and retrieve them during the initial launch of the application.

If opting for external storage, you should be aware of the following limitations:

  • Permissions: Adjust your application to request the necessary permissions for accessing external storage. For detailed instructions, refer to the section on Permissions and access to external storage .
  • Filesystem in Userspace (FUSE): Note that Android 11 or higher defaults to using Filesystem in Userspace (FUSE) for SD cards. FUSE can significantly affect performance when dealing with large files, impacting SDK components’ performance.

It is strongly recommended to consult the Android Developer Guide on Mitigating FUSE Performance . This guide provides a comprehensive understanding and potential workarounds for performance issues related to FUSE.

Loading the offline map

The offline map must be compliant with the Navigation Data Standard version 2.4.6. Other Navigation Data Standard versions are not supported.

To utilize the offline map, you need to instantiate the NdsStore object, which allows you to load offline map data. Other SDK components can then use it for their features.

For map management functionalities, such as enabling automatic map updates, installing or removing map regions, and querying map structures, you will need NdsStoreUpdater .

Follow these steps to construct the NdsStore and NdsStoreUpdater objects:

  1. Define the necessary file paths and directories:
    // Assume the map and the keystore files are stored in the app-specific storage
    val rootDir = context.filesDir
    val mapDir = rootDir.resolve("map")
    val keystorePath = rootDir.resolve("keystore.sqlite")
    val updateDir = rootDir.resolve("update") // NdsStoreUpdater will create this directory
    val persistentDir = rootDir.resolve("persistent") // NdsStoreUpdater will create this directory
  2. Create the NdsStoreConfiguration object:
    val defaultNdsStoreConfig =
    NdsStoreConfiguration(
    ndsStorePath = mapDir,
    keystorePath = keystorePath,
    accessPermit = NdsStoreAccessPermit.MapLicense("YOUR_MAP_LICENSE"),
    )
  3. Create the NdsStore object and handle any potential failures:
    ndsStore =
    NdsStore.create(context = context, configuration = defaultNdsStoreConfig).fold(
    { it },
    {
    // Error handling - Your code goes here
    throw IllegalStateException(it.message)
    },
    )
  4. Set up the NdsStoreUpdaterConfiguration :
    val defaultUpdateConfig =
    NdsStoreUpdaterConfiguration(
    updateStoragePath = updateDir,
    persistentStoragePath = persistentDir,
    updateServerApiKey = TOMTOM_API_KEY,
    )
  5. Create the NdsStoreUpdater object and handle any potential failures:
    ndsStoreUpdater =
    NdsStoreUpdater.create(
    context = context,
    ndsStore = ndsStore,
    configuration = defaultUpdateConfig,
    ).fold(
    { it },
    {
    // Error handling - Your code goes here
    throw IllegalStateException(it.toString())
    },
    )

To access a specific offline map, create only one instance of NdsStore and NdsStoreUpdater . Creating multiple instances for the same map can lead to unexpected behavior.

Downloading map contents around the specified location

The offline map included in the setup package contains only metadata and does not include pre-installed map regions. Therefore, it is necessary to download and install map regions before utilizing search, display, routing, or navigation functionalities.

To enable automatic map updates around the specified location, follow these steps:

  1. Create the NdsStoreUpdater object with an NdsStoreUpdaterConfiguration that is set up to enable the updates:
    ndsStoreUpdater =
    NdsStoreUpdater.create(
    context = context,
    ndsStore = ndsStore,
    configuration =
    defaultUpdateConfig.copy(
    automaticUpdates =
    defaultAutomaticNdsStoreUpdaterConfiguration.copy(
    relevantRegions = RelevantRegions(),
    ),
    ),
    ).fold(
    { it },
    {
    // Error handling - Your code goes here
    throw IllegalStateException(it.toString())
    },
    )
  2. Add an RegionGraphListener to monitor the success events of map updates, and then enable map updates:
    private var rootNodes = listOf<RegionGraphNode>()
    private val nodeStates = mutableMapOf<RegionGraphNodeId, RegionGraphNodeState>()
    private val regionGraphListener =
    object : RegionGraphListener {
    override fun onRegionGraphChanged(
    regionGraphResult: Result<RegionGraph, MapUpdateError>,
    mapRegionStates: Map<RegionGraphNodeId, RegionGraphNodeState>,
    ) {
    regionGraphResult
    .ifSuccess {
    // Your code goes here
    // For example, you can save the region graph and the states
    rootNodes = it.roots
    nodeStates.clear()
    nodeStates.putAll(mapRegionStates)
    }
    .ifFailure {
    // Your code goes here
    }
    }
    override fun onMapRegionStatesChanged(mapRegionStates: Map<RegionGraphNodeId, RegionGraphNodeState>) {
    // Your code goes here
    // for example, update the current states
    nodeStates.putAll(mapRegionStates)
    }
    }
  3. Update the position by passing the location to the NdsStore .
    val amsterdam = GeoPoint(52.377956, 4.897070)
    ndsStoreUpdater.updatePosition(amsterdam)

The NdsStoreUpdater will download the relevant map regions around the specified location in the background. Upon successful map update, you will receive a notification from RegionGraphListener . The more details about RegionGraphListener can be found in Manual Map Management

Utilizing the NdsStore

Now that the NdsStore is created and map contents are successfully downloaded, you can use it with other SDK components. For example, you can create a route planner:

val routePlanner = OfflineRoutePlanner.create(ndsStore)

With the route planner, you can plan routes by providing the desired itinerary:

val amsterdam = GeoPoint(52.377956, 4.897070)
val rotterdam = GeoPoint(51.926517, 4.462456)
val routePlanningOptions = RoutePlanningOptions(itinerary = Itinerary(amsterdam, rotterdam))
val result = routePlanner.planRoute(routePlanningOptions)
if (result.isSuccess()) {
// Success - Your code goes here
val route = result.value().routes.first()
} else {
// Error handling - Your code goes here
val error = result.failure()
}

Next steps

You have successfully set up and utilized offline maps with the Navigation SDK. To further enhance your offline map implementation, consider exploring the following topics:

By diving deeper into these areas, you can unlock the full potential of offline maps in your application.