Skip to main content
GuidesAPI ReferenceExamples

Route Navigation

|

In this guide you will learn how to do real navigation along a computed route rendered on an interactive map, from the current position to a desired destination.

Preview of route to navigate

Starting a navigation

Inside MainActivity.ky retain a RoutingService instance. Normally in Android's MVVM, services are retained in the Repository layer, injected via dependency injection, and ultimately consumed by ViewModels but for the scope of this example we will use it inside an activity. The routing service has a NavigationListener and a ProgressListener which will update the UI.

MainActivity.kt
class MainActivity : AppCompatActivity()
{
//...
private val navigationService = NavigationService()

private val navRoute: Route?
get() = navigationService.getNavigationRoute(navigationListener)


private val navigationListener: NavigationListener = NavigationListener.create(
onNavigationStarted = {
SdkCall.execute {
gemSurfaceView.mapView?.let { mapView ->
mapView.preferences?.enableCursor = false
navRoute?.let { route ->
mapView.presentRoute(route)
val remainingDistance = route.getTimeDistance(true)?.totalDistance ?: 0
Toast.makeText(
this@MainActivity,
"Distance to destination $remainingDistance m",
Toast.LENGTH_LONG
).show()
}

enableGPSButton()
mapView.followPosition()
}
}
}
)

//...

// Define a listener that will let us know the progress of the routing process.
private val routingProgressListener = ProgressListener.create(
onStarted = {
progressBar.visibility = View.VISIBLE
},

onCompleted = { _, _ ->
progressBar.visibility = View.GONE
},

postOnMain = true
)
//...
}

The NavigationListener receives event updates during navigation such as when the destination is reached, or when the route to the desired destination has been recomputed, because a detour away from the original route was taken. Other events include turn instructions, passed waypoints, voiced instructions, navigation errors and so on.

When the navigation starts the resulting route is shown on map and the follow position button is enabled. The follow position button has a click listener that calls mapView.followPosition() which will make the camera follow the current position at an angle.

Starting the navigation requiers the user to give permission to access location and location activated. The check for current position is done with PositionService that uses a PositionListener get the first available position. After the first valid position is received navigation is started.

MainActivity.kt
class MainActivity : AppCompatActivity()
{
//...
override fun onCreate(savedInstanceState: Bundle?)
{
//...
SdkSettings.onMapDataReady = onMapDataReady@{ isReady ->
if (!isReady) return@onMapDataReady

// Defines an action that should be done when the world map is ready (Updated/ loaded).
startNavigation()
}
//...
}
//...
private fun startNavigation()
{
val startNavTask = {
val hasPermissions =
PermissionsHelper.hasPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)

if (hasPermissions) {
val destination = Landmark("Paris", 48.8566932, 2.3514616)

// Cancel any navigation in progress.
navigationService.cancelNavigation(navigationListener)
// Start the new navigation.
val error = navigationService.startNavigation(
destination,
navigationListener,
routingProgressListener,
)
Log.i(TAG, "MainActivity.startNavigation: after = $error")
}
}

SdkCall.execute {
lateinit var positionListener: PositionListener
if (PositionService.position?.isValid() == true)
{
startNavTask()
}
else
{
positionListener = PositionListener {
if (!it.isValid()) return@PositionListener

PositionService.removeListener(positionListener)
startNavTask()
}

// listen for first valid position to start the nav
PositionService.addListener(positionListener)
}
}
}
//...
}