@@ -12,7 +12,6 @@ import com.mapbox.navigation.base.route.NavigationRoute
1212import com.mapbox.navigation.base.trip.model.RouteProgress
1313import com.mapbox.navigation.core.MapboxNavigation
1414import com.mapbox.navigation.core.directions.session.RoutesObserver
15- import com.mapbox.navigation.core.history.MapboxHistoryReaderProvider
1615import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
1716import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
1817import com.mapbox.navigation.core.replay.MapboxReplayer
@@ -24,6 +23,7 @@ import com.mapbox.navigation.utils.internal.logW
2423import kotlinx.coroutines.CoroutineScope
2524import kotlinx.coroutines.Dispatchers
2625import kotlinx.coroutines.SupervisorJob
26+ import kotlinx.coroutines.cancel
2727import kotlinx.coroutines.flow.Flow
2828import kotlinx.coroutines.flow.MutableStateFlow
2929import kotlinx.coroutines.flow.StateFlow
@@ -67,25 +67,33 @@ import java.util.Collections
6767class ReplayRouteSession : MapboxNavigationObserver {
6868
6969 private lateinit var replayRouteMapper: ReplayRouteMapper
70+ private lateinit var coroutineScope: CoroutineScope
7071 private val optionsFlow = MutableStateFlow (ReplayRouteSessionOptions .Builder ().build())
7172 private var mapboxNavigation: MapboxNavigation ? = null
7273 private var lastLocationEvent: ReplayEventUpdateLocation ? = null
7374 private var polylineDecodeStream: ReplayPolylineDecodeStream ? = null
7475 private var currentRoute: NavigationRoute ? = null
75- private var coroutineScope: CoroutineScope ? = null
76+ set(value) {
77+ field = value
78+ isNewRouteInitialized = value != null
79+ }
80+ private var isNewRouteInitialized = false
7681
7782 private val routeProgressObserver = RouteProgressObserver { routeProgress ->
7883 if (currentRoute?.id != routeProgress.navigationRoute.id) {
7984 currentRoute = routeProgress.navigationRoute
80- onRouteChanged (routeProgress)
85+ onRouteProgressRouteChanged (routeProgress)
8186 }
8287 }
8388
8489 private val routesObserver = RoutesObserver { result ->
85- if (result.navigationRoutes.isEmpty()) {
90+ val route = result.navigationRoutes.firstOrNull()
91+ if (route == null ) {
8692 mapboxNavigation?.resetReplayLocation()
8793 currentRoute = null
8894 polylineDecodeStream = null
95+ } else if (! isNewRouteInitialized && currentRoute?.id != route.id) {
96+ onInitializeNewRoute(route)
8997 }
9098 }
9199
@@ -113,24 +121,23 @@ class ReplayRouteSession : MapboxNavigationObserver {
113121 }
114122
115123 override fun onAttached (mapboxNavigation : MapboxNavigation ) {
116- val coroutineScope = CoroutineScope (SupervisorJob () + Dispatchers .Main .immediate)
117- .also { this .coroutineScope = it }
124+ this .coroutineScope = CoroutineScope (SupervisorJob () + Dispatchers .Main .immediate)
118125 this .mapboxNavigation = mapboxNavigation
119126 mapboxNavigation.startReplayTripSession()
120- mapboxNavigation.registerRouteProgressObserver(routeProgressObserver )
127+ observeStateFlow( mapboxNavigation).launchIn(coroutineScope )
121128 mapboxNavigation.registerRoutesObserver(routesObserver)
129+ mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
122130 mapboxNavigation.mapboxReplayer.registerObserver(replayEventsObserver)
123- mapboxNavigation.mapboxReplayer.play()
124- observeStateFlow(mapboxNavigation).launchIn(coroutineScope)
125131 }
126132
127133 private fun observeStateFlow (mapboxNavigation : MapboxNavigation ): Flow <* > {
128134 return optionsFlow.mapDistinct { it.replayRouteOptions }.onEach { replayRouteOptions ->
129135 mapboxNavigation.mapboxReplayer.clearEvents()
130136 this .replayRouteMapper = ReplayRouteMapper (replayRouteOptions)
131- val routes = mapboxNavigation.getNavigationRoutes()
132- mapboxNavigation.setNavigationRoutes(emptyList())
133- mapboxNavigation.setNavigationRoutes(routes)
137+ currentRoute = null
138+ mapboxNavigation.resetTripSession {
139+ mapboxNavigation.mapboxReplayer.play()
140+ }
134141 }
135142 }
136143
@@ -158,6 +165,9 @@ class ReplayRouteSession : MapboxNavigationObserver {
158165 }
159166
160167 override fun onDetached (mapboxNavigation : MapboxNavigation ) {
168+ if (this ::coroutineScope.isInitialized) {
169+ coroutineScope.cancel()
170+ }
161171 mapboxNavigation.unregisterRoutesObserver(routesObserver)
162172 mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
163173 mapboxNavigation.mapboxReplayer.unregisterObserver(replayEventsObserver)
@@ -167,28 +177,43 @@ class ReplayRouteSession : MapboxNavigationObserver {
167177 this .currentRoute = null
168178 }
169179
170- private fun onRouteChanged (routeProgress : RouteProgress ) {
180+ private fun onInitializeNewRoute (route : NavigationRoute ) {
181+ mapboxNavigation?.mapboxReplayer?.clearEvents()
182+ this .replayRouteMapper = ReplayRouteMapper (optionsFlow.value.replayRouteOptions)
183+ mapboxNavigation?.resetTripSession {
184+ route.routeOptions.coordinatesList().firstOrNull()?.let {
185+ val replayFirstLocation = replayRouteMapper.mapPointList(listOf (it))
186+ mapboxNavigation?.mapboxReplayer?.pushEvents(replayFirstLocation)
187+ }
188+ mapboxNavigation?.mapboxReplayer?.play()
189+ }
190+ isNewRouteInitialized = true
191+ }
192+
193+ private fun onRouteProgressRouteChanged (routeProgress : RouteProgress ) {
171194 val navigationRoute = routeProgress.navigationRoute
172195 val mapboxReplayer = mapboxNavigation?.mapboxReplayer ? : return
173196 mapboxReplayer.clearEvents()
174- mapboxReplayer.play()
175- val geometries = navigationRoute.directionsRoute.routeOptions()!! .geometries()
176- val usesPolyline6 = geometries.contains(DirectionsCriteria .GEOMETRY_POLYLINE6 )
177- val geometry = navigationRoute.directionsRoute.geometry()
178- if (! usesPolyline6 || geometry.isNullOrEmpty()) {
179- logW(LOG_CATEGORY ) {
180- " The NavigationRouteReplay must have geometry encoded with polyline6 " +
181- " $geometries $geometry "
197+ mapboxNavigation?.resetTripSession {
198+ mapboxReplayer.play()
199+ val geometries = navigationRoute.directionsRoute.routeOptions()!! .geometries()
200+ val usesPolyline6 = geometries.contains(DirectionsCriteria .GEOMETRY_POLYLINE6 )
201+ val geometry = navigationRoute.directionsRoute.geometry()
202+ if (! usesPolyline6 || geometry.isNullOrEmpty()) {
203+ logW(LOG_CATEGORY ) {
204+ " The NavigationRouteReplay must have geometry encoded with polyline6 " +
205+ " $geometries $geometry "
206+ }
207+ return @resetTripSession
182208 }
183- return
184- }
185- polylineDecodeStream = ReplayPolylineDecodeStream (geometry, 6 )
209+ polylineDecodeStream = ReplayPolylineDecodeStream (geometry, 6 )
186210
187- // Skip up to the current geometry index. There is some imprecision here because the
188- // distance traveled is not equal to a route index.
189- polylineDecodeStream?.skip(routeProgress.currentRouteGeometryIndex)
211+ // Skip up to the current geometry index. There is some imprecision here because the
212+ // distance traveled is not equal to a route index.
213+ polylineDecodeStream?.skip(routeProgress.currentRouteGeometryIndex)
190214
191- pushMorePoints()
215+ pushMorePoints()
216+ }
192217 }
193218
194219 private fun isLastEventPlayed (events : List <ReplayEventBase >): Boolean {
0 commit comments