Skip to main content

Avoid Geofence Area

Last updated: June 19, 2026 | 3 minutes read

This example computes a route that avoids a geofence area - a named geographic zone the route must not cross. The area is a 1 km circle near Timișu de Jos, drawn on the map as a translucent red polygon, and the route from Brașov to Predeal is forced to detour around it. Geofence areas are stored per user on the Magic Lane server, so the app first signs in with an external login, registers the area, renders it, and only then calculates the route referencing that area by name.

Route detouring around a geofence area

Logging in and registering the geofence area

Geofence areas are associated with a user account, so the app waits for the worldwide road map to be up to date and then performs an external login with Login.registerExternalLogin. When the login completes, the Geofence object is given a single GeofenceArea - a CircleGeographicArea centred near Timișu de Jos with a 1 km radius, tagged with the name "Area to avoid" - via addAreas. Registration is asynchronous and reports back through a ProgressListener.

MainActivity.ktView on Github
geofenceAreas = arrayListOf(
GeofenceArea(
CircleGeographicArea(Coordinates(45.5950875, 25.6359825), 1000),
getString(R.string.area_to_avoid),
),
)
val addError = geofence.addAreas(geofenceAreas, addAreasProgressListener)

Showing the area on the map

Once the areas are registered, the addAreasProgressListener renders each circular area as a polygon marker so the avoided zone is visible. A MarkerCollection of type Polygon is configured with a magenta outline and a semi-transparent red fill, a Marker is created at each area's centre point, and the collection is added to the map's marker preferences. Routing is started straight afterwards.

MainActivity.ktView on Github
val polygonSettings = MarkerCollectionRenderSettings(
polylineInnerColor = Rgba.magenta(),
polygonFillColor = Rgba(255, 0, 0, 128),
)
polygonSettings.polylineInnerSize = 1.0 // mm
val polygonCollection = MarkerCollection(EMarkerType.Polygon, "Polygon")

for (geofenceArea in geofenceAreas) {
if (geofenceArea.area is CircleGeographicArea) {
geofenceArea.area?.centerPoint?.let {
val marker = Marker(it, 1000)
polygonCollection.add(marker)
}
}
}

mapView.preferences?.markers?.add(polygonCollection, polygonSettings)

calculateRoute()

Calculating the route that avoids the area

The route is computed with a RoutingService between Brașov and Predeal. The geofence is applied through the routing preferences: avoidGeofenceAreas is set to the list of area names to avoid - here the single "Area to avoid" tag used when the area was registered. calculateRoute only reports whether the calculation could be started: any such error is shown right away in a dialog, while the actual result arrives later through the service's onCompleted callback.

MainActivity.ktView on Github
private fun calculateRoute() = SdkCall.execute {
val waypoints = arrayListOf(
Landmark("Brasov", 45.65094531, 25.60403406),
Landmark("Predeal", 45.5052, 25.5742),
)

routingService.preferences.avoidGeofenceAreas = arrayListOf(getString(R.string.area_to_avoid))

val error = routingService.calculateRoute(waypoints)
if (error != GemError.NoError) {
runOnAliveUi {
showDialog(
getString(
R.string.route_calculation_failed,
SdkCall.runSynced { GemError.getMessage(error, this) },
),
) {
finish()
exitProcess(0)
}
}
}
}

Presenting the route

The RoutingService is created with onStarted / onCompleted callbacks. onStarted shows a "calculating route" status message; onCompleted reports any error in a dialog, and on success presents the first returned route on the map with presentRoute, insetting the visible area so the whole route - and the geofence circle it skirts - stays clear of the toolbar and status panel.

MainActivity.ktView on Github
SdkCall.execute {
if (routes.isNotEmpty()) {
binding.gemSurface.mapView?.presentRoute(
routes[0],
edgeAreaInsets = getEdgeAreaInsets(),
)
}
}