fix: Custom navigation events
This commit is contained in:
parent
65cdeb17d0
commit
ffbd7c46b8
5 changed files with 97 additions and 27 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
49
app/src/main/java/eu/ztsh/garmin/mapbox/NavigationStatus.kt
Normal file
49
app/src/main/java/eu/ztsh/garmin/mapbox/NavigationStatus.kt
Normal 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)
|
||||||
|
|
||||||
|
}
|
|
@ -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() {
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue