Skip to main content

GPX Import

Last updated: June 19, 2026 | 3 minutes read

This example imports a GPX file bundled with the app, displays its recorded track on the map as a red path, and then computes a bike route that follows that track. The GPX data is parsed into a Path with Path.produceWithGpx, drawn on the map with presentPath, and handed to the routing service, which snaps a route onto the road network. The computed route is rendered with its distance and travel-time bubble.

Imported GPX track with the computed route and its distance and time
The red GPX track overlaid on the blue computed route

Waiting for the road map before routing

The route can only be calculated once the worldwide road map data is available, so the example waits for the onWorldwideRoadMapSupportStatus callback to report UpToDate before importing the GPX file and computing the route. The listener is cleared as soon as it fires so the route is calculated only once.

MainActivity.ktView on Github
// Wait for the worldwide road map to be ready before calculating the route from GPX.
SdkSettings.onWorldwideRoadMapSupportStatus = { status ->
if (status == EOffboardListenerStatus.UpToDate) {
SdkSettings.onWorldwideRoadMapSupportStatus = {}
calculateRouteFromGPX()
}
}

Importing the GPX file and displaying the path

The GPX file is opened from the app assets and parsed into a Path with Path.produceWithGpx. The resulting track is drawn on the map as a red line with presentPath, and a bike route is requested along it with calculateRoute. calculateRoute returns immediately with a code indicating whether the route calculation was successfully started. If GemError.isError reports an error, an error dialog is shown. The computed route itself is delivered later, asynchronously, through the routing service's onCompleted callback.

MainActivity.ktView on Github
private fun calculateRouteFromGPX() = SdkCall.execute {
val gpxAssetsFilename = "gpx/test_route.gpx"

// Opens GPX input stream.
val input = applicationContext.resources.assets.open(gpxAssetsFilename)

// Produce a Path based on the input stream data
val track = Path.produceWithGpx(input) ?: return@execute

val mapView = binding.gemSurfaceView.mapView ?: return@execute

// Set the line color to red and display the path on the map.
val lineColor = Rgba.red()
mapView.presentPath(track, lineColor, lineColor, 0.0, 0.6, false)

// Set the transport mode to bike and calculate the route.
val error = routingService.calculateRoute(track, ERouteTransportMode.Bicycle)
if (GemError.isError(error)) {
val message = GemError.getMessage(error, this)
runOnAliveUi { showDialog(getString(R.string.routing_error, message)) }
}
}

Presenting the computed route

When the routing service finishes, the first computed route is shown on the map with presentRoute, including a bubble with the route name, distance, and travel time. If routing fails, the errorCode is resolved to a human-readable message with GemError.getMessage and surfaced to the user in an error dialog instead.

MainActivity.ktView on Github
onCompleted = { routes, errorCode, _ ->
binding.progressBar.visibility = View.GONE

when (errorCode) {
GemError.NoError -> {
if (!routes.isEmpty()) {
val route = routes[0]
SdkCall.execute {
binding.gemSurfaceView.mapView?.presentRoute(
route,
displayBubble = true,
displayRouteName = true,
displayTrafficIcon = false,
displayFerryIcon = false,
displayTollIcon = false,
edgeAreaInsets = getInsetsRect(),
)
}
}
}
else -> {
val message = SdkCall.runSynced { GemError.getMessage(errorCode, this) }
runOnAliveUi { showDialog(getString(R.string.routing_error, message)) }
}
}
},