Реализация построения маршрутов на карте мобильного приложения

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1735 услуг
Реализация построения маршрутов на карте мобильного приложения
Средний
~2-3 дня
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    495

Реализация построения маршрутов на карте мобильного приложения

Отображение маршрута на карте — это не просто нарисовать линию между двумя точками. Нужно получить реальные геометрию дорог от routing API, отрисовать Polyline с нужным стилем, показать дистанцию и время, обработать несколько вариантов маршрута и дать пользователю выбрать. Конкретная реализация зависит от SDK и провайдера маршрутов.

Выбор провайдера: встроенный routing vs Directions API

Провайдер Платформа Офлайн Точность в РФ Цена
Google Directions API iOS + Android Нет Хорошая $5/1000 запросов
Apple MKDirections iOS Нет Средняя в РФ Бесплатно
Яндекс МапKit Router iOS + Android Есть (Full SDK) Отличная в РФ По тарифу
Mapbox Directions API iOS + Android Нет Хорошая Есть бесплатный tier
2ГИС SDK Router iOS + Android Есть Хорошая в РФ По тарифу
OSRM (self-hosted) Любая Зависит Зависит от данных Бесплатно

Для большинства российских приложений с ценовой чувствительностью — Яндекс или 2ГИС с офлайн-режимом.

Google Maps: Directions API + отрисовка Polyline

Google Maps SDK не содержит встроенного routing — нужно вызвать Directions REST API отдельно и нарисовать полученную геометрию вручную.

// Запрос к 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=ru")
        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) // из maps-utils
}

// Отрисовка
fun drawRoute(googleMap: GoogleMap, points: List<LatLng>) {
    googleMap.addPolyline(
        PolylineOptions()
            .addAll(points)
            .color(Color.parseColor("#4285F4"))
            .width(8f)
            .geodesic(true)
            .startCap(RoundCap())
            .endCap(RoundCap())
    )

    // Камера на весь маршрут
    val boundsBuilder = LatLngBounds.builder()
    points.forEach { boundsBuilder.include(it) }
    googleMap.animateCamera(
        CameraUpdateFactory.newLatLngBounds(boundsBuilder.build(), 100)
    )
}

PolyUtil.decode из maps-utils раскодирует Google Encoded Polyline. Без этой утилиты придётся писать decoder вручную — алгоритм несложный, но зачем.

Яндекс MapKit: DrivingRouter

Яндекс строит маршруты прямо в SDK без REST-вызовов:

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  // запросить несколько вариантов
        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
                }
                // Клик по альтернативному маршруту
                polyline.addTapListener { _, _ ->
                    selectRoute(index)
                    true
                }
            }

            // Мета-информация первого маршрута
            routes.firstOrNull()?.let { route ->
                val metadata = route.metadata.weight
                val distance = metadata.distance.text  // "350 км"
                val time = metadata.timeWithTraffic.text  // "4 ч 20 мин"
                showRouteInfo(distance, time)
            }
        }
        override fun onDrivingRoutesError(error: Error) {}
    }
)

Пешеходный и транзитный маршруты

Вместо DrivingRouterPedestrianRouter или TransitRouter. Транзитный маршрут возвращает список сегментов: пешие участки, автобусы, метро — с временем и остановками.

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 }

        // Рисуем все маршруты, первый — основной
        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)
        }

        // Зум на маршрут
        self?.mapView.setVisibleMapRect(
            routes[0].polyline.boundingMapRect,
            edgePadding: UIEdgeInsets(top: 60, left: 40, bottom: 80, right: 40),
            animated: true
        )
    }
}

Промежуточные точки (Waypoints)

Все провайдеры поддерживают waypoints. В Google Directions API — параметр &waypoints=lat,lng|lat,lng. В Яндекс MapKit — добавить RequestPoint с типом VIAPOINT между стартом и финишем. В MKDirections — через MKDirections.Request.waypoints (появились в iOS 16).

Типичные проблемы

Маршрут не перестраивается при изменении точек. Старый Polyline не удалён перед добавлением нового. Нужно хранить ссылку на текущий overlay и удалять его: mapView.removeOverlay(currentRoute).

Encoding polyline не декодируется. Google использует точность 1e5 (5 знаков после запятой). Яндекс — собственный формат. Не используйте универсальный decoder для Яндекс-маршрутов.

Сроки

2–3 дня. Один тип маршрута без waypoints — 1 день. Несколько режимов транспорта, альтернативные маршруты, пересчёт — 2–3 дня. Стоимость рассчитывается индивидуально.