Migrate from Google

VERSION 1.4.0
PUBLIC PREVIEW

Overview

This tutorial covers some fundamental use cases to help you switch your Android app from Google’s APIs to TomTom’s as quickly and efficiently as possible. It starts with basic environment setup, then dives straight into the code.

Prerequisites

Before you start writing code, prepare your environment:

  1. Install Android Studio if you don’t already have it.

  2. Make sure to use Gradle in your project. We are no longer supporting Maven. Contact us if your project is using Maven instead of Gradle.

  3. Create a new project or open an existing one. Make sure that the minimum SDK API level is set to at least 26 (Android 8.0 "Oreo") by making the following changes in the android block of your app’s build.gradle.kts file.

    1android {
    2 defaultConfig {
    3 minSdk = 26
    4 }
    5}
  4. To prevent duplication of the libc++_shared.so file in your Android Gradle build, add the following packaging option to the android block of your app’s build.gradle.kts file.

    1android {
    2 packaging {
    3 jniLibs.pickFirsts.add("lib/**/libc++_shared.so")
    4 }
    5}

    This ensures that only one copy of libc++_shared.so is included in the build output, addressing the issue of multiple copies from different sources.

  5. To prevent potential errors during app start-up, it’s important to ensure that OpenGL ES 3.0 support is enabled in the Android Studio emulator. If your emulator supports it, navigate to Settings, choose "Renderer maximum (up to OpenGL ES 3.1)" for the "OpenGL ES API level (requires restart)" field, and then restart the emulator to apply the changes.

Configuring project dependencies

  1. Add a maven block to your settings.gradle.kts file to specify the URI for repositories.tomtom.com.

    1dependencyResolutionManagement {
    2 repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    3 repositories {
    4 google()
    5 mavenCentral()
    6 maven {
    7 url = uri("https://repositories.tomtom.com/artifactory/maven")
    8 }
    9 }
    10}
  2. Verify that everything works as expected by adding a Maps SDK dependency to the build.gradle.kts file of your application module. For example, com.tomtom.sdk.maps:map-display. Synchronize the project.

    val version = "1.4.0"
    implementation("com.tomtom.sdk.maps:map-display:$version")
  3. Get your TomTom API key from the TomTom Developer Portal. To find out how, refer to the How to get a TomTom API key guide.

  4. Store the TomTom API key to a project property in your project gradle.properties file. Replace api_key_placeholder with the actual TomTom API key.

    tomtomApiKey=api_key_placeholder
  5. Declare the tomtomApiKey variable within the build.gradle.kts file, outside of the android block.

    val tomtomApiKey: String by project
  6. Map the TomTom API key property to a custom field of the gradle BuildConfig class in the android block of your app’s build.gradle.kts file.

    1android {
    2 buildFeatures {
    3 buildConfig = true
    4 }
    5 buildTypes.configureEach {
    6 buildConfigField("String", "TOMTOM_API_KEY", "\"$tomtomApiKey\"")
    7 }
    8}

    To use the TomTom API key in your application code, it is sufficient to access the newly added BuildConfig field.

    val apiKey = BuildConfig.TOMTOM_API_KEY

Now that you’ve completed the project setup, here is what you can do next.

  1. If you don’t have an API key visit a How to get a TomTom API key site and create one.
  2. Create fields with the API keys in your module’s build.gradle.kts, which will be used later in the application:
    1android {
    2 defaultConfig {
    3 manifestPlaceholders["GoogleApiKey"] = "YOUR_GOOGLE_API_KEY"
    4 resValue("string", "maps_api_key", "YOUR_API_KEY")
    5 buildConfigField("String", "ROUTING_API_KEY", ""YOUR_API_KEY"")
    6 }
    7}

Displaying a map

Google

To display the map using the Google Maps SDK for Android, you need to perform these steps:

  1. Add dependencies to your module’s gradle.build file:
    implementation("com.google.android.gms:play-services-maps:18.0.0")
  2. Add a map fragment to the XML layout:
    1<androidx.fragment.app.FragmentContainerView
    2 android:id="@+id/map"
    3 android:name="com.google.android.gms.maps.SupportMapFragment"
    4 android:layout_width="match_parent"
    5 android:layout_height="match_parent" />
  3. Add a Google Android API key inside the application section of the AndroidManifest.xml file:
    1<meta-data
    2 android:name="com.google.android.geo.API_KEY"
    3 android:value="${GoogleApiKey}" />
  4. Implement the MapReadyCallback interface in the MainActivity class and override the OnMapReadyCallback.onMapReady(GoogleMap) method to assign the ready instance of the map to the property.
    override fun onMapReady(googleMap: GoogleMap) {
    this.googleMap = googleMap
  5. In the onCreate method of the MainActivity get the map fragment instance from activity_main.xml. Set MainActivity as a callback object which will be triggered when GoogleMap is ready.
    val mapFragment = supportFragmentManager.findFragmentById(R.id.map) as SupportMapFragment
    mapFragment.getMapAsync(this)

TomTom SDK

To do the same thing in the TomTom SDK for Android:

  1. Add dependency to your module’s gradle.build file:
    implementation("com.tomtom.sdk.maps:map-display:1.4.0")
  2. Add a MapFragment to the main activity layout. Don’t forget to set the API key for the Maps Display module:
    1<androidx.fragment.app.FragmentContainerView
    2 xmlns:tomtom="http://schemas.android.com/apk/res-auto"
    3 android:id="@+id/map_fragment"
    4 android:name="com.tomtom.sdk.map.display.ui.MapFragment"
    5 android:layout_width="match_parent"
    6 android:layout_height="match_parent"
    7 tomtom:mapKey="@string/maps_api_key"
    8 />
  3. Define a TomTomMap property in the MainActivity class.
    private lateinit var tomTomMap: TomTomMap
  4. As with Google, you need to implement the MapReadyCallback interface in the MainActivity class and override the OnMapReadyCallback.onMapReady(TomTomMap) method.
    1 override fun onMapReady(map: TomTomMap) {
    2 this.tomTomMap = map
    3}
  5. In the onCreate method of the MainActivity class, get the map fragment from the layout using FragmentManager. Set the MapReadyCallback that is triggered when the map is ready. The map has to be fully initialized before your app can interact with the TomTomMap object.
    val mapFragment = supportFragmentManager.findFragmentById(R.id.map_fragment) as? MapFragment
    mapFragment?.getMapAsync(this)
Globe view

Displaying a marker

The next step is to allow your user to interact with the map. For instance, displaying a marker at the map location where the user does a long click.

Google

Once the GoogleMap is initialized set the MapLongClickListener.

1this.googleMap.setOnMapLongClickListener { latLng: LatLng ->
2 displayMarkerAt(latLng)
3}

Then set the marker at the selected coordinates.

1private fun displayMarkerAt(latLng: LatLng) {
2 val markerOptions =
3 MarkerOptions()
4 .position(latLng)
5 .title("Long clicked location")
6 googleMap.addMarker(markerOptions)
7}

TomTom SDK

As with Google, the map must be fully initialized before you can interact with it. Add the MapLongClickListener to the TomTomMap object.

1tomTomMap.addMapLongClickListener { geoPoint: GeoPoint ->
2 displayMarkerAt(geoPoint)
3 true
4}

Display a Marker at the map location of a long press.

1private fun displayMarkerAt(geoPoint: GeoPoint) {
2 val markerOptions =
3 MarkerOptions(
4 geoPoint,
5 // No default marker icon
6 ImageFactory.fromResource(com.tomtom.sdk.map.display.common.R.drawable.ic_sdk_tt_compass),
7 label = Label("Long clicked location"),
8 )
9 tomTomMap.addMarker(markerOptions)
10}
center

Displaying traffic

Google

Google has only one method for traffic visualization. That method can only display traffic flow tiles. To show the traffic layer:

googleMap.isTrafficEnabled = true

To hide the traffic layer:

googleMap.isTrafficEnabled = false

TomTom SDK

The TomTom SDK provides two kinds of traffic information: traffic flow and traffic incidents.

  • Traffic flow shows the difference between current and free-flow speed. Green indicates that the speeds are the same, meaning there are no traffic jams. Red indicates that traffic is slower than free-flow, meaning that there are traffic jams.
    tomTomMap.showTrafficFlow()
    tomTomMap.hideTrafficFlow()
  • Traffic incidents shows specific traffic problems such as closed roads, rain, ice on the road, or accidents.
    tomTomMap.showTrafficIncidents()
    tomTomMap.hideTrafficIncidents()
Traffic flow

Displaying a route/directions

Google

Displaying a route in Google Maps SDK for Android is awkward. It boils down to interacting with the Directions API, gathering a list of route positions, then drawing a polyline from that list directly onto the map. This procedure is too verbose and complex to show here.

TomTom SDK

The TomTom Routing API allows the app to easily calculate a route between two points, add waypoints, and specify other route properties. The requested Route can then be drawn on the map in a single step.

  1. To enable the Routing API inside your application, add a dependency to the module’s gradle.build file:
    implementation("com.tomtom.sdk.routing:route-planner-online:1.4.0")
  2. Create an instance of the RoutingApi object.
    1val routingApi =
    2 OnlineRoutePlanner.create(
    3 context = applicationContext,
    4 apiKey = BuildConfig.ROUTING_API_KEY,
    5 )
  3. Construct the RoutePlanningOptions object. This contains route request parameters that will be used for Routing API call.
    1val amsterdam = GeoPoint(52.37, 4.90)
    2val hague = GeoPoint(52.07, 4.30)
    3val routePlanningOptions =
    4 RoutePlanningOptions(
    5 itinerary = Itinerary(origin = amsterdam, destination = hague),
    6 vehicle = Vehicle.Car(),
    7 costModel = CostModel(routeType = RouteType.Short),
    8 )
  4. Provide the created RoutePlanningOptions object as a parameter to the RoutingApi.planRoute(RoutePlanningOptions, RoutePlanningCallback method. The method performs a request for the route using the provided parameters.
    routingApi.planRoute(routePlanningOptions, routePlanningCallback)
  5. The result of request is returned by the RoutePlanningCallback that was provided to the method above. If the call was successful it returns RoutePlanningResponse.

Otherwise, it passes the exception that was raised.

+

1private val routePlanningCallback =
2 object : RoutePlanningCallback {
3 override fun onFailure(failure: RoutingFailure) {
4 Toast.makeText(this@MainActivity, failure.message, Toast.LENGTH_SHORT).show()
5 }
6
7 override fun onSuccess(result: RoutePlanningResponse) {
8 drawRouteOnTheMap(result)
9 }
10
11 override fun onRoutePlanned(route: Route) = Unit
12 }
  1. Get the Route from the RoutePlanningResponse and add it to the TomTomMap.
    1private fun drawRouteOnTheMap(result: RoutePlanningResponse) {
    2 val route = result.routes.first()
    3 val routeOptions =
    4 RouteOptions(
    5 geometry = route.geometry,
    6 departureMarkerVisible = true,
    7 destinationMarkerVisible = true,
    8 )
    9 tomTomMap.addRoute(routeOptions)
    10 tomTomMap.zoomToRoutes()
    11}
Adding a route

Showing user location

To use the user’s location in Android, the app must request location permissions. These steps must be performed for both the TomTom SDK and the Google Maps SDK.

  1. Add location permissions to the AndroidManifest.xml:
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
  2. Register the location permission callback to handle the user’s response to the system permissions dialog.
    1private val locationPermissionRequest =
    2 registerForActivityResult(
    3 ActivityResultContracts.RequestMultiplePermissions(),
    4 ) { permissions ->
    5 if (permissions[Manifest.permission.ACCESS_FINE_LOCATION] == true &&
    6 permissions[Manifest.permission.ACCESS_COARSE_LOCATION] == true
    7 ) {
    8 showUserLocation()
    9 } else {
    10 Toast.makeText(
    11 this,
    12 getString(R.string.location_permission_denied),
    13 Toast.LENGTH_SHORT,
    14 ).show()
    15 }
    16 }
  3. Request permission in runtime to let the user decide whether to allow location permissions.
    1private fun enableUserLocation() {
    2 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
    3 == PackageManager.PERMISSION_GRANTED &&
    4 ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
    5 == PackageManager.PERMISSION_GRANTED
    6 ) {
    7 showUserLocation()
    8 } else {
    9 locationPermissionRequest.launch(
    10 arrayOf(
    11 Manifest.permission.ACCESS_FINE_LOCATION,
    12 Manifest.permission.ACCESS_COARSE_LOCATION,
    13 ),
    14 )
    15 }
    16}

Google

In Google you can enable location and the location button as follows:

1@SuppressLint("MissingPermission")
2private fun showUserLocation() {
3 googleMap.isMyLocationEnabled = true
4 googleMap.uiSettings.isMyLocationButtonEnabled = true
5}

TomTom SDK

In the TomTom SDK you can either use a pre-defined location provider, or define your own LocationProvider to provide location updates to the map. This tutorial focuses on the pre-defined AndroidLocationProvider. This engine relies on the Android system location services, meaning that it does not require Google services. For more information read Built-in Location Provider guide.

  1. Add the AndroidLocationProvider dependency:
    implementation("com.tomtom.sdk.location:provider-android:1.4.0")
  2. Create a LocationProvider property and initialize AndroidLocationProvider.
  3. Set LocationProvider to the map.
  4. Enable LocationProvider to start updating the user’s location.
  5. Show the user location on the map. To do this, enable LocationMarker on the map and set its specifications using LocationMarkerOptions.
1private fun showUserLocation() {
2 locationProvider = AndroidLocationProvider(context = this)
3 locationProvider?.let {
4 tomTomMap.setLocationProvider(it)
5 it.enable()
6 tomTomMap.enableLocationMarker(LocationMarkerOptions(LocationMarkerOptions.Type.Pointer))
7 }
8}
Location pointer

Summary

This tutorial instructed you on how to move a basic app from Google’s SDKs to TomTom’s SDKs. Now you can enrich your app with TomTom’s features and functions.

If you want to learn more, take a look at our other tutorials: