Migrate from Google

VERSION 0.3.1056
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. Create a new project or open an existing one. Make sure that the minimum SDK API level is set to at least 21 (Android 5.0 "Lollipop") and that compile SDK API level is set to 31.
  3. Add the packagingOptions.
    1android {
    2 ...
    3 packagingOptions {
    4 pickFirst "lib/**/libc++_shared.so"
    5 }
    6}
  4. To get access to the TomTom SDK repository, add the following to your settings.gradle file
    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}
  5. If you don’t have an API key visit a How to get a TomTom API key site and create one.
  6. Create fields with the API keys in your module’s build.gradle, which will be used later in the application:
    1android {
    2 ...
    3 defaultConfig {
    4 ...
    5 manifestPlaceholders = ["GoogleApiKey" : "YOUR_GOOGLE_API_KEY"]
    6
    7 resValue "string", "maps_api_key", "YOUR_API_KEY"
    8 buildConfigField("String", "ROUTING_API_KEY", ""YOUR_API_KEY"")
    9 }
    10 ...
    11}

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 OnMapReadyCallback 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:0.3.1056"
  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 OnMapReadyCallback 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 OnMapReadyCallback 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 OnMapLongClickListener.

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 = MarkerOptions()
3 .position(latLng)
4 .title("Long clicked location")
5 googleMap.addMarker(markerOptions)
6}

TomTom SDK

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

1tomTomMap.addOnMapLongClickListener { 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 = MarkerOptions(
3 geoPoint,
4 ImageFactory.fromResource(R.drawable.ic_sdk_tt_compass), // No default marker icon
5 label = Label("Long clicked location")
6 )
7 tomTomMap.addMarker(markerOptions)
8}

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:0.3.1056"
  2. Create an instance of the RoutingApi object.
    1val routingApi = OnlineRoutePlanner.create(
    2 context = applicationContext,
    3 apiKey = BuildConfig.ROUTING_API_KEY
    4)
  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 = RoutePlanningOptions(
    4 itinerary = Itinerary(origin = amsterdam, destination = hague),
    5 vehicle = Vehicle.Car(),
    6 costModel = CostModel(routeType = RouteType.Short)
    7)
  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 RoutePlanningResult.

Otherwise, it passes the exception that was raised.

+

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

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 = registerForActivityResult(
    2 ActivityResultContracts.RequestMultiplePermissions()
    3) { permissions ->
    4 if (permissions[Manifest.permission.ACCESS_FINE_LOCATION] == true &&
    5 permissions[Manifest.permission.ACCESS_COARSE_LOCATION] == true
    6 ) {
    7 showUserLocation()
    8 } else {
    9 Toast.makeText(
    10 this,
    11 getString(R.string.location_permission_denied),
    12 Toast.LENGTH_SHORT
    13 ).show()
    14 }
    15}
  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 engine, 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 Engine guide.

  1. Add the AndroidLocationProvider dependency:
    implementation "com.tomtom.sdk.location:provider-android:0.3.1056"
  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: