@@ -12,7 +12,6 @@ import com.mapbox.navigation.base.route.NavigationRoute
12
12
import com.mapbox.navigation.base.trip.model.RouteProgress
13
13
import com.mapbox.navigation.core.MapboxNavigation
14
14
import com.mapbox.navigation.core.directions.session.RoutesObserver
15
- import com.mapbox.navigation.core.history.MapboxHistoryReaderProvider
16
15
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
17
16
import com.mapbox.navigation.core.lifecycle.MapboxNavigationObserver
18
17
import com.mapbox.navigation.core.replay.MapboxReplayer
@@ -24,6 +23,7 @@ import com.mapbox.navigation.utils.internal.logW
24
23
import kotlinx.coroutines.CoroutineScope
25
24
import kotlinx.coroutines.Dispatchers
26
25
import kotlinx.coroutines.SupervisorJob
26
+ import kotlinx.coroutines.cancel
27
27
import kotlinx.coroutines.flow.Flow
28
28
import kotlinx.coroutines.flow.MutableStateFlow
29
29
import kotlinx.coroutines.flow.StateFlow
@@ -67,25 +67,33 @@ import java.util.Collections
67
67
class ReplayRouteSession : MapboxNavigationObserver {
68
68
69
69
private lateinit var replayRouteMapper: ReplayRouteMapper
70
+ private lateinit var coroutineScope: CoroutineScope
70
71
private val optionsFlow = MutableStateFlow (ReplayRouteSessionOptions .Builder ().build())
71
72
private var mapboxNavigation: MapboxNavigation ? = null
72
73
private var lastLocationEvent: ReplayEventUpdateLocation ? = null
73
74
private var polylineDecodeStream: ReplayPolylineDecodeStream ? = null
74
75
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
76
81
77
82
private val routeProgressObserver = RouteProgressObserver { routeProgress ->
78
83
if (currentRoute?.id != routeProgress.navigationRoute.id) {
79
84
currentRoute = routeProgress.navigationRoute
80
- onRouteChanged (routeProgress)
85
+ onRouteProgressRouteChanged (routeProgress)
81
86
}
82
87
}
83
88
84
89
private val routesObserver = RoutesObserver { result ->
85
- if (result.navigationRoutes.isEmpty()) {
90
+ val route = result.navigationRoutes.firstOrNull()
91
+ if (route == null ) {
86
92
mapboxNavigation?.resetReplayLocation()
87
93
currentRoute = null
88
94
polylineDecodeStream = null
95
+ } else if (! isNewRouteInitialized && currentRoute?.id != route.id) {
96
+ onInitializeNewRoute(route)
89
97
}
90
98
}
91
99
@@ -113,24 +121,23 @@ class ReplayRouteSession : MapboxNavigationObserver {
113
121
}
114
122
115
123
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)
118
125
this .mapboxNavigation = mapboxNavigation
119
126
mapboxNavigation.startReplayTripSession()
120
- mapboxNavigation.registerRouteProgressObserver(routeProgressObserver )
127
+ observeStateFlow( mapboxNavigation).launchIn(coroutineScope )
121
128
mapboxNavigation.registerRoutesObserver(routesObserver)
129
+ mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
122
130
mapboxNavigation.mapboxReplayer.registerObserver(replayEventsObserver)
123
- mapboxNavigation.mapboxReplayer.play()
124
- observeStateFlow(mapboxNavigation).launchIn(coroutineScope)
125
131
}
126
132
127
133
private fun observeStateFlow (mapboxNavigation : MapboxNavigation ): Flow <* > {
128
134
return optionsFlow.mapDistinct { it.replayRouteOptions }.onEach { replayRouteOptions ->
129
135
mapboxNavigation.mapboxReplayer.clearEvents()
130
136
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
+ }
134
141
}
135
142
}
136
143
@@ -158,6 +165,9 @@ class ReplayRouteSession : MapboxNavigationObserver {
158
165
}
159
166
160
167
override fun onDetached (mapboxNavigation : MapboxNavigation ) {
168
+ if (this ::coroutineScope.isInitialized) {
169
+ coroutineScope.cancel()
170
+ }
161
171
mapboxNavigation.unregisterRoutesObserver(routesObserver)
162
172
mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
163
173
mapboxNavigation.mapboxReplayer.unregisterObserver(replayEventsObserver)
@@ -167,28 +177,43 @@ class ReplayRouteSession : MapboxNavigationObserver {
167
177
this .currentRoute = null
168
178
}
169
179
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 ) {
171
194
val navigationRoute = routeProgress.navigationRoute
172
195
val mapboxReplayer = mapboxNavigation?.mapboxReplayer ? : return
173
196
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
182
208
}
183
- return
184
- }
185
- polylineDecodeStream = ReplayPolylineDecodeStream (geometry, 6 )
209
+ polylineDecodeStream = ReplayPolylineDecodeStream (geometry, 6 )
186
210
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)
190
214
191
- pushMorePoints()
215
+ pushMorePoints()
216
+ }
192
217
}
193
218
194
219
private fun isLastEventPlayed (events : List <ReplayEventBase >): Boolean {
0 commit comments