Migrate from Mapbox
This tutorial contrasts features of the Mapbox SDK and TomTom SDKs. It uses a simple navigation application created using both the Mapbox and TomTom SDKs to highlight these differences. The application displays the user’s location on a map. It also allows the user to enable and disable a traffic layer on the map. When the user does a long tap on the map, the app draws a marker at the selected location. Next, the app calculates a route from the user’s location to the selected destination and displays it on the map. Finally, the app performs navigation along the route. During navigation, the app provides information about upcoming maneuvers, the estimated time and distance remaining on 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:
-
Install Android Studio if you don’t already have it.
-
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.
-
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’sbuild.gradle.kts
file.1android {2 defaultConfig {3 minSdk = 264 }5} -
To prevent duplication of the
libc++_shared.so
file in your Android Gradle build, add the following packaging option to theandroid
block of your app’sbuild.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. -
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
-
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} -
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.20.1"implementation("com.tomtom.sdk.maps:map-display:$version") -
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.
-
Store the TomTom API key to a project property in your project
gradle.properties
file. Replaceapi_key_placeholder
with the actual TomTom API key.tomtomApiKey=api_key_placeholder -
Declare the tomtomApiKey variable within the
build.gradle.kts
file, outside of theandroid
block.val tomtomApiKey: String by project -
Map the TomTom API key property to a custom field of the gradle
BuildConfig
class in theandroid
block of your app’sbuild.gradle.kts
file.1android {2 buildFeatures {3 buildConfig = true4 }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.
- If you don’t have an API Key visit the How to get a TomTom API Key site and create one.
- 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 resValue("string", "mapbox_access_token", "YOUR_MAPBOX_ACCESS_TOKEN")4 buildConfigField("String", "TOMTOM_API_KEY", ""YOUR_TOMTOM_API_KEY"")5 }6}
Displaying a map
Mapbox
To display a map using the Mapbox Maps SDK for Android, complete the following steps:
- Add the maps dependency in your module’s
build.gradle.kts
.implementation("com.mapbox.maps:android:10.3.0") - In the XML layout, provide the
MapView
map interface.1<com.mapbox.maps.MapView2 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" /> - Finally, get the instance of the map in the activity/fragment.
1mapView = binding.mapView2mapboxMap = mapView.getMapboxMap()3mapboxMap.loadStyleUri(Style.MAPBOX_STREETS)
TomTom SDKs
To display a map using the TomTom SDKs, perform the following steps:
- Add the Map Display module dependency to the module’s
build.gradle.kts
.implementation("com.tomtom.sdk.maps:map-display:1.20.1") - Provide a container within which the map will be displayed to the XML layout.
1<androidx.fragment.app.FragmentContainerView2 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" />
- In the activity/fragment, configure
MapOptions
and initializeMapFragment
. Place that instance in the container you prepared in the previous step.1val mapOptions =2 MapOptions(3 mapKey = BuildConfig.TOMTOM_API_KEY,4 )5val mapFragment = MapFragment.newInstance(mapOptions)6childFragmentManager.beginTransaction()7 .replace(R.id.map_container, mapFragment)8 .commit() - Every interaction performed on the map is handled using the
TomTomMap
object. To get the map instance set anMapReadyCallback
to theMapFragment
.1mapFragment.getMapAsync { map ->2 this.tomTomMap = map3 showUserLocation()4 showTraffic(configurationView.trafficSwitch.isChecked)5 handleTrafficSwitch()6 handleMapLongClick()7}
Showing user location
The next step is showing the user location on the map. To do this, Android requires the user to grant permissions for ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION. On devices that run Android 6.0 or higher, you must request permissions at runtime. Check how to grant location permissions in Android by visiting here.
Mapbox
To show the user’s map location in the Mapbox SDK, enable the location plugin.
1val locationPlugin = mapView.location2locationPlugin.updateSettings {3 this.enabled = true4 this.locationPuck = locationPlugin.createDefault2DPuck(requireContext())5}6locationPlugin.addOnIndicatorPositionChangedListener(onIndicatorPositionChangedListener)
Observe the indicator position changes to get the latest updated user location.
1private val onIndicatorPositionChangedListener =2 OnIndicatorPositionChangedListener {3 lastUserLocation = it4 }
TomTom SDKs
Use LocationProvider
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 LocationProvider
implementations see the Built-in Location Provider guide.
1locationProvider = DefaultLocationProviderFactory.create(context = requireContext())2tomTomMap.setLocationProvider(locationProvider)3locationProvider.enable()4tomTomMap.enableLocationMarker(LocationMarkerOptions(LocationMarkerOptions.Type.Pointer))
Use the last known location provided by LocationProvider
as the user’s current location.
val origin = locationProvider.lastKnownLocation?.position ?: return
Adding a marker
This section describes how to add a marker to the map where the user has performed a long click.
Mapbox
The gestures in the Mapbox SDK are handled by the GesturesPlugin. 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 true7}
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 =2 BitmapFactory.decodeResource(3 resources,4 com.tomtom.sdk.map.display.common.R.drawable.ic_sdk_tt_compass,5 )6 ?: return // Mapbox does not provide default marker7annotationManager.deleteAll()8val pointAnnotationOptions =9 PointAnnotationOptions()10 .withPoint(point)11 .withIconImage(icon)12 .withIconColor(Color.RED)13annotationManager.create(pointAnnotationOptions)
TomTom SDKs
In the TomTom SDKs, gestures performed on the map are observed by setting various callbacks. In this tutorial, the MapLongClickListener
is used. The usage of other gesture listeners is similar.
1tomTomMap.addMapLongClickListener { coordinate: GeoPoint ->2 if (!isNavigationRunning) {3 displayMarker(coordinate)4 requestRoute(coordinate)5 }6 true7}
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. You can read more about markers in the Working with markers guide.
1tomTomMap.clear()2val markerOptions =3 MarkerOptions(4 coordinate = coordinate,5 pinImage = ImageFactory.fromResource(com.tomtom.sdk.map.display.common.R.drawable.ic_sdk_tt_compass),6 )7tomTomMap.addMarker(markerOptions)
Showing a traffic layer
Both the TomTom and Mapbox SDKs support displaying 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}
Drawing a route
This section describes how to calculate and draw a route from the user’s location to a destination selected with a long click.
Mapbox
To plan a route between the chosen points, initialize MapboxNavigation
.
1val navigationOptions =2 NavigationOptions.Builder(requireContext())3 .accessToken(getString(R.string.mapbox_access_token))4 .locationEngine(replayLocationEngine) // Add simulation location engine5 .build()6mapboxNavigation =7 if (MapboxNavigationProvider.isCreated()) {8 MapboxNavigationProvider.retrieve()9 } else {10 MapboxNavigationProvider.create(navigationOptions)11 }
Use the RouteOptions
class to prepare the routing request. After the configured request is performed, the result is returned via RouterCallback
.
1val origin = lastUserLocation ?: return2val routeOptions =3 RouteOptions.builder()4 .applyDefaultNavigationOptions()5 .coordinates(origin = origin, destination = destination)6 .build()7mapboxNavigation.requestRoutes(8 routeOptions,9 object : RouterCallback {10 override fun onCanceled(11 routeOptions: RouteOptions,12 routerOrigin: RouterOrigin,13 ) = Unit1415 override fun onFailure(16 reasons: List<RouterFailure>,17 routeOptions: RouteOptions,18 ) {19 (requireActivity() as MainActivity).showToast(getString(R.string.routing_request_failed))20 }2122 override fun onRoutesReady(23 routes: List<DirectionsRoute>,24 routerOrigin: RouterOrigin,25 ) {26 mapboxNavigation.setRoutes(routes)27 drawRoutes(routes)28 enableNavigation()29 }30 },31)
If the call is successful the returned routes are drawn on the map. Before drawing the routes on the map, initialize MapboxRouteLineApi
and MapboxRouteLineView
. Define the route style using MapboxRouteLineOptions
.
private val routeLineApi: MapboxRouteLineApi by lazy { MapboxRouteLineApi(routeLineOptions) }private val routeLineView: MapboxRouteLineView by lazy { MapboxRouteLineView(routeLineOptions) }
Once the previous 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 OnlineRoutePlanner
class.
routePlanner = OnlineRoutePlanner.create(requireContext(), BuildConfig.TOMTOM_API_KEY)
The routing request is configured similarly to the Mapbox SDK using the RoutePlanningOptions
class. The RoutePlanningOptions
object is provided to the routing request. The result of the call is returned via RoutePlanningCallback
.
1val origin = locationProvider.lastKnownLocation?.position ?: return2val routePlanningOptions =3 RoutePlanningOptions(4 itinerary = Itinerary(origin = origin, destination = destination),5 guidanceOptions =6 GuidanceOptions(7 phoneticsType = InstructionPhoneticsType.Ipa,8 extendedSections = ExtendedSections.All,9 ),10 )11routePlanner.planRoute(12 routePlanningOptions,13 object : RoutePlanningCallback {14 override fun onSuccess(result: RoutePlanningResponse) {15 tomTomMap.removeMarkers()16 result.routes.firstOrNull()?.let {17 drawRoute(it)18 tomTomMap.zoomToRoutes(64)19 routePlan = RoutePlan(it, routePlanningOptions)20 }21 }2223 override fun onFailure(failure: RoutingFailure) {24 (requireActivity() as MainActivity).showToast(getString(R.string.routing_request_failed))25 }2627 override fun onRoutePlanned(route: Route) = Unit28 },29)
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.geometry3 val routeOptions =4 RouteOptions(5 geometry = geometry,6 departureMarkerVisible = true,7 destinationMarkerVisible = true,8 )9 tomTomMap.addRoute(routeOptions)10}
Read more about routing in the Planning routes guide.
Navigation
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 purposes of this tutorial, navigation is simulated in both cases. To use real location data for navigation you must replace LocationProvider
with one that provides real data.
Mapbox
Only the main functions of Mapbox SDK navigation are described. The entry point to navigation is the MapboxNavigation
class. An instance of it was already created for planning a route. The ReplayLocationProvider
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 is 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 must 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.MapboxManeuverView2 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
must be initialized.
1private val distanceFormatter: DistanceFormatterOptions by lazy {2 DistanceFormatterOptions.Builder(requireContext())3 .unitType(UnitType.METRIC)4 .build()5}67private 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 must be observed and the related data supplied to the maneuver API. Then the view is updated.
1private val routeProgressObserver =2 RouteProgressObserver { routeProgress ->3 viewportDataSource.onRouteProgressChanged(routeProgress)4 viewportDataSource.evaluate()5 displayManeuver(routeProgress)6 displayTripProgress(routeProgress)7 }8private fun displayManeuver(routeProgress: RouteProgress) {9 val maneuvers = maneuverApi.getManeuvers(routeProgress)10 maneuverView.renderManeuvers(maneuvers)11}
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 must be initialized before starting a trip session. This application uses SimulationLocationProvider
to simulate navigation. It can be replaced with any other LocationProvider
. Read about different types of `LocationProvider`s and how they work in the TomTom SDKs in the Built-in Location Provider guide.
1navigationTileStore =2 NavigationTileStore.create(3 context = requireContext(),4 navigationTileStoreConfig =5 NavigationTileStoreConfiguration(6 apiKey = BuildConfig.TOMTOM_API_KEY,7 ),8 )9val routeGeometry =10 routePlan?.route?.geometry?.map { GeoLocation(position = it) } ?: return11val simulationStrategy =12 InterpolationStrategy(routeGeometry, currentSpeed = Speed.metersPerSecond(20.0))13locationProvider = SimulationLocationProvider.create(simulationStrategy)14tomTomNavigation =15 OnlineTomTomNavigationFactory.create(16 OnlineConfiguration(17 context = requireContext(),18 navigationTileStore = navigationTileStore,19 locationProvider = locationProvider,20 routePlanner = routePlanner,21 ),22 )
Summary
This tutorial instructed you on how to move a basic app from Mapbox’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: