Migrate from Mapbox

VERSION 0.3.34
PUBLIC PREVIEW

This tutorial shows some of the differences between Mapbox SDK and TomTom SDKs. For this purpose, a simple navigation application was created using Mapbox and TomTom SDKs. The application displays a map with the user’s location on it. The user can also enable and disable the traffic layer on the map. The app draws a marker at a place selected by the user with a long click on the map. It then calculates a route from the user’s location to the selected destination and adds it to the map. Finally, it performs navigation along the route. During navigation, the app provides information about upcoming maneuvers, estimated remaining time and distance of the trip, and speed limits.

Prerequisites

This tutorial does not discuss the configuration of Mapbox SDK in the project. The following steps describe how to prepare your project to use the TomTom SDKs.

  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 the 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 defaultConfig {
    3 resValue "string", "mapbox_access_token", "YOUR_MAPBOX_ACCESS_TOKEN"
    4
    5 buildConfigField("String", "MAPS_API_KEY", ""YOUR_API_KEY"")
    6 buildConfigField("String", "ROUTING_API_KEY", ""YOUR_API_KEY"")
    7 buildConfigField("String", "NAVIGATION_API_KEY", ""YOUR_API_KEY"")
    8 }
    9}

Displaying a map

Mapbox

To display a map using the Mapbox Maps SDK for Android, complete the following steps:

  1. Add the maps dependency in your module’s build.gradle.
    1dependencies {
    2 implementation "com.mapbox.maps:android:10.3.0"
    3}
  2. In the XML layout, provide the MapView map interface.
    1<com.mapbox.maps.MapView
    2 android:id="@+id/mapView"
    3 android:layout_width="match_parent"
    4 android:layout_height="0dp"
    5 app:layout_constraintBottom_toTopOf="@+id/configuration_view"
    6 app:layout_constraintEnd_toEndOf="parent"
    7 app:layout_constraintStart_toStartOf="parent"
    8 app:layout_constraintTop_toTopOf="parent" />
  3. Finally, get the instance of the map in the activity/fragment.
    1mapView = binding.mapView
    2mapboxMap = mapView.getMapboxMap()
    3mapboxMap.loadStyleUri(Style.MAPBOX_STREETS)

TomTom SDKs

To do the same using the TomTom SDKs perform following steps:

  1. Add the Map Display module dependency to the module’s build.gradle.
    1dependencies {
    2 implementation "com.tomtom.sdk:maps-display:0.3.34"
    3}
  2. Provide a container within which the map will be displayed to the XML layout.
    1<androidx.fragment.app.FragmentContainerView
    2 android:id="@+id/map_container"
    3 android:layout_width="match_parent"
    4 android:layout_height="0dp"
    5 app:layout_constraintBottom_toTopOf="@+id/configuration_view"
    6 app:layout_constraintEnd_toEndOf="parent"
    7 app:layout_constraintStart_toStartOf="parent"
    8 app:layout_constraintTop_toTopOf="parent" />
  3. In the activity/fragment, configure MapOptions and initialize MapFragment. Place the instance of it in the previously-prepared container.
    1val mapOptions = MapOptions(
    2 mapKey = BuildConfig.MAPS_API_KEY,
    3)
    4val mapFragment = MapFragment.newInstance(mapOptions)
    5childFragmentManager.beginTransaction()
    6 .replace(R.id.map_container, mapFragment)
    7 .commit()
  4. Every interaction performed on the map is handled using the TomTomMap object. To get the map instance set an OnMapReadyCallback to the MapFragment.
    1mapFragment.getMapAsync { map ->
    2 this.tomTomMap = map
    3 showUserLocation()
    4 showTraffic(configurationView.trafficSwitch.isChecked)
    5 handleTrafficSwitch()
    6 handleMapLongClick()
    7}

Globe view

Showing user location

The next step is showing the user location on the map. To do this, Android requires the user to grant ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions. On devices that run Android 6.0 or higher, you must request permissions at runtime. Check how to grant location permissions in Android here.

Mapbox

To show the user location on the map in the Mapbox SDK, enable the location plugin.

1val locationPlugin = mapView.location
2locationPlugin.updateSettings {
3 this.enabled = true
4 this.locationPuck = locationPlugin.createDefault2DPuck(requireContext())
5}
6locationPlugin.addOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener)

Observe the indicator position changes to get the latest updated user location.

1private val onIndicatorPositionChangedListener = OnIndicatorPositionChangedListener {
2 lastUserLocation = it
3}

TomTom SDKs

Use LocationEngine to display the user location in the TomTom SDKs. Provide the initialized engine to the TomTomMap instance and enable it to start updating the location. Then set the location marker that will show the user location on the map. If you want to read more about LocationEngine implementations see the Build-in Location Engine guide.

1locationEngine = AndroidLocationEngine(context = requireContext())
2tomTomMap.setLocationEngine(locationEngine)
3locationEngine.enable()
4tomTomMap.enableLocationMarker(LocationMarkerOptions(LocationMarkerType.POINTER))

Use the last known location provided by LocationEngine as the user’s current location.

val origin = locationEngine.lastKnownLocation?.position ?: return

Location pointer

Adding a marker

This section describes how to put a marker on the map where the user has performed a long click.

Mapbox

The gestures in the Mapbox SDK are handled by the gestures plugin. To detect a long click on the map, set the listener to the plugin.

1mapView.gestures.addOnMapLongClickListener { point: Point ->
2 if (mapboxNavigation.getNavigationSessionState() == NavigationSessionState.Idle) {
3 displayMarker(point)
4 requestRoute(point)
5 }
6 true
7}

To operate on markers, start by creating a point annotation manager on the map instance.

annotationManager = mapView.annotations.createPointAnnotationManager()

Use PointAnnotationOptions to specify the marker configuration. Then use the manager to add it to the map.

1val icon = BitmapFactory.decodeResource(resources, R.drawable.ic_sdk_tt_compass)
2 ?: return // Mapbox does not provide default marker
3annotationManager.deleteAll()
4val pointAnnotationOptions = PointAnnotationOptions()
5 .withPoint(point)
6 .withIconImage(icon)
7 .withIconColor(Color.RED)
8annotationManager.create(pointAnnotationOptions)

TomTom SDKs

In the TomTom SDKs, gestures performed on the map are observed by setting various callbacks. In this tutorial, the OnMapLongClickListener is used. The usage of other gesture listeners is similar.

1tomTomMap.addOnMapLongClickListener { coordinate: GeoCoordinate ->
2 if (!isNavigationRunning) {
3 displayMarker(coordinate)
4 requestRoute(coordinate)
5 }
6 true
7}

To display a marker at the selected coordinates, first define its options using the MarkerOptions class. The configured marker is then added to the TomTomMap instance. Read more about markers in the Working with markers guide.

1tomTomMap.clear()
2val markerOptions = MarkerOptions(
3 coordinate = coordinate,
4 pinImage = ImageFactory.fromResource(R.drawable.ic_sdk_tt_compass)
5)
6tomTomMap.addMarker(markerOptions)

center

Showing a traffic layer

Both SDKs support showing traffic flow on the map. Flow is indicated by different colors on roads, depending on the degree of delay.

Mapbox

To show traffic on the map in the Mapbox SDK, load the special map style that contains that feature.

1if (!showTraffic) {
2 mapboxMap.loadStyleUri(Style.MAPBOX_STREETS)
3} else {
4 mapboxMap.loadStyleUri(Style.TRAFFIC_DAY)
5}

TomTom SDKs

In the TomTom SDKs, traffic flow is shown as a layer on the map.

TomTom SDKs also support showing traffic incidents.

1if (!showTraffic) {
2 tomTomMap.hideTrafficFlow()
3 tomTomMap.hideTrafficIncidents()
4} else {
5 tomTomMap.showTrafficFlow()
6 tomTomMap.showTrafficIncidents()
7}

Traffic flow

Drawing a route

This section describes how to calculate and draw a route from the user location to the destination the user has already chosen with a long click.

Mapbox

To plan a route between the chosen points, initialize MapboxNavigation.

1val navigationOptions = NavigationOptions.Builder(requireContext())
2 .accessToken(getString(R.string.mapbox_access_token))
3 .locationEngine(replayLocationEngine) // Add simulation location engine
4 .build()
5mapboxNavigation = if (MapboxNavigationProvider.isCreated()) {
6 MapboxNavigationProvider.retrieve()
7} else {
8 MapboxNavigationProvider.create(navigationOptions)
9}

Use the RouteOptions class to prepare the routing request. After the configured request is performed, the result is returned via RouterCallback.

1val origin = lastUserLocation ?: return
2val routeOptions = RouteOptions.builder()
3 .applyDefaultNavigationOptions()
4 .coordinates(origin = origin, destination = destination)
5 .build()
6mapboxNavigation.requestRoutes(
7 routeOptions,
8 object : RouterCallback {
9 override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) = Unit
10
11 override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
12 (requireActivity() as MainActivity).showToast(getString(R.string.routing_request_failed))
13 }
14
15 override fun onRoutesReady(routes: List<DirectionsRoute>, routerOrigin: RouterOrigin) {
16 mapboxNavigation.setRoutes(routes)
17 drawRoutes(routes)
18 enableNavigation()
19 }
20 }
21)

If the call is successful the returned routes are drawn on the map. Before drawing them on the map, initialize MapboxRouteLineApi and MapboxRouteLineView. The route style is defined using MapboxRouteLineOptions.

private val routeLineApi: MapboxRouteLineApi by lazy { MapboxRouteLineApi(routeLineOptions) }
private val routeLineView: MapboxRouteLineView by lazy { MapboxRouteLineView(routeLineOptions) }

Once the above classes are initialized you can render the calculated route on the map.

1private fun drawRoutes(routes: List<DirectionsRoute>) {
2 val routeLines = routes.map { RouteLine(it, null) }
3 routeLineApi.setRoutes(routeLines) { routeDrawData ->
4 mapboxMap.getStyle()?.let { mapStyle ->
5 routeLineView.renderRouteDrawData(mapStyle, routeDrawData)
6 }
7 }
8}

TomTom SDKs

To request a route requires a RoutingApi object, which is an access point to the routing functionalities. To create it use the OnlineRoutingApi class.

routingApi = OnlineRoutingApi.create(requireContext(), BuildConfig.ROUTING_API_KEY)

The routing request is configured similarly to the Mapbox SDK using the RoutingOptions class. The RoutingOptions object is provided to the routing request. The result of the call is returned via RoutingCallback.

1val origin = locationEngine.lastKnownLocation?.position ?: return
2val routingOptions = RoutingOptions.Builder(Itinerary(origin, destination))
3 .instructionType(InstructionType.TAGGED)
4 .instructionPhonetics(InstructionPhoneticsType.IPA)
5 .instructionAnnouncementPoints(AnnouncementPoints.ALL)
6 .sectionTypes(listOf(SectionType.LANES, SectionType.SPEED_LIMIT, SectionType.MOTORWAY))
7 .build()
8routingApi.planRoute(
9 routingOptions,
10 object : RoutingCallback {
11 override fun onSuccess(result: RoutingResult) {
12 tomTomMap.removeMarkers()
13 result.routes.firstOrNull()?.let {
14 drawRoute(it)
15 tomTomMap.zoomToRoutes(64)
16 routePlan = RoutePlan(it, routingOptions)
17 }
18 }
19
20 override fun onError(error: RoutingError) {
21 (requireActivity() as MainActivity).showToast(getString(R.string.routing_request_failed))
22 }
23 }
24)

If the routing call is successful, you can draw the Route on the map. To draw it, configure the RouteOptions object, which specifies the appearance of the route, and add it to the TomTomMap.

1private fun drawRoute(route: Route) {
2 val geometry = route.geometry
3 val routeOptions = RouteOptions(
4 geometry = geometry,
5 departureMarkerVisible = true,
6 destinationMarkerVisible = true
7 )
8 tomTomMap.addRoute(routeOptions)
9}

Adding a route

Read more about routing in the Planning a route guide.

The last part of this tutorial is about navigation along the previously calculated route. Navigation shows the current speed limit, the next maneuver, and the estimated time and distance remaining for the trip. For the purpose of this tutorial, navigation is simulated in both cases. To use real location data for navigation you have to replace LocationEngine with the one that will provide real data.

Mapbox

Only the main functions of Mapbox SDK navigation will be described. The entry point to navigation is the MapboxNavigation class. An instance of it was already created for planning a route. The ReplayLocationEngine was provided during initialization. This engine is responsible for simulating location updates.

Set the route returned by the routing request to navigation. The route defines a list of coordinates along which navigation will be performed.

mapboxNavigation.setRoutes(routes)

Once the route is set to navigation, you can start the trip session.

1mapboxNavigation.startTripSession()
2setChevronLocationPuck()
3navigationCamera.requestNavigationCameraToFollowing()
4startLocationSimulationUpdates(route)
5showNavigationComponents()

Navigation UI components have to be configured and initialized separately. This tutorial only discusses the maneuver component, which displays the next action and the distance to it.

First, add the maneuver view to the layout.

1<com.mapbox.navigation.ui.maneuver.view.MapboxManeuverView
2 android:id="@+id/maneuver_view"
3 android:layout_width="match_parent"
4 android:layout_height="wrap_content"
5 android:visibility="gone"
6 android:layout_margin="4dp"
7 app:layout_constraintEnd_toEndOf="parent"
8 app:layout_constraintStart_toStartOf="parent"
9 app:layout_constraintTop_toTopOf="parent" />

Then you can access the view in the activity/fragment.

maneuverView = binding.maneuverView

Once the maneuver view is ready, update it with the upcoming maneuvers during the navigation session. To do this, MapboxManeuverApi has to be initialized.

1private val distanceFormatter: DistanceFormatterOptions by lazy {
2 DistanceFormatterOptions.Builder(requireContext())
3 .unitType(UnitType.METRIC)
4 .build()
5}
6
7private val maneuverApi: MapboxManeuverApi by lazy {
8 MapboxManeuverApi(MapboxDistanceFormatter(distanceFormatter))
9}

Maneuvers are updated depending on the progress along the route. This means that the progress has to be observed and the related data supplied to the maneuver API. Then the view will be updated.

1private val routeProgressObserver = RouteProgressObserver { routeProgress ->
2 viewportDataSource.onRouteProgressChanged(routeProgress)
3 viewportDataSource.evaluate()
4 displayManeuver(routeProgress)
5 displayTripProgress(routeProgress)
6}
7private fun displayManeuver(routeProgress: RouteProgress) {
8 val maneuvers = maneuverApi.getManeuvers(routeProgress)
9 maneuverView.renderManeuvers(maneuvers)
10}

Each of the navigation UI components is handled in a similar way. Some of them need different listeners, to observe different navigation data.

TomTom SDKs

This tutorial contains a superficial description of navigation. If you want to learn more about how to use the Navigation SDK, you can read the guides. A good place to start is Navigation quickstart guide.

The entry point to interact with navigation is the TomTomNavigation class. Therefore it has to be initialized before starting a trip session. This application uses SimulationLocationEngine to simulate navigation. It can be replaced with any other LocationEngine. Read about different types of LocationEngine and how they work in the TomTom SDKs in the Built-in Location Engine guide.

1val routeGeometry =
2 routePlan?.route?.geometry?.map { GeoLocation(position = it) } ?: return
3val simulationStrategy =
4 InterpolationStrategy(routeGeometry, currentSpeedInMetersPerSecond = 20.0)
5locationEngine = SimulationLocationEngine.create(simulationStrategy)
6val navigationConfiguration = NavigationConfiguration.Builder(
7 context = requireContext(),
8 navigationApiKey = BuildConfig.NAVIGATION_API_KEY,
9 locationEngine = locationEngine,
10 routingApi = routingApi
11).build()
12tomTomNavigation = TomTomNavigation.create(navigationConfiguration)

center

Summary

This tutorial only described some of the functionalities of the TomTom SDKs. If you want to learn more, see the documentation and the rest of our tutorials.