Route Alarms
In this guide you will learn how to simulate navigation along a computed route rendered on an interactive map, from a departure position to a desired destination. The map is fully 3D, supporting pan, pinch-zoom, rotate and tilt. The navigation includes pop-up speed camera warnings.
Setup
- Get your Magic Lane API key token: if you do not have a token, see the Getting Started guide
- Download the Maps & Navigation SDK for Android archive file
- Download the RouteAlarms project archive file or clone the project with Git
- See the Configure Android Example guide
Run the example
In Android Studio, from the File
menu, select Sync Project with Gradle Files
An android device should be connected via USB cable.
Press SHIFT+F10 to compile, install and run the example on the android device.

How it works
You can open the MainActivity.kt file to see how simulated navigation along a computed route with speed camera warning alarms works.
private val navigationService = NavigationService()
A NavigationService()
is instantiated, which carries out both simulated navigation and real navigation.
private val navigationListener = NavigationListener.create(
onNavigationStarted = {
SdkCall.execute {
// Set the overlay for which to be notified.
setAlarmOverlay(ECommonOverlayId.Safety)
gemSurfaceView.mapView?.let { mapView ->
mapView.preferences?.enableCursor = false
navRoute?.let { route ->
mapView.presentRoute(route)
}
enableGPSButton()
mapView.followPosition()
}
}
}
)
The NavigationListener
receives event updates (notifications) from the navigation service, during navigation or simulation on a route, 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.
Only the onNavigationStarted
listener is instantiated in this case.
private val alarmListener = AlarmListener.create(
onOverlayItemAlarmsUpdated = {
SdkCall.execute execute@{
// Get the maximum distance until an alarm is reached.
val maxDistance = alarmService?.alarmDistance ?: 0.0
// Get the overlay items that are present and relevant.
val markerList = alarmService?.overlayItemAlarms
if (markerList == null || markerList.size == 0) return@execute
// Get the distance to the closest alarm marker.
val distance = markerList.getDistance(0)
if (distance <= maxDistance) {
// If you are close enough to the alarm item, notify the user.
Toast.makeText(
this@MainActivity,
"Speed camera in $distance m",
Toast.LENGTH_LONG
).show()
// Remove the alarm listener if you want to notify only once.
alarmService?.setAlarmListener(null)
}
}
}
)
Also instantiated a onOverlayItemAlarmsUpdated
alarm listener to get speed camera notifications from the navigation service, including the distance to the next speed camera.
@Suppress("SameParameterValue")
private fun setAlarmOverlay(overlay: ECommonOverlayId) {
SdkCall.execute {
alarmService = AlarmService.produce(alarmListener)
alarmService?.alarmDistance = 500.0 // meters
val availableOverlays = OverlayService().getAvailableOverlays(null)?.first
if (availableOverlays != null) {
for (item in availableOverlays) {
if (item.uid == overlay.value) {
alarmService?.overlays?.add(item.uid)
}
}
}
}
}
When the navigationListener
is instantiated above, it calls this function which sets the alarmDistance
to 500 meters in the AlarmService
.
That is how the alarmListener
instantiated above knows at what distance prior to the speed camera to display the notification it received.
private val routingProgressListener = ProgressListener.create(
onStarted = {
progressBar.visibility = View.VISIBLE
},
onCompleted = { _, _ ->
progressBar.visibility = View.GONE
},
postOnMain = true
)
Define a listener to indicate when the route computation is completed, so real or simulated navigation (simulated in this case) can start.
When navigation is started, mapView.followPosition()
causes the camera to follow the green arrow.
If the user pans (moves) the map to another location, the camera no longer follows the green arrow.

private fun enableGPSButton() {
// Set actions for entering/ exiting following position mode.
gemSurfaceView.mapView?.apply {
onExitFollowingPosition = {
followCursorButton.visibility = View.VISIBLE
}
onEnterFollowingPosition = {
followCursorButton.visibility = View.GONE
}
// Set on click action for the GPS button.
followCursorButton.setOnClickListener {
SdkCall.execute { followPosition() }
}
}
}
enableGPSButton()
causes a round purple button to appear in the lower right corner of the screen, whenever the simulation is active and the camera is not following the green arrow. If the user pushes this button, the followPosition()
function is called, and thus the camera starts to follow the green arrow once again.
private fun startSimulation() = SdkCall.execute {
val waypoints = arrayListOf(
Landmark("A", 53.056306247688326, 8.882596560149098),
Landmark("B", 53.06178963549359, 8.876610724727849)
)
navigationService.startSimulation(waypoints, navigationListener, routingProgressListener)
}
The starting, or departure point of the route is the first waypoint in a list of 2 or more Landmarks (2 in this case), each containing a name, latitude (in degrees) and longitude (in degrees). The destination point is the last waypoint in the list.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
progressBar = findViewById(R.id.progressBar)
gemSurfaceView = findViewById(R.id.gem_surface)
followCursorButton = findViewById(R.id.followCursor)
SdkSettings.onMapDataReady = onMapDataReady@{ isReady ->
if (!isReady) return@onMapDataReady
// Defines an action that should be done when
// the world map is ready (updated / loaded).
startSimulation()
}
SdkSettings.onApiTokenRejected = {
Toast.makeText(this@MainActivity, "TOKEN REJECTED",
Toast.LENGTH_SHORT).show()
}
if (!Util.isInternetConnected(this)) {
Toast.makeText(this, "You must be connected to internet!", Toast.LENGTH_LONG).show()
}
}
The MainActivity
overrides the onCreate()
function which checks that internet access is available, and then, when the map is instantiated and ready, starts the simulation: startSimulation()
.
Android Examples
Maps SDK for Android Examples can be downloaded or cloned with Git