From 1c7d7fa69f2b077d9ab2db3cf63bcbc0fe6f7a8b Mon Sep 17 00:00:00 2001 From: VysotskiVadim Date: Wed, 2 Nov 2022 09:41:07 +0100 Subject: [PATCH 1/4] implemented route privew --- CHANGELOG.md | 1 + .../examples/core/MapboxNavigationActivity.kt | 89 ++++- .../res/layout/layout_activity_navigation.xml | 15 +- .../core/RoutesPreviewTest.kt | 139 +++++++ .../utils/coroutines/Adapters.kt | 17 + libnavigation-core/api/current.txt | 43 ++ .../navigation/core/MapboxNavigation.kt | 74 ++++ .../core/NavigationComponentProvider.kt | 12 + .../core/preview/NativeRoutesDataParser.kt | 18 + .../navigation/core/preview/RoutesPreview.kt | 74 ++++ .../core/preview/RoutesPreviewController.kt | 144 +++++++ .../core/preview/RoutesPreviewObserver.kt | 64 +++ .../preview/RoutesPreviewUpdateReasons.kt | 34 ++ .../RouteAlternativesController.kt | 2 +- .../core/preview/RouteDataParserStub.kt | 28 ++ .../preview/RoutePreviewControllerFactory.kt | 18 + .../preview/RoutesPreviewControllerTest.kt | 378 ++++++++++++++++++ 17 files changed, 1136 insertions(+), 14 deletions(-) create mode 100644 instrumentation-tests/src/androidTest/java/com/mapbox/navigation/instrumentation_tests/core/RoutesPreviewTest.kt create mode 100644 libnavigation-core/src/main/java/com/mapbox/navigation/core/preview/NativeRoutesDataParser.kt create mode 100644 libnavigation-core/src/main/java/com/mapbox/navigation/core/preview/RoutesPreview.kt create mode 100644 libnavigation-core/src/main/java/com/mapbox/navigation/core/preview/RoutesPreviewController.kt create mode 100644 libnavigation-core/src/main/java/com/mapbox/navigation/core/preview/RoutesPreviewObserver.kt create mode 100644 libnavigation-core/src/main/java/com/mapbox/navigation/core/preview/RoutesPreviewUpdateReasons.kt create mode 100644 libnavigation-core/src/test/java/com/mapbox/navigation/core/preview/RouteDataParserStub.kt create mode 100644 libnavigation-core/src/test/java/com/mapbox/navigation/core/preview/RoutePreviewControllerFactory.kt create mode 100644 libnavigation-core/src/test/java/com/mapbox/navigation/core/preview/RoutesPreviewControllerTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index e1931091c67..a45d263c6af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -82,6 +82,7 @@ This release depends on, and has been tested with, the following Mapbox dependen - Added `ViewBinderCustomization.infoPanelRoutePreviewButtonBinder` and `ViewBinderCustomization.infoPanelStartNavigationButtonBinder` that allows injection of custom Info Panel buttons for Route Preview and Start Navigation in `NavigationView`. [#6490](https://github.com/mapbox/mapbox-navigation-android/pull/6490) - Added `ViewBinderCustomization.actionCompassButtonBinder`, `ViewBinderCustomization.actionCameraModeButtonBinder`, `ViewBinderCustomization.actionToggleAudioButtonBinder` and `ViewBinderCustomization.actionRecenterButtonBinder` that allows injection of a custom Compass, Camera Mode, Toggle Voice Instructions and Camera Recenter Buttons in `NavigationView`. [#6490](https://github.com/mapbox/mapbox-navigation-android/pull/6490) - Introduced `ActionButtonsBinder` base `UIBinder` class, that allows use of a custom action buttons layout with default action buttons in `NavigationView`. [#6490](https://github.com/mapbox/mapbox-navigation-android/pull/6490) +- Added experimental routes preview state, see `MapboxNavigaton#setRoutesPreview`, `MapboxNavigaton#setRoutesPreviewPrimaryRoute`, `MapboxNavigaton#registerRoutesPreviewObserver`, `MapboxNavigaton#getRoutesPreview`. [#6495](https://github.com/mapbox/mapbox-navigation-android/pull/6495) #### Bug fixes and improvements - Improved precision of congestion visualization and independent leg styling transitions, especially for long routes. [#6476](https://github.com/mapbox/mapbox-navigation-android/pull/6476) - Fixed an issue with congestion visualization on the route line that occurred during route refreshes. [#6476](https://github.com/mapbox/mapbox-navigation-android/pull/6476) diff --git a/examples/src/main/java/com/mapbox/navigation/examples/core/MapboxNavigationActivity.kt b/examples/src/main/java/com/mapbox/navigation/examples/core/MapboxNavigationActivity.kt index 84ea81b9275..80cc3fd7fb1 100644 --- a/examples/src/main/java/com/mapbox/navigation/examples/core/MapboxNavigationActivity.kt +++ b/examples/src/main/java/com/mapbox/navigation/examples/core/MapboxNavigationActivity.kt @@ -5,6 +5,7 @@ import android.content.res.Configuration import android.content.res.Resources import android.location.Location import android.os.Bundle +import android.view.View import android.view.View.INVISIBLE import android.view.View.VISIBLE import android.widget.Toast @@ -19,8 +20,10 @@ import com.mapbox.maps.MapboxMap import com.mapbox.maps.Style.Companion.MAPBOX_STREETS import com.mapbox.maps.plugin.LocationPuck2D import com.mapbox.maps.plugin.animation.camera +import com.mapbox.maps.plugin.gestures.OnMapClickListener import com.mapbox.maps.plugin.gestures.gestures import com.mapbox.maps.plugin.locationcomponent.location +import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI import com.mapbox.navigation.base.TimeFormat import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions import com.mapbox.navigation.base.extensions.applyLanguageAndVoiceUnitOptions @@ -35,6 +38,7 @@ import com.mapbox.navigation.core.MapboxNavigation import com.mapbox.navigation.core.MapboxNavigationProvider import com.mapbox.navigation.core.directions.session.RoutesObserver import com.mapbox.navigation.core.formatter.MapboxDistanceFormatter +import com.mapbox.navigation.core.preview.RoutesPreviewObserver import com.mapbox.navigation.core.trip.session.LocationMatcherResult import com.mapbox.navigation.core.trip.session.LocationObserver import com.mapbox.navigation.core.trip.session.NavigationSessionStateObserver @@ -52,11 +56,10 @@ import com.mapbox.navigation.ui.maps.location.NavigationLocationProvider import com.mapbox.navigation.ui.maps.route.arrow.api.MapboxRouteArrowApi import com.mapbox.navigation.ui.maps.route.arrow.api.MapboxRouteArrowView import com.mapbox.navigation.ui.maps.route.arrow.model.RouteArrowOptions -import com.mapbox.navigation.ui.maps.route.line.MapboxRouteLineApiExtensions.setRoutes +import com.mapbox.navigation.ui.maps.route.line.MapboxRouteLineApiExtensions.findClosestRoute import com.mapbox.navigation.ui.maps.route.line.api.MapboxRouteLineApi import com.mapbox.navigation.ui.maps.route.line.api.MapboxRouteLineView import com.mapbox.navigation.ui.maps.route.line.model.MapboxRouteLineOptions -import com.mapbox.navigation.ui.maps.route.line.model.RouteLine import com.mapbox.navigation.ui.tripprogress.api.MapboxTripProgressApi import com.mapbox.navigation.ui.tripprogress.model.DistanceRemainingFormatter import com.mapbox.navigation.ui.tripprogress.model.EstimatedTimeToArrivalFormatter @@ -75,6 +78,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import java.util.Locale +@OptIn(ExperimentalPreviewMapboxNavigationAPI::class) class MapboxNavigationActivity : AppCompatActivity() { /* ----- Layout binding reference ----- */ @@ -89,6 +93,8 @@ class MapboxNavigationActivity : AppCompatActivity() { // location puck integration private val navigationLocationProvider = NavigationLocationProvider() + private val waypoints = mutableListOf() + // camera private lateinit var navigationCamera: NavigationCamera private lateinit var viewportDataSource: MapboxNavigationViewportDataSource @@ -229,18 +235,17 @@ class MapboxNavigationActivity : AppCompatActivity() { } private val routesObserver = RoutesObserver { result -> - if (result.routes.isNotEmpty()) { + if (result.navigationRoutes.isNotEmpty()) { // generate route geometries asynchronously and render them - CoroutineScope(Dispatchers.Main).launch { - val result = routeLineAPI.setRoutes( - listOf(RouteLine(result.routes.first(), null)) - ) + routeLineAPI.setNavigationRoutes( + result.navigationRoutes, + mapboxNavigation.getAlternativeMetadataFor(result.navigationRoutes) + ) { val style = mapboxMap.getStyle() if (style != null) { - routeLineView.renderRouteDrawData(style, result) + routeLineView.renderRouteDrawData(style, it) } } - // update the camera position to account for the new route viewportDataSource.onRouteChanged(result.routes.first()) viewportDataSource.evaluate() @@ -263,11 +268,52 @@ class MapboxNavigationActivity : AppCompatActivity() { } } + private val routesPreviewObserver = RoutesPreviewObserver { update -> + val routePreview = update.routesPreview + if (routePreview != null) { + routeLineAPI.setNavigationRoutes( + routePreview.routesList, + routePreview.alternativesMetadata + ) { + val style = mapboxMap.getStyle() + if (style != null) { + routeLineView.renderRouteDrawData(style, it) + } + } + // update the camera position to account for the new route + viewportDataSource.onRouteChanged(routePreview.primaryRoute) + viewportDataSource.evaluate() + + binding.mapView.gestures.removeOnMapClickListener(previewMapClickListener) + binding.mapView.gestures.addOnMapClickListener(previewMapClickListener) + } else { + binding.mapView.gestures.removeOnMapClickListener(previewMapClickListener) + } + } + private val navigationSessionStateObserver = NavigationSessionStateObserver { logD("NavigationSessionState=$it", LOG_CATEGORY) logD("sessionId=${mapboxNavigation.getNavigationSessionState().sessionId}", LOG_CATEGORY) } + private val routeClickPadding = com.mapbox.android.gestures.Utils.dpToPx(30f) + + private val previewMapClickListener = OnMapClickListener { + CoroutineScope(Dispatchers.Main).launch { + val result = routeLineAPI.findClosestRoute( + it, + binding.mapView.getMapboxMap(), + routeClickPadding + ) + + val routeFound = result.value?.navigationRoute + if (routeFound != null && routeFound != routeLineAPI.getPrimaryNavigationRoute()) { + mapboxNavigation.changeRoutesPreviewPrimaryRoute(routeFound) + } + } + false + } + @SuppressLint("MissingPermission") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -438,6 +484,7 @@ class MapboxNavigationActivity : AppCompatActivity() { mapboxNavigation.registerRouteProgressObserver(routeProgressObserver) mapboxNavigation.registerLocationObserver(locationObserver) mapboxNavigation.registerVoiceInstructionsObserver(voiceInstructionsObserver) + mapboxNavigation.registerRoutesPreviewObserver(routesPreviewObserver) } override fun onStop() { @@ -447,6 +494,7 @@ class MapboxNavigationActivity : AppCompatActivity() { mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver) mapboxNavigation.unregisterLocationObserver(locationObserver) mapboxNavigation.unregisterVoiceInstructionsObserver(voiceInstructionsObserver) + mapboxNavigation.unregisterRoutesPreviewObserver(routesPreviewObserver) } override fun onDestroy() { @@ -464,19 +512,23 @@ class MapboxNavigationActivity : AppCompatActivity() { Point.fromLngLat(it.longitude, it.latitude) } ?: return + waypoints.add(destination) + val coordinates = listOf(origin) + waypoints + val layersList = listOf(mapboxNavigation.getZLevel()) + waypoints.map { null } mapboxNavigation.requestRoutes( RouteOptions.builder() .applyDefaultNavigationOptions() .applyLanguageAndVoiceUnitOptions(this) - .coordinatesList(listOf(origin, destination)) - .layersList(listOf(mapboxNavigation.getZLevel(), null)) + .alternatives(true) + .coordinatesList(coordinates) + .layersList(layersList) .build(), object : NavigationRouterCallback { override fun onRoutesReady( routes: List, routerOrigin: RouterOrigin ) { - setRouteAndStartNavigation(routes) + setRoutesPreview(routes) } override fun onFailure( @@ -493,6 +545,19 @@ class MapboxNavigationActivity : AppCompatActivity() { ) } + private fun setRoutesPreview(routes: List) { + binding.navigateButton.apply { + visibility = View.VISIBLE + setOnClickListener { + visibility = View.GONE + setRouteAndStartNavigation(mapboxNavigation.getRoutesPreview()!!.routesList) + mapboxNavigation.setRoutesPreview(emptyList()) + waypoints.clear() + } + } + mapboxNavigation.setRoutesPreview(routes) + } + private fun setRouteAndStartNavigation(route: List) { // set route mapboxNavigation.setNavigationRoutes(route) diff --git a/examples/src/main/res/layout/layout_activity_navigation.xml b/examples/src/main/res/layout/layout_activity_navigation.xml index 1a6f38c5d9e..85d34baa5bf 100644 --- a/examples/src/main/res/layout/layout_activity_navigation.xml +++ b/examples/src/main/res/layout/layout_activity_navigation.xml @@ -2,7 +2,9 @@ + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools" + > +