From 08b55d39ffa56953d8aa3b3354065375662c1d77 Mon Sep 17 00:00:00 2001 From: dzmitryfomchyn Date: Tue, 16 Jan 2024 12:28:48 +0100 Subject: [PATCH] Adasis example activity --- examples/src/main/AndroidManifest.xml | 6 + .../navigation/examples/MainActivity.kt | 6 + .../examples/core/AdasisActivity.kt | 319 ++++++++++++++++++ .../examples/core/MapboxNavigationActivity.kt | 11 - .../res/layout/layout_activity_adasis.xml | 31 ++ examples/src/main/res/values/strings.xml | 3 + 6 files changed, 365 insertions(+), 11 deletions(-) create mode 100644 examples/src/main/java/com/mapbox/navigation/examples/core/AdasisActivity.kt create mode 100644 examples/src/main/res/layout/layout_activity_adasis.xml diff --git a/examples/src/main/AndroidManifest.xml b/examples/src/main/AndroidManifest.xml index 859373f2e7f..0315b1cb48e 100644 --- a/examples/src/main/AndroidManifest.xml +++ b/examples/src/main/AndroidManifest.xml @@ -95,6 +95,12 @@ android:label="@string/title_multileg_route"> + + + diff --git a/examples/src/main/java/com/mapbox/navigation/examples/MainActivity.kt b/examples/src/main/java/com/mapbox/navigation/examples/MainActivity.kt index 303d89ab7f1..dcb54683038 100644 --- a/examples/src/main/java/com/mapbox/navigation/examples/MainActivity.kt +++ b/examples/src/main/java/com/mapbox/navigation/examples/MainActivity.kt @@ -13,6 +13,7 @@ import androidx.recyclerview.widget.LinearLayoutManager import com.mapbox.android.core.permissions.PermissionsListener import com.mapbox.common.LogConfiguration import com.mapbox.common.LoggingLevel +import com.mapbox.navigation.examples.core.AdasisActivity import com.mapbox.navigation.examples.core.IndependentRouteGenerationActivity import com.mapbox.navigation.examples.core.MapboxBuildingHighlightActivity import com.mapbox.navigation.examples.core.MapboxCustomStyleActivity @@ -143,6 +144,11 @@ class MainActivity : AppCompatActivity(), PermissionsListener { getString(R.string.description_draw_utility), RouteDrawingActivity::class.java ), + SampleItem( + getString(R.string.title_adasis), + getString(R.string.description_adasis), + AdasisActivity::class.java + ) ) } diff --git a/examples/src/main/java/com/mapbox/navigation/examples/core/AdasisActivity.kt b/examples/src/main/java/com/mapbox/navigation/examples/core/AdasisActivity.kt new file mode 100644 index 00000000000..bb572fc84a0 --- /dev/null +++ b/examples/src/main/java/com/mapbox/navigation/examples/core/AdasisActivity.kt @@ -0,0 +1,319 @@ +package com.mapbox.navigation.examples.core + +import android.annotation.SuppressLint +import android.location.Location +import android.os.Bundle +import android.util.Log +import android.view.View +import androidx.appcompat.app.AppCompatActivity +import com.mapbox.api.directions.v5.models.DirectionsRoute +import com.mapbox.api.directions.v5.models.RouteOptions +import com.mapbox.geojson.Point +import com.mapbox.maps.CameraOptions +import com.mapbox.maps.EdgeInsets +import com.mapbox.maps.MapboxMap +import com.mapbox.maps.Style +import com.mapbox.maps.plugin.animation.CameraAnimationsPlugin +import com.mapbox.maps.plugin.animation.MapAnimationOptions +import com.mapbox.maps.plugin.animation.camera +import com.mapbox.maps.plugin.gestures.gestures +import com.mapbox.maps.plugin.locationcomponent.LocationComponentPlugin +import com.mapbox.maps.plugin.locationcomponent.location +import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI +import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions +import com.mapbox.navigation.base.extensions.applyLanguageAndVoiceUnitOptions +import com.mapbox.navigation.base.options.NavigationOptions +import com.mapbox.navigation.base.route.NavigationRoute +import com.mapbox.navigation.base.route.NavigationRouterCallback +import com.mapbox.navigation.base.route.RouterFailure +import com.mapbox.navigation.base.route.RouterOrigin +import com.mapbox.navigation.core.MapboxNavigation +import com.mapbox.navigation.core.MapboxNavigationProvider +import com.mapbox.navigation.core.adasis.AdasisConfig +import com.mapbox.navigation.core.directions.session.RoutesObserver +import com.mapbox.navigation.core.replay.MapboxReplayer +import com.mapbox.navigation.core.replay.ReplayLocationEngine +import com.mapbox.navigation.core.replay.route.ReplayProgressObserver +import com.mapbox.navigation.core.replay.route.ReplayRouteMapper +import com.mapbox.navigation.core.trip.session.LocationMatcherResult +import com.mapbox.navigation.core.trip.session.LocationObserver +import com.mapbox.navigation.core.trip.session.RouteProgressObserver +import com.mapbox.navigation.examples.core.databinding.LayoutActivityAdasisBinding +import com.mapbox.navigation.examples.core.waypoints.WaypointsController +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.setNavigationRoutes +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.RouteLineResources +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class AdasisActivity : AppCompatActivity() { + + private lateinit var mapboxMap: MapboxMap + private lateinit var mapCamera: CameraAnimationsPlugin + private lateinit var mapboxNavigation: MapboxNavigation + private lateinit var binding: LayoutActivityAdasisBinding + private lateinit var locationComponent: LocationComponentPlugin + private var isNavigating = false + + private val mapboxReplayer = MapboxReplayer() + private val navigationLocationProvider = NavigationLocationProvider() + private val waypointsController = WaypointsController() + + private val routeLineResources: RouteLineResources by lazy { + RouteLineResources.Builder().build() + } + + private val options: MapboxRouteLineOptions by lazy { + MapboxRouteLineOptions.Builder(this) + .withRouteLineResources(routeLineResources) + .withRouteLineBelowLayerId("road-label") + .build() + } + + private val routeLineView by lazy { + MapboxRouteLineView(options) + } + + private val routeLineApi: MapboxRouteLineApi by lazy { + MapboxRouteLineApi(options) + } + + private val routeArrowApi: MapboxRouteArrowApi by lazy { + MapboxRouteArrowApi() + } + + private val routeArrowView: MapboxRouteArrowView by lazy { + MapboxRouteArrowView(RouteArrowOptions.Builder(this).build()) + } + + private val replayProgressObserver = ReplayProgressObserver(mapboxReplayer) + + private val routeProgressObserver = RouteProgressObserver { routeProgress -> + routeArrowApi.addUpcomingManeuverArrow(routeProgress).apply { + routeArrowView.renderManeuverUpdate(mapboxMap.getStyle()!!, this) + } + } + + private val locationObserver = object : LocationObserver { + override fun onNewRawLocation(rawLocation: Location) {} + override fun onNewLocationMatcherResult(locationMatcherResult: LocationMatcherResult) { + navigationLocationProvider.changePosition( + locationMatcherResult.enhancedLocation, + locationMatcherResult.keyPoints, + ) + if (isNavigating) { + updateCamera(locationMatcherResult.enhancedLocation) + } + } + } + + private val routesObserver = RoutesObserver { result -> + if (result.navigationRoutes.isNotEmpty()) { + CoroutineScope(Dispatchers.Main).launch { + routeLineApi.setNavigationRoutes(result.navigationRoutes).apply { + routeLineView.renderRouteDrawData(mapboxMap.getStyle()!!, this) + } + } + isNavigating = true + startSimulation(result.navigationRoutes[0].directionsRoute) + } + } + + private var adasisMessagesLog: String = "Received adasis messages:\n" + private var numberOfMessages = 1 + + private fun init() { + initNavigation() + initStyle() + } + + @SuppressLint("MissingPermission") + private fun initNavigation() { + mapboxNavigation = MapboxNavigationProvider.create( + NavigationOptions.Builder(this@AdasisActivity) + .accessToken(getMapboxAccessTokenFromResources()) + .locationEngine(ReplayLocationEngine(mapboxReplayer)) + .build() + ) + mapboxNavigation.registerLocationObserver(object : LocationObserver { + override fun onNewRawLocation(rawLocation: Location) { + updateCamera(rawLocation) + navigationLocationProvider.changePosition( + rawLocation, + ) + mapboxNavigation.unregisterLocationObserver(this) + } + + override fun onNewLocationMatcherResult( + locationMatcherResult: LocationMatcherResult, + ) { + // + } + }) + mapboxNavigation.startTripSession() + mapboxReplayer.pushRealLocation(this, 0.0) + mapboxReplayer.play() + } + + @SuppressLint("MissingPermission") + private fun initStyle() { + mapboxMap.loadStyleUri(Style.MAPBOX_STREETS) { style -> + routeLineView.initializeLayers(style) + binding.mapView.gestures.addOnMapLongClickListener { point -> + val currentLocation = navigationLocationProvider.lastLocation + if (currentLocation != null) { + waypointsController.add(point) + val origin = Point.fromLngLat( + currentLocation.longitude, + currentLocation.latitude + ) + findRoute(origin) + } + false + } + } + } + + @SuppressLint("DiscouragedApi") + private fun getMapboxAccessTokenFromResources(): String { + return getString( + resources.getIdentifier("mapbox_access_token", "string", packageName) + ) + } + + private fun getMapCamera(): CameraAnimationsPlugin { + return binding.mapView.camera + } + + @SuppressLint("MissingPermission") + private fun startSimulation(route: DirectionsRoute) { + mapboxReplayer.stop() + mapboxReplayer.clearEvents() + mapboxReplayer.pushRealLocation(this, 0.0) + val replayEvents = ReplayRouteMapper().mapDirectionsRouteGeometry(route) + mapboxReplayer.pushEvents(replayEvents) + mapboxReplayer.seekTo(replayEvents.first()) + mapboxReplayer.play() + } + + private fun updateCamera(location: Location) { + val mapAnimationOptionsBuilder = MapAnimationOptions.Builder() + mapAnimationOptionsBuilder.duration(1500L) + mapCamera.easeTo( + CameraOptions.Builder() + .center(Point.fromLngLat(location.longitude, location.latitude)) + .bearing(location.bearing.toDouble()) + .pitch(45.0) + .zoom(17.0) + .padding(EdgeInsets(1000.0, 0.0, 0.0, 0.0)) + .build(), + mapAnimationOptionsBuilder.build() + ) + } + + private fun findRoute(origin: Point) { + val coordinates = waypointsController.coordinates(origin) + val routeOptions = RouteOptions.builder() + .applyDefaultNavigationOptions() + .applyLanguageAndVoiceUnitOptions(this) + .coordinatesList(coordinates) + .layersList( + ArrayList(coordinates.size).apply { + add(mapboxNavigation.getZLevel()) + repeat(coordinates.size - 1) { add(null) } + }, + ) + .build() + + mapboxNavigation.requestRoutes( + routeOptions, + object : NavigationRouterCallback { + override fun onRoutesReady( + routes: List, + routerOrigin: RouterOrigin, + ) { + mapboxNavigation.setNavigationRoutes(routes) + } + + override fun onFailure(reasons: List, routeOptions: RouteOptions) { + // no impl + } + + override fun onCanceled(routeOptions: RouteOptions, routerOrigin: RouterOrigin) { + // no impl + } + } + ) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = LayoutActivityAdasisBinding.inflate(layoutInflater) + setContentView(binding.root) + + mapboxMap = binding.mapView.getMapboxMap() + binding.adasisMsgLog.text = adasisMessagesLog + + locationComponent = binding.mapView.location.apply { + setLocationProvider(navigationLocationProvider) + enabled = true + } + mapCamera = getMapCamera() + + init() + } + + @OptIn(ExperimentalPreviewMapboxNavigationAPI::class) + override fun onStart() { + super.onStart() + if (::mapboxNavigation.isInitialized) { + mapboxNavigation.registerRoutesObserver(routesObserver) + mapboxNavigation.registerLocationObserver(locationObserver) + mapboxNavigation.registerRouteProgressObserver(routeProgressObserver) + mapboxNavigation.registerRouteProgressObserver(replayProgressObserver) + + mapboxNavigation.setAdasisMessageCallback( + AdasisConfig.Builder().build() + ) { messageBuffer, context -> + this@AdasisActivity.runOnUiThread { + // TODO decode buffer and print data + adasisMessagesLog += "${numberOfMessages++}: ${messageBuffer.size} bytes\n" + binding.adasisMsgLog.text = adasisMessagesLog + binding.scrollContainer.fullScroll(View.FOCUS_DOWN) + + Log.d(TAG, "Adasis message: $messageBuffer, context: $context") + } + } + } + } + + @OptIn(ExperimentalPreviewMapboxNavigationAPI::class) + override fun onStop() { + super.onStop() + mapboxNavigation.unregisterRoutesObserver(routesObserver) + mapboxNavigation.unregisterLocationObserver(locationObserver) + mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver) + mapboxNavigation.unregisterRouteProgressObserver(replayProgressObserver) + mapboxNavigation.resetAdasisMessageCallback() + } + + override fun onDestroy() { + super.onDestroy() + routeLineApi.cancel() + routeLineView.cancel() + mapboxReplayer.finish() + mapboxNavigation.onDestroy() + } + + private companion object { + val TAG = AdasisActivity::class.simpleName + } +} 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 a80e58135a7..84ea81b9275 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,7 +5,6 @@ import android.content.res.Configuration import android.content.res.Resources import android.location.Location import android.os.Bundle -import android.util.Log import android.view.View.INVISIBLE import android.view.View.VISIBLE import android.widget.Toast @@ -22,7 +21,6 @@ import com.mapbox.maps.plugin.LocationPuck2D import com.mapbox.maps.plugin.animation.camera 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,7 +33,6 @@ import com.mapbox.navigation.base.route.RouterFailure import com.mapbox.navigation.base.route.RouterOrigin import com.mapbox.navigation.core.MapboxNavigation import com.mapbox.navigation.core.MapboxNavigationProvider -import com.mapbox.navigation.core.adasis.AdasisConfig import com.mapbox.navigation.core.directions.session.RoutesObserver import com.mapbox.navigation.core.formatter.MapboxDistanceFormatter import com.mapbox.navigation.core.trip.session.LocationMatcherResult @@ -434,7 +431,6 @@ class MapboxNavigationActivity : AppCompatActivity() { mapboxNavigation.startTripSession() } - @OptIn(ExperimentalPreviewMapboxNavigationAPI::class) override fun onStart() { super.onStart() mapboxNavigation.registerRoutesObserver(routesObserver) @@ -442,14 +438,8 @@ class MapboxNavigationActivity : AppCompatActivity() { mapboxNavigation.registerRouteProgressObserver(routeProgressObserver) mapboxNavigation.registerLocationObserver(locationObserver) mapboxNavigation.registerVoiceInstructionsObserver(voiceInstructionsObserver) - mapboxNavigation.setAdasisMessageCallback( - AdasisConfig.Builder().build() - ) { message, context -> - Log.d("AdasisTest.", "Adasis message: $message, context: $context") - } } - @OptIn(ExperimentalPreviewMapboxNavigationAPI::class) override fun onStop() { super.onStop() mapboxNavigation.unregisterRoutesObserver(routesObserver) @@ -457,7 +447,6 @@ class MapboxNavigationActivity : AppCompatActivity() { mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver) mapboxNavigation.unregisterLocationObserver(locationObserver) mapboxNavigation.unregisterVoiceInstructionsObserver(voiceInstructionsObserver) - mapboxNavigation.resetAdasisMessageCallback() } override fun onDestroy() { diff --git a/examples/src/main/res/layout/layout_activity_adasis.xml b/examples/src/main/res/layout/layout_activity_adasis.xml new file mode 100644 index 00000000000..3c1a3b3698f --- /dev/null +++ b/examples/src/main/res/layout/layout_activity_adasis.xml @@ -0,0 +1,31 @@ + + + + + + + + + + diff --git a/examples/src/main/res/values/strings.xml b/examples/src/main/res/values/strings.xml index 39135f2d447..79afad8bcd0 100644 --- a/examples/src/main/res/values/strings.xml +++ b/examples/src/main/res/values/strings.xml @@ -36,6 +36,9 @@ BuildingHighlight Example Demonstrates how to highlight and extrude buildings on arrival. + Adasis Example + Demonstrates to to access Adasis functionality. + Start Navigation Play history Select history