-
-
Notifications
You must be signed in to change notification settings - Fork 73
Description
Hi Folks,
We develop the Navigator using MapLibre SDK which receives Direction API request from the our server instead of what the user clicks to build the route. We pass the Direction API response with the geometry as polyline6 and we have no problems if the route is 200-300 km. But if the route is 1000 and more km, there is a problem in the display of the route line, it can appear in half a minute or even in a couple of minutes. But the instruction banner and maneuvers on the map are displayed normally. All the problem is in the blue line of the route, which is very long processed. Perhaps someone has already encountered this and can help, what am I doing wrong? I will be glad to provide more information and code if needed.
There's a function I use to start a route:
private fun calculateRoute() {
binding.startRouteLayout.visibility = View.GONE
val userLocation = mapLibreMap.locationComponent.lastKnownLocation
if (userLocation == null) {
Toast.makeText(this, "User location is null; origin cannot be set.", Toast.LENGTH_LONG).show()
return
}
CoroutineScope(Dispatchers.Main).launch {
try {
val currentUuidToFetch = uuid
if (currentUuidToFetch == null) {
return@launch
}
val directionsResponse = withContext(Dispatchers.IO) {
fetchRouteFromServer(currentUuidToFetch)
}
directionsResponse?.let { routeResp ->
val resultRouteResponse = transformRouteResponse(routeResp)
this@NavigationUIActivity.route = resultRouteResponse.routes.firstOrNull()
if (this@NavigationUIActivity.route != null) {
navigationMapRoute?.removeRoute()
navigationMapRoute?.addRoutes(resultRouteResponse.routes)
binding.startRouteLayout.visibility = View.VISIBLE
if (!navigationAutomaticallyLaunched) {
startActiveNavigation()
navigationAutomaticallyLaunched = true
} else {
Timber.d("Navigation was already launched automatically or manually, skipping auto-launch.")
}
} else {
Timber.w("No routes found in response for UUID: $currentUuidToFetch")
}
} ?: run {
Timber.w("Failed to fetch route for UUID: $currentUuidToFetch, response is null")
}
} catch (e: Exception) {
Timber.e(e, "Failed to calculate route")
}
}
}And these two functions are responsible for transforming the route from my server and passing this route to NavigationLauncher:
private fun transformRouteResponse(routeResponse: DirectionsResponse): DirectionsResponse {
val originalRoutes: List<DirectionsRoute> = routeResponse.routes
val transformedRoutes: List<DirectionsRoute> = transformRoutes(originalRoutes)
return DirectionsResponse.Builder(
code = routeResponse.code,
routes = transformedRoutes
).apply {
withMessage(routeResponse.message)
withWaypoints(routeResponse.waypoints)
withUuid(routeResponse.uuid)
}.build()
}
private fun transformRoutes(originalRoutes: List<DirectionsRoute>): List<DirectionsRoute> {
val modifiedRoutes: MutableList<DirectionsRoute> = ArrayList()
for (originalRoute in originalRoutes) {
val routeOptionsBuilder: RouteOptions.Builder
if (originalRoute.routeOptions != null) {
routeOptionsBuilder = originalRoute.routeOptions!!.toBuilder()
} else {
val baseUrlForBuilder = getString(R.string.base_url)
val userForBuilder = "mapbox"
val profileForBuilder = NavigationRoute.PROFILE_DRIVING
val coordinatesForBuilder = mutableListOf<Point>()
originalRoute.legs.firstOrNull()?.steps?.firstOrNull()?.maneuver?.location?.let { locationFromManeuver ->
try {
val convertedPoint = Point.fromLngLat(locationFromManeuver.longitude, locationFromManeuver.latitude)
coordinatesForBuilder.add(convertedPoint)
Timber.d("Successfully converted and added start point: $convertedPoint")
} catch (e: NoSuchMethodException) {
Timber.e(e, "NoSuchMethodException: longitude/latitude not found on maneuver location. Type: ${locationFromManeuver.javaClass.name}")
} catch (e: Exception) {
Timber.e(e, "Error converting first point from maneuver location. Type: ${locationFromManeuver.javaClass.name}")
}
}
originalRoute.legs.lastOrNull()?.steps?.lastOrNull()?.maneuver?.location?.let { locationFromManeuver ->
try {
val convertedPoint = Point.fromLngLat(locationFromManeuver.longitude, locationFromManeuver.latitude)
coordinatesForBuilder.add(convertedPoint)
Timber.d("Successfully converted and added end point: $convertedPoint")
} catch (e: NoSuchMethodException) {
Timber.e(e, "NoSuchMethodException: longitude/latitude not found on maneuver location. Type: ${locationFromManeuver.javaClass.name}")
} catch (e: Exception) {
Timber.e(e, "Error converting last point from maneuver location. Type: ${locationFromManeuver.javaClass.name}")
}
}
if (coordinatesForBuilder.size < 2) {
Timber.e("Cannot create RouteOptions: not enough valid coordinates extracted/converted. Using fallback.")
val currentUserLocation = mapLibreMap.locationComponent.lastKnownLocation
val originPoint = currentUserLocation?.let { Point.fromLngLat(it.longitude, it.latitude) }
?: Point.fromLngLat(0.0, 0.0)
val destinationPoint = this@NavigationUIActivity.destination
?: Point.fromLngLat(37.98009032708625, 56.11309765065775)
coordinatesForBuilder.clear()
coordinatesForBuilder.add(originPoint)
coordinatesForBuilder.add(destinationPoint)
}
routeOptionsBuilder = RouteOptions.Builder(
baseUrl = baseUrlForBuilder,
user = userForBuilder,
profile = profileForBuilder,
coordinates = ArrayList(coordinatesForBuilder)
)
}
val finalRouteOptions = routeOptionsBuilder.apply {
withAccessToken(getString(R.string.mapbox_access_token))
withVoiceInstructions(true)
withBannerInstructions(true)
withRoundaboutExits(true)
withContinueStraight(true)
withVoiceUnits(UnitType.METRIC)
withSteps(true)
withAlternatives(false)
withAnnotations("congestion,distance")
withOverview("full")
withLanguage("ru")
}.build()
val routeWithOptions = originalRoute.toBuilder()
.withRouteOptions(finalRouteOptions)
.build()
modifiedRoutes.add(routeWithOptions)
}
return modifiedRoutes
}