Route building on map in mobile app

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Route building on map in mobile app
Medium
~2-3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

Implementation of Route Building on a Map in a Mobile Application

Displaying a route on a map is not just drawing a line between two points. You need to get the real geometry of roads from a routing API, render Polyline with the desired style, show distance and time, handle multiple route variants, and let the user choose. The specific implementation depends on the SDK and route provider.

Provider Choice: Built-in Routing vs Directions API

Provider Platform Offline Accuracy in RF Price
Google Directions API iOS + Android No Good $5/1000 requests
Apple MKDirections iOS No Medium in RF Free
Yandex MapKit Router iOS + Android Yes (Full SDK) Excellent in RF Per tariff
Mapbox Directions API iOS + Android No Good Free tier
2GIS SDK Router iOS + Android Yes Good in RF Per tariff
OSRM (self-hosted) Any Depends Depends on data Free

For most Russian applications with price sensitivity — Yandex or 2GIS with offline mode.

Google Maps: Directions API + Polyline Drawing

Google Maps SDK does not contain built-in routing — you need to call the Directions REST API separately and draw the obtained geometry manually.

// Request to Directions API
suspend fun getDirections(
    origin: LatLng,
    destination: LatLng
): List<LatLng> {
    val url = buildString {
        append("https://maps.googleapis.com/maps/api/directions/json")
        append("?origin=${origin.latitude},${origin.longitude}")
        append("&destination=${destination.latitude},${destination.longitude}")
        append("&mode=driving")
        append("&language=en")
        append("&key=$MAPS_API_KEY")
    }

    val response = httpClient.get(url)
    val json = JSONObject(response.body<String>())
    val route = json.getJSONArray("routes").getJSONObject(0)
    val overviewPolyline = route.getJSONObject("overview_polyline").getString("points")

    return PolyUtil.decode(overviewPolyline) // from maps-utils
}

// Drawing
fun drawRoute(googleMap: GoogleMap, points: List<LatLng>) {
    googleMap.addPolyline(
        PolylineOptions()
            .addAll(points)
            .color(Color.parseColor("#4285F4"))
            .width(8f)
            .geodesic(true)
            .startCap(RoundCap())
            .endCap(RoundCap())
    )

    // Camera on entire route
    val boundsBuilder = LatLngBounds.builder()
    points.forEach { boundsBuilder.include(it) }
    googleMap.animateCamera(
        CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 100)
    )
}

PolyUtil.decode from maps-utils decodes Google Encoded Polyline. Without this utility, you would have to write a decoder manually — the algorithm is simple, but why.

Yandex MapKit: DrivingRouter

Yandex builds routes directly in the SDK without REST calls:

val drivingRouter = DirectionsFactory.getInstance()
    .createDrivingRouter(DrivingRouterType.COMBINED)

val routePoints = listOf(
    RequestPoint(Point(55.7558, 37.6173), RequestPointType.WAYPOINT, null, null),
    RequestPoint(Point(59.9343, 30.3351), RequestPointType.WAYPOINT, null, null)
)

val drivingSession = drivingRouter.requestRoutes(
    routePoints,
    DrivingOptions().apply {
        routesCount = 3  // request several variants
        avoidTolls = false
        avoidPoorConditions = true
    },
    VehicleOptions(),
    object : DrivingSession.DrivingRouteListener {
        override fun onDrivingRoutes(routes: List<DrivingRoute>) {
            routes.forEachIndexed { index, route ->
                val color = if (index == 0) Color.BLUE else Color.GRAY
                val polyline = mapObjectCollection.addPolyline(route.geometry).apply {
                    strokeColor = color
                    strokeWidth = if (index == 0) 6f else 3f
                    zIndex = if (index == 0) 1f else 0f
                }
                // Tap on alternative route
                polyline.addTapListener { _, _ ->
                    selectRoute(index)
                    true
                }
            }

            // Meta information of first route
            routes.firstOrNull()?.let { route ->
                val metadata = route.metadata.weight
                val distance = metadata.distance.text  // "350 km"
                val time = metadata.timeWithTraffic.text  // "4 h 20 min"
                showRouteInfo(distance, time)
            }
        }
        override fun onDrivingRoutesError(error: Error) {}
    }
)

Walking and Transit Routes

Instead of DrivingRouter — use PedestrianRouter or TransitRouter. Transit route returns a list of segments: walking sections, buses, metro — with times and stops.

iOS MapKit: MKDirections

func buildDrivingRoute(from: CLLocationCoordinate2D, to: CLLocationCoordinate2D) {
    let request = MKDirections.Request()
    request.source = MKMapItem(placemark: MKPlacemark(coordinate: from))
    request.destination = MKMapItem(placemark: MKPlacemark(coordinate: to))
    request.transportType = .automobile
    request.requestsAlternateRoutes = true

    MKDirections(request: request).calculate { [weak self] response, error in
        guard let routes = response?.routes, !routes.isEmpty else { return }

        // Draw all routes, first is primary
        routes.enumerated().forEach { index, route in
            let renderer = MKPolylineRenderer(polyline: route.polyline)
            renderer.strokeColor = index == 0 ? .systemBlue : .systemGray
            renderer.lineWidth = index == 0 ? 5 : 3
            self?.mapView.addOverlay(route.polyline, level: .aboveRoads)
        }

        // Zoom to route
        self?.mapView.setVisibleMapRect(
            routes[0].polyline.boundingMapRect,
            edgePadding: UIEdgeInsets(top: 60, left: 40, bottom: 80, right: 40),
            animated: true
        )
    }
}

Intermediate Points (Waypoints)

All providers support waypoints. In Google Directions API — parameter &waypoints=lat,lng|lat,lng. In Yandex MapKit — add RequestPoint with type VIAPOINT between start and finish. In MKDirections — via MKDirections.Request.waypoints (available since iOS 16).

Common Problems

Route doesn't rebuild when points change. Old Polyline not removed before adding new one. You need to store a reference to the current overlay and remove it: mapView.removeOverlay(currentRoute).

Encoding polyline not decoded. Google uses precision 1e5 (5 decimal places). Yandex — custom format. Don't use universal decoder for Yandex routes.

Timeline

2–3 days. One route type without waypoints — 1 day. Multiple transport modes, alternative routes, recalculation — 2–3 days. Cost is calculated individually.