feat!: Application outline
This commit is contained in:
parent
80dfa6ab4e
commit
01fbf32042
9 changed files with 1440 additions and 190 deletions
|
@ -1,102 +1,153 @@
|
|||
package eu.ztsh.garmin.mapbox
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.content.res.Resources
|
||||
import android.util.Log
|
||||
import com.mapbox.api.directions.v5.models.RouteOptions
|
||||
import com.mapbox.maps.EdgeInsets
|
||||
import com.mapbox.maps.MapView
|
||||
import com.mapbox.maps.Style
|
||||
import com.mapbox.maps.plugin.gestures.gestures
|
||||
import android.view.View
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.mapbox.maps.ImageHolder
|
||||
import com.mapbox.maps.plugin.LocationPuck2D
|
||||
import com.mapbox.maps.plugin.animation.camera
|
||||
import com.mapbox.maps.plugin.locationcomponent.location
|
||||
import com.mapbox.maps.plugin.viewport.data.FollowPuckViewportStateOptions
|
||||
import com.mapbox.maps.plugin.viewport.state.FollowPuckViewportState
|
||||
import com.mapbox.maps.plugin.viewport.viewport
|
||||
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
|
||||
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.base.options.NavigationOptions
|
||||
import com.mapbox.navigation.core.MapboxNavigation
|
||||
import com.mapbox.navigation.core.directions.session.RoutesObserver
|
||||
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
|
||||
import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
|
||||
import com.mapbox.navigation.core.trip.session.LocationObserver
|
||||
import com.mapbox.navigation.core.trip.session.RouteProgressObserver
|
||||
import com.mapbox.navigation.core.trip.session.VoiceInstructionsObserver
|
||||
import com.mapbox.navigation.ui.maps.camera.NavigationCamera
|
||||
import com.mapbox.navigation.ui.maps.camera.data.MapboxNavigationViewportDataSource
|
||||
import com.mapbox.navigation.ui.maps.camera.lifecycle.NavigationBasicGesturesHandler
|
||||
import com.mapbox.navigation.ui.maps.camera.state.NavigationCameraState
|
||||
import com.mapbox.navigation.ui.maps.location.NavigationLocationProvider
|
||||
import com.mapbox.navigation.utils.internal.toPoint
|
||||
import eu.ztsh.garmin.MainActivity
|
||||
import eu.ztsh.garmin.UI
|
||||
import eu.ztsh.garmin.mock.ReplayResources
|
||||
|
||||
class MapControl(val mapView: MapView, private val resources: Resources) {
|
||||
class MapControl(
|
||||
val context: AppCompatActivity,
|
||||
val ui: UI,
|
||||
private val resources: Resources
|
||||
) : MapboxNavigationObserver {
|
||||
|
||||
/**
|
||||
* Used to execute camera transitions based on the data generated by the [viewportDataSource].
|
||||
* This includes transitions from route overview to route following and continuously updating the camera as the location changes.
|
||||
*/
|
||||
lateinit var navigationCamera: NavigationCamera
|
||||
|
||||
/**
|
||||
* Produces the camera frames based on the location and routing data for the [navigationCamera] to execute.
|
||||
*/
|
||||
lateinit var viewportDataSource: MapboxNavigationViewportDataSource
|
||||
|
||||
/**
|
||||
* [NavigationLocationProvider] is a utility class that helps to provide location updates generated by the Navigation SDK
|
||||
* to the Maps SDK in order to update the user location indicator on the map.
|
||||
*/
|
||||
val navigationLocationProvider = NavigationLocationProvider()
|
||||
|
||||
val routesRequestCallback = object : NavigationRouterCallback {
|
||||
override fun onRoutesReady(routes: List<NavigationRoute>, @RouterOrigin routerOrigin: String) {
|
||||
MapboxNavigationApp.current()?.setNavigationRoutes(routes)
|
||||
}
|
||||
|
||||
override fun onFailure(reasons: List<RouterFailure>, routeOptions: RouteOptions) {
|
||||
Log.e(TAG, "onFailure: ")
|
||||
}
|
||||
|
||||
override fun onCanceled(routeOptions: RouteOptions, @RouterOrigin routerOrigin: String) {
|
||||
Log.w(TAG, "onCanceled: ")
|
||||
}
|
||||
}
|
||||
val replay = ReplayResources(this)
|
||||
|
||||
// Observers
|
||||
private lateinit var routeControl: RouteControl
|
||||
private lateinit var voiceControl: VoiceControl
|
||||
|
||||
private lateinit var routesObserver: RoutesObserver
|
||||
private lateinit var locationObserver: LocationObserver
|
||||
private lateinit var routeProgressObserver: RouteProgressObserver
|
||||
private lateinit var voiceInstructionsObserver: VoiceInstructionsObserver
|
||||
|
||||
fun init() {
|
||||
mapView.mapboxMap.loadStyle(Style.TRAFFIC_DAY) // TODO: base on sun position
|
||||
viewportDataSource = MapboxNavigationViewportDataSource(ui.mapView.mapboxMap)
|
||||
if (this.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
viewportDataSource.overviewPadding = UI.landscapeOverviewPadding
|
||||
} else {
|
||||
viewportDataSource.overviewPadding = UI.overviewPadding
|
||||
}
|
||||
if (this.resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
|
||||
viewportDataSource.followingPadding = UI.landscapeFollowingPadding
|
||||
} else {
|
||||
viewportDataSource.followingPadding = UI.followingPadding
|
||||
}
|
||||
|
||||
mapView.location.apply {
|
||||
// locationProvider = this.getLocationProvider()
|
||||
// setLocationProvider(navigationLocationProvider)
|
||||
navigationCamera = NavigationCamera(
|
||||
ui.mapView.mapboxMap,
|
||||
ui.mapView.camera,
|
||||
viewportDataSource
|
||||
)
|
||||
// set the animations lifecycle listener to ensure the NavigationCamera stops
|
||||
// automatically following the user location when the map is interacted with
|
||||
ui.mapView.camera.addCameraAnimationsLifecycleListener(
|
||||
NavigationBasicGesturesHandler(navigationCamera)
|
||||
)
|
||||
navigationCamera.registerNavigationCameraStateChangeObserver { navigationCameraState ->
|
||||
// shows/hide the recenter button depending on the camera state
|
||||
when (navigationCameraState) {
|
||||
NavigationCameraState.TRANSITION_TO_FOLLOWING,
|
||||
NavigationCameraState.FOLLOWING -> ui.recenter.visibility = View.INVISIBLE
|
||||
|
||||
NavigationCameraState.TRANSITION_TO_OVERVIEW,
|
||||
NavigationCameraState.OVERVIEW,
|
||||
NavigationCameraState.IDLE -> ui.recenter.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
routeControl = RouteControl(this, ui, context)
|
||||
voiceControl = VoiceControl(ui, context)
|
||||
|
||||
routesObserver = routeControl.routesObserver
|
||||
locationObserver = LocationObserver(this)
|
||||
routeProgressObserver = routeControl.routeProgressObserver
|
||||
voiceInstructionsObserver = voiceControl.voiceInstructionsObserver
|
||||
}
|
||||
|
||||
fun initNavigation() {
|
||||
MapboxNavigationApp.setup(
|
||||
NavigationOptions.Builder(context)
|
||||
.build()
|
||||
)
|
||||
|
||||
// initialize location puck
|
||||
ui.mapView.location.apply {
|
||||
setLocationProvider(navigationLocationProvider)
|
||||
this.locationPuck = LocationPuck2D(
|
||||
bearingImage = ImageHolder.Companion.from(
|
||||
com.mapbox.navigation.ui.maps.R.drawable.mapbox_navigation_puck_icon
|
||||
)
|
||||
)
|
||||
puckBearingEnabled = true
|
||||
enabled = true
|
||||
}
|
||||
|
||||
follow(true)
|
||||
setGestures(mapView)
|
||||
replay.replayOriginLocation()
|
||||
}
|
||||
|
||||
fun follow(immediately: Boolean = false) {
|
||||
mapView.viewport.apply {
|
||||
// transition to followPuckViewportState with default transition
|
||||
val followPuckViewportState: FollowPuckViewportState = this.makeFollowPuckViewportState(
|
||||
FollowPuckViewportStateOptions.Builder()
|
||||
// .bearing(FollowPuckViewportStateBearing.Constant(0.0))
|
||||
.padding(EdgeInsets(200.0 * resources.displayMetrics.density, 0.0, 0.0, 0.0))
|
||||
.build()
|
||||
)
|
||||
if (immediately) {
|
||||
val immediateTransition = this.makeImmediateViewportTransition()
|
||||
this.transitionTo(followPuckViewportState, immediateTransition) { success ->
|
||||
Log.d(TAG, "follow: $success")
|
||||
}
|
||||
} else {
|
||||
this.transitionTo(followPuckViewportState) { success ->
|
||||
Log.d(TAG, "follow: $success")
|
||||
}
|
||||
}
|
||||
}
|
||||
fun mapboxNavigation(): MapboxNavigation {
|
||||
return (context as MainActivity).mapboxNavigation
|
||||
}
|
||||
|
||||
private fun setGestures(mapView: MapView) {
|
||||
mapView.gestures.apply {
|
||||
addOnMapClickListener { point ->
|
||||
mapView.location.isLocatedAt(point) { isPuckLocatedAtPoint ->
|
||||
if (isPuckLocatedAtPoint) {
|
||||
follow()
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
addOnMapLongClickListener { point ->
|
||||
MapboxNavigationApp.current()?.requestRoutes(
|
||||
RouteOptions.builder()
|
||||
.applyDefaultNavigationOptions()
|
||||
.coordinatesList(mutableListOf(navigationLocationProvider.lastLocation!!.toPoint(), point))
|
||||
.build(),
|
||||
routesRequestCallback
|
||||
)
|
||||
true
|
||||
}
|
||||
}
|
||||
override fun onAttached(mapboxNavigation: MapboxNavigation) {
|
||||
mapboxNavigation.registerRoutesObserver(routesObserver)
|
||||
mapboxNavigation.registerLocationObserver(locationObserver)
|
||||
mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
|
||||
mapboxNavigation.registerVoiceInstructionsObserver(voiceInstructionsObserver)
|
||||
|
||||
replay.onAttached(mapboxNavigation)
|
||||
}
|
||||
|
||||
override fun onDetached(mapboxNavigation: MapboxNavigation) {
|
||||
mapboxNavigation.unregisterRoutesObserver(routesObserver)
|
||||
mapboxNavigation.unregisterLocationObserver(locationObserver)
|
||||
mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
|
||||
mapboxNavigation.unregisterVoiceInstructionsObserver(voiceInstructionsObserver)
|
||||
replay.onDetached(mapboxNavigation)
|
||||
}
|
||||
|
||||
fun onDestroy() {
|
||||
routeControl.cancel()
|
||||
voiceControl.cancel()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue