Ведение

Guidance - содержит информацию о текущей сессии ведения, позволяет подписаться на различные события во время ведения. Для его получения используйте метод Navigation.getGuidance.

Отслеживание локации

По умолчанию, Navigation создается в режиме suspended, в котором локация не отслеживается и ведение не работает. Для включения отслеживания текущей локации устройства, чтобы местоположение пользователя оставалось актуальным, используется режим resumed.

Для управления режимом слежения за локацией используются методы Navigation.resume и Navigation.suspend.

Совет

Хорошей практикой является переключение Navigation в режим suspended при сворачивании приложение с картой, и переключение в resumed при повторном открытии приложения.

Не рекомендуется переводить Navigation в режим suspended если вы реализуете сценарий фонового ведения.

Старт/стоп ведения

Начать ведение по маршруту можно с помощью метода Navigation.startGuidance. В качестве единственного аргумента он принимает маршрут, по которому начнется ведение.

Для окончание ведения существует симметричный метод Navigation.stopGuidance.

Примечание

Число возможных активных сессий ведения ограничено. В любой возможный момент времени можно иметь не больше одной запущенной сессии ведения.

Данные во время ведении

Рассмотрим основные данные, доступ к которым предоставляет Guidance во время ведения.

  • Текущий маршрут - Guidance.getCurrentRoute содержит маршрут, по которому в текущий момент активно ведение, либо значение null если ведения нет. В ходе ведения текущий маршрут может быть изменен, если, например, пользователь съехал с маршрута или был выбран другой альтернативный маршрут.

  • Локация пользователя - Guidance.getLocation содержит текущую локацию пользователя. Она состоит из координат, определяющих местоположение, текущего направления, точности определения локации, скорости ведения и т.д.

  • Превышение скорости - Guidance.getSpeedLimit и Guidance.getSpeedLimitStatus предоставляют информацию о максимально разрешенной скорости на данном участке маршрута. Guidance.getSpeedLimitsPolicy содержит информацию о скоростных ограничений для данного региона в различных местностях (в городе, загородом и на шоссе).

Полный API приведен в документации Guidance.

Windshield

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

Для обращения к объекту Windshield используется метод Guidance.getWindshield.

Состояние сущности Windshield определяется следующими данным:

  • Маневры - с помощью Guidance.getManoeuvres можно получить список предстоящих маневров на маршруте. Каждый маневр описывается позицией на маршруте, его местоположением и объектом Annotation, который содержит информацию о его типе.

  • Дорожная разметка - Guidance.getLaneSigns возвращает список, где каждый элемент содержит информацию в какой полосе дороги пользователь должен находиться, он характеризуется позицией на маршруте, и объектом LaneSign, который определяет вид разметки на данном участке дороги. Объект LaneSign содержит список Lane с информацией о каждой конкретной полосе дороги, ее направлении, типе и вариантах маневров.

  • Дорожные события - при помощи Guidance.getRoadEvents можно получить список предстоящих дорожных событий на маршруте вместе с информацией о скоростных ограничениях.

  • Указатели - метод Guidance.getDirectionSigns возвращает список предстоящих указателей на дороге. Например, указатель того, что следующий участок маршрута будет проходить через туннель или через скоростное шоссе.

С помощью WindshieldListener можно подписаться на события изменения состояния Windshield.

С примером использования Windshield для реализации UI-компонента, который отображает информацию о следующем маневре и полосной разметке, можно ознакомиться в демо-приложении.

События

В ходе ведения приложения состояние ведения постоянно изменяется. Для подписки на события ведения используется интерфейс GuidanceListener.

val guidanceListener = object : GuidanceListener {
    override fun onLocationChanged() = Unit
    override fun onCurrentRouteChanged(reason: RouteChangeReason) = Unit
    override fun onRouteLost() = Unit
    override fun onReturnedToRoute() = Unit
    override fun onRouteFinished() = Unit
    override fun onWayPointReached() = Unit
    override fun onStandingStatusChanged() = Unit
    override fun onRoadNameChanged() = Unit
    override fun onSpeedLimitUpdated() = Unit
    override fun onSpeedLimitStatusUpdated() = Unit
    override fun onAlternativesChanged() = Unit
    override fun onFastestAlternativeChanged() = Unit
}
guidance.addListener(guidanceListener)

GuidanceListener предоставляет возможность подписаться на события навигации (съезда с маршрута, возвращение к маршруту, достижение промежуточных и конечных точек маршрута) и изменения состояния ведения (текущей локации пользователя, маршрута, названия улицы, информации о лимитах скорости, списка альтернатив и т.д).

Альтернативы во время ведения

Альтернативные маршруты, которые доступны во время ведения, называются локальными альтернативами. Они имеют свойство автоматически перестраиваться. Для подписки на это событие используется метод GuidanceListener.onAlternativesChanged.

Для смены текущего маршрута на альтернативный используется метод Guidance.switchToRoute.

Более быстрые альтернативы

Сессия ведения по маршруту может быть очень продолжительной, иногда достигать нескольких часов. В таких случаях маршрут, который был построен на момент начала ведения, через некоторое время может устареть и стать не таким оптимальным. Эта проблема особенно актуальна при ведении в городе, где дорожная ситуация на дороге способна меняться достаточно часто. NaviKit SDK решает данную проблему и предоставляет возможность получить более быстрый альтернативный маршрут.

Метод Guidance.getFastestAlternative возвращает информацию о более быстрой альтернативе во время ведения, если она существует. Начните ведение по такому маршруту, чтобы изменить текущий маршрут на более оптимальный.

При помощи метода-обработчика GuidanceListener.onFastestAlternativeChanged можно подписаться на оповещения об изменении более быстрого маршрута.

Аннотации

Для настройки голосовых подсказок на маршруте (голосовых аннотаций), используется класс Annotator.

Для включения и выключения аннотаций используются методы Annotator.mute и Annotator.unmute.

Чтобы аннотатор начал свою работу необходимо добавить в него делегат - объект с типом Speaker, который нужно реализовать самостоятельно.

Примечание

NaviKit SDK не предоставляет свою реализацию Speaker.

С примером реализации Speaker с помощью Android TextToSpeech можно ознакомиться в демо-приложении.

Язык аннотаций можно изменять при помощи метода Navigation.setAnnotationLanguage.

Аннотации делятся на несколько видов, связанные с дорожными событиями AnnotatedRoadEvents и с предупреждениями на маршруте AnnotatedEvents. При помощи методов Annotator.setAnnotatedRoadEvents и Annotator.setAnnotatedEvents можно изменять активность отдельных аннотаций.

Существует возможность подписаться на события класса Annotator с помощью интерфейса AnnotatorListener. Он оповещает о действиях аннотатора - какой тип события был воспроизведен.

Восстановление состояния

Существует возможность восстановления состояния ведения при помощи механизма сериализации/десериализации Navigation.

  1. Сначала сериализуйте Navigation, используя метод NavigationSerialization.serialize.

    val serializedNavigation = NavigationSerialization().serialize(navigation)
    
  2. Теперь в serializedNavigation хранится слепок навигации. Его можно куда-нибудь сохранить, например на диск, а позже восстановить используя десериализацию.

  3. С помощью NavigationSerialization.deserialize создайте новый инстанс навигации.

    val navigation = NavigationSerialization().deserialize(serializedNavigation)
    

Таким образом, перед закрытием приложения можно сохранить Navigation на диск, и затем при следующем открытии восстановить его. Так как состояние ведения содержится в Guidance, а ведение является частью Navigation, оно тоже восстановится и последняя сессия ведения продолжится.

С примером реализации логики восстановления состояния ведения можно ознакомиться в нашем демо-приложении.

Симуляция ведения

В ходе разработки и тестирования навигационных приложений часто требуется проверить как работает сценарий ведения по маршруту. Для этого можно использовать сторонние средства симуляции локации пользователя или воспользоваться готовым API симуляции из NaviKit SDK.

Cуществует возможность включения симуляции движения по маршруту или произвольной траектории, для этого используется LocationSimulator класс.

Пример реализации менеджера для симуляции ведения по маршруту:

class SimulationManager {

    private var locationSimulator: LocationSimulator? = null

    private val locationSimulatorListener: LocationSimulatorListener {
        resetSimulation()
    }

    fun startSimulation(route: DrivingRoute) {
        locationSimulator = MapKitFactory.getInstance().createLocationSimulator(route.geometry)
        locationSimulator?.apply {
            subscribeForSimulatorEvents(locationSimulatorListener)
            speed = 20.0
            MapKitFactory.getInstance().setLocationManager(this)
            startSimulation(SimulationAccuracy.COARSE)
        }
    }

    fun resetSimulation() {
        locationSimulator?.unsubscribeFromSimulatorEvents()
        locationSimulator = null
        MapKitFactory.getInstance().resetLocationManagerToDefault()
    }

    fun setSpeed(value: Double) {
        locationSimulator?.speed = value
    }
}

Метод startSimulation принимает маршрут, по которому должна начаться симуляция ведения. Затем при помощи MapKit.createLocationSimulator создается новый экземпляр LocationSimulator, который нужно сконфигурировать:

  1. подписаться на событие завершения симуляции при помощи LocationSimulatorListener;
  2. выставить значение скорости движения во время ведения;
  3. заменить реализацию LocationManager на только что созданный locationSimulator;
  4. начать симуляцию.

В resetSimulation происходит сброс симуляции. При помощи MapKit.resetLocationManagerToDefault менеджер симуляции локации меняется на вариант по умолчанию, который считывает настоящую позицию пользователя.

Более подробно с примером реализации симуляции по маршруту можно ознакомиться в демо-приложении.

Фоновое ведение

Фоновым ведением называется такая сессия ведения, которая способна продолжаться после скрытия Activity приложения и даже после её уничтожения.

После того, как Activity приложения теряет focus, через некоторое время она может быть уничтожена Android-системой для освобождения ресурсов, после чего приложение может быть завершено в любой момент. Для обеспечения работы Android-приложения даже после смерти Activity, следует использовать Foreground service - один из базовых компонентов Android-приложения.

Для реализации фонового ведения нужно во время ведения запускать Foreground service, который будет отображать нотификацию. После закрытия Activity, Navigation должен оставаться в режиме resumed. В этом случае приложение будет защищено от уничтожения со стороны Android-системы и ведение с голосовыми подсказками будет работать в фоновом режиме.

Примечание

NaviKit SDK не предоставляет сервис для фонового ведения. Для реализации сценария фонового ведение вам потребуется реализовать свой собственный Foreground service с нотификацией.

С примером реализации сервиса фонового ведения можно ознакомиться в демо-приложении.