fix: Custom navigation events

This commit is contained in:
Piotr Dec 2024-08-09 01:25:35 +02:00
parent 65cdeb17d0
commit ffbd7c46b8
Signed by: stawros
GPG key ID: F89F27AD8F881A91
5 changed files with 97 additions and 27 deletions

View file

@ -4,6 +4,7 @@ import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.view.View import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.mapbox.geojson.Point
import com.mapbox.maps.ImageHolder import com.mapbox.maps.ImageHolder
import com.mapbox.maps.plugin.LocationPuck2D import com.mapbox.maps.plugin.LocationPuck2D
import com.mapbox.maps.plugin.animation.camera import com.mapbox.maps.plugin.animation.camera
@ -48,6 +49,8 @@ class MapControl(
*/ */
val navigationLocationProvider = NavigationLocationProvider() val navigationLocationProvider = NavigationLocationProvider()
val navigationStatusControl = NavigationStatusControl()
val replay = ReplayResources(this) val replay = ReplayResources(this)
// Observers // Observers
@ -59,7 +62,6 @@ class MapControl(
private lateinit var routeProgressObserver: RouteProgressObserver private lateinit var routeProgressObserver: RouteProgressObserver
private lateinit var voiceInstructionsObserver: VoiceInstructionsObserver private lateinit var voiceInstructionsObserver: VoiceInstructionsObserver
private val searchControl = SearchControl(this, ui) private val searchControl = SearchControl(this, ui)
private val navigationStateListener = NavigationStateListener()
fun init() { fun init() {
viewportDataSource = MapboxNavigationViewportDataSource(ui.mapView.mapboxMap) viewportDataSource = MapboxNavigationViewportDataSource(ui.mapView.mapboxMap)
@ -105,6 +107,10 @@ class MapControl(
voiceInstructionsObserver = voiceControl.voiceInstructionsObserver voiceInstructionsObserver = voiceControl.voiceInstructionsObserver
} }
fun routeToPoint(point: Point) {
routeControl.findRoute(point)
}
fun initNavigation() { fun initNavigation() {
MapboxNavigationApp.setup( MapboxNavigationApp.setup(
NavigationOptions.Builder(context) NavigationOptions.Builder(context)
@ -135,7 +141,8 @@ class MapControl(
mapboxNavigation.registerLocationObserver(locationObserver) mapboxNavigation.registerLocationObserver(locationObserver)
mapboxNavigation.registerRouteProgressObserver(routeProgressObserver) mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
mapboxNavigation.registerVoiceInstructionsObserver(voiceInstructionsObserver) mapboxNavigation.registerVoiceInstructionsObserver(voiceInstructionsObserver)
mapboxNavigation.registerNavigationSessionStateObserver(navigationStateListener)
navigationStatusControl.registerObserver(searchControl)
replay.onAttached(mapboxNavigation) replay.onAttached(mapboxNavigation)
} }
@ -145,7 +152,8 @@ class MapControl(
mapboxNavigation.unregisterLocationObserver(locationObserver) mapboxNavigation.unregisterLocationObserver(locationObserver)
mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver) mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
mapboxNavigation.unregisterVoiceInstructionsObserver(voiceInstructionsObserver) mapboxNavigation.unregisterVoiceInstructionsObserver(voiceInstructionsObserver)
mapboxNavigation.unregisterNavigationSessionStateObserver(navigationStateListener)
navigationStatusControl.unregisterObserver(searchControl)
replay.onDetached(mapboxNavigation) replay.onDetached(mapboxNavigation)
} }

View file

@ -1,12 +0,0 @@
package eu.ztsh.garmin.mapbox
import com.mapbox.navigation.core.trip.session.NavigationSessionState
import com.mapbox.navigation.core.trip.session.NavigationSessionStateObserver
class NavigationStateListener: NavigationSessionStateObserver {
override fun onNavigationSessionStateChanged(navigationSession: NavigationSessionState) {
// TODO("Not yet implemented")
}
}

View file

@ -0,0 +1,49 @@
package eu.ztsh.garmin.mapbox
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import java.util.concurrent.CopyOnWriteArraySet
import java.util.concurrent.atomic.AtomicReference
class NavigationStatusControl {
private val stateObservers = CopyOnWriteArraySet<NavigationStatusObserver>()
private val current = AtomicReference(NavigationStatus.IDLE)
fun registerObserver(observer: NavigationStatusObserver) {
stateObservers.add(observer)
observer.onNavigationStatusChanged(current.get())
}
fun unregisterObserver(observer: NavigationStatusObserver) {
stateObservers.remove(observer)
}
fun sendEvent(status: NavigationStatus) {
current.set(status)
stateObservers.forEach {
it.onNavigationStatusChanged(status)
}
if (status == NavigationStatus.FINISHED || status == NavigationStatus.CANCELED) {
// TODO: lifecyclescope?
runBlocking {
delay(1000)
sendEvent(NavigationStatus.IDLE)
}
}
}
}
enum class NavigationStatus {
IDLE,
STARTED,
FINISHED,
CANCELED
}
fun interface NavigationStatusObserver {
fun onNavigationStatusChanged(navigationStatus: NavigationStatus)
}

View file

@ -3,10 +3,10 @@ package eu.ztsh.garmin.mapbox
import android.content.Context import android.content.Context
import android.view.View import android.view.View
import android.widget.Toast import android.widget.Toast
import androidx.lifecycle.lifecycleScope
import com.mapbox.api.directions.v5.models.Bearing import com.mapbox.api.directions.v5.models.Bearing
import com.mapbox.api.directions.v5.models.RouteOptions import com.mapbox.api.directions.v5.models.RouteOptions
import com.mapbox.geojson.Point import com.mapbox.geojson.Point
import com.mapbox.maps.plugin.gestures.gestures
import com.mapbox.navigation.base.TimeFormat import com.mapbox.navigation.base.TimeFormat
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
import com.mapbox.navigation.base.extensions.applyLanguageAndVoiceUnitOptions import com.mapbox.navigation.base.extensions.applyLanguageAndVoiceUnitOptions
@ -37,6 +37,10 @@ import com.mapbox.navigation.ui.maps.route.line.model.MapboxRouteLineApiOptions
import com.mapbox.navigation.ui.maps.route.line.model.MapboxRouteLineViewOptions import com.mapbox.navigation.ui.maps.route.line.model.MapboxRouteLineViewOptions
import eu.ztsh.garmin.Garmin import eu.ztsh.garmin.Garmin
import eu.ztsh.garmin.UI import eu.ztsh.garmin.UI
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
class RouteControl(private val mapControl: MapControl, ui: UI, private val context: Context) { class RouteControl(private val mapControl: MapControl, ui: UI, private val context: Context) {
@ -115,11 +119,6 @@ class RouteControl(private val mapControl: MapControl, ui: UI, private val conte
// Ensure that the route line related layers are present before the route arrow // Ensure that the route line related layers are present before the route arrow
routeLineView.initializeLayers(it) routeLineView.initializeLayers(it)
// add long click listener that search for a route to the clicked destination
// ui.mapView.gestures.addOnMapLongClickListener { point ->
// findRoute(point)
// true
// }
} }
// initialize view interactions // initialize view interactions
@ -219,7 +218,7 @@ class RouteControl(private val mapControl: MapControl, ui: UI, private val conte
} }
} }
private fun findRoute(destination: Point) { fun findRoute(destination: Point) {
val originLocation = mapControl.navigationLocationProvider.lastLocation ?: return val originLocation = mapControl.navigationLocationProvider.lastLocation ?: return
val originPoint = Point.fromLngLat(originLocation.longitude, originLocation.latitude) val originPoint = Point.fromLngLat(originLocation.longitude, originLocation.latitude)
@ -284,6 +283,15 @@ class RouteControl(private val mapControl: MapControl, ui: UI, private val conte
// start simulation // start simulation
mapControl.replay.startSimulation(routes.first().directionsRoute) mapControl.replay.startSimulation(routes.first().directionsRoute)
mapControl.context.apply {
lifecycleScope.launch {
async {
delay(5000)
mapControl.navigationCamera.requestNavigationCameraToFollowing()
}
}
}
} }
private fun clearRouteAndStopNavigation() { private fun clearRouteAndStopNavigation() {
@ -298,6 +306,9 @@ class RouteControl(private val mapControl: MapControl, ui: UI, private val conte
mapControl.ui.maneuverView.visibility = View.INVISIBLE mapControl.ui.maneuverView.visibility = View.INVISIBLE
mapControl.ui.routeOverview.visibility = View.INVISIBLE mapControl.ui.routeOverview.visibility = View.INVISIBLE
mapControl.ui.tripProgressCard.visibility = View.INVISIBLE mapControl.ui.tripProgressCard.visibility = View.INVISIBLE
// post custom event
mapControl.navigationStatusControl.sendEvent(NavigationStatus.CANCELED)
} }
fun cancel() { fun cancel() {

View file

@ -21,6 +21,7 @@ import com.mapbox.maps.plugin.annotation.annotations
import com.mapbox.maps.plugin.annotation.generated.CircleAnnotationOptions import com.mapbox.maps.plugin.annotation.generated.CircleAnnotationOptions
import com.mapbox.maps.plugin.annotation.generated.createCircleAnnotationManager import com.mapbox.maps.plugin.annotation.generated.createCircleAnnotationManager
import com.mapbox.maps.plugin.gestures.gestures import com.mapbox.maps.plugin.gestures.gestures
import com.mapbox.navigation.core.trip.session.NavigationSessionState
import com.mapbox.search.autocomplete.PlaceAutocomplete import com.mapbox.search.autocomplete.PlaceAutocomplete
import com.mapbox.search.autocomplete.PlaceAutocompleteOptions import com.mapbox.search.autocomplete.PlaceAutocompleteOptions
import com.mapbox.search.autocomplete.PlaceAutocompleteSuggestion import com.mapbox.search.autocomplete.PlaceAutocompleteSuggestion
@ -33,7 +34,7 @@ import eu.ztsh.garmin.R
import eu.ztsh.garmin.UI import eu.ztsh.garmin.UI
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class SearchControl(val mapControl: MapControl, val ui: UI) { class SearchControl(val mapControl: MapControl, val ui: UI): NavigationStatusObserver {
// Set your Access Token here if it's not already set in some other way // Set your Access Token here if it's not already set in some other way
// MapboxOptions.accessToken = "<my-access-token>" // MapboxOptions.accessToken = "<my-access-token>"
@ -86,13 +87,12 @@ class SearchControl(val mapControl: MapControl, val ui: UI) {
} }
addOnNavigateClickListener { searchPlace -> addOnNavigateClickListener { searchPlace ->
showToast(R.string.not_implemented_yet) mapControl.routeToPoint(searchPlace.coordinate)
// startActivity(geoIntent(searchPlace.coordinate)) mapControl.navigationStatusControl.sendEvent(NavigationStatus.STARTED)
} }
addOnShareClickListener { searchPlace -> addOnShareClickListener { _ ->
showToast(R.string.not_implemented_yet) showToast(R.string.not_implemented_yet)
// startActivity(shareIntent(searchPlace))
} }
} }
@ -182,6 +182,20 @@ class SearchControl(val mapControl: MapControl, val ui: UI) {
} }
} }
override fun onNavigationStatusChanged(navigationStatus: NavigationStatus) {
when (navigationStatus) {
NavigationStatus.IDLE -> {
ui.queryEditText.visibility = View.VISIBLE
}
NavigationStatus.STARTED -> {
mapControl.navigationCamera.requestNavigationCameraToOverview()
closePlaceCard()
ui.queryEditText.visibility = View.GONE
}
else -> {}
}
}
private fun showToast(@StringRes resId: Int): Unit = private fun showToast(@StringRes resId: Int): Unit =
Toast.makeText(mapControl.context, resId, Toast.LENGTH_LONG).show() Toast.makeText(mapControl.context, resId, Toast.LENGTH_LONG).show()