Skip to content

Commit 5851598

Browse files
authored
Fix ReplayRouteSession route state (#6675)
* Fix ReplayRouteSession route state * use new resetTripSession and set current route null * fix changelog
1 parent 88b9076 commit 5851598

File tree

4 files changed

+232
-63
lines changed

4 files changed

+232
-63
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Mapbox welcomes participation and contributions from everyone.
1212
- Fixed memory leak in `ReplayProgressObserver` which happened after route refresh. [#6691](https://github.com/mapbox/mapbox-navigation-android/pull/6691)
1313
- Fixed a rare issue where a reroute relative to old routes might have occurred after setting new routes. [#6693](https://github.com/mapbox/mapbox-navigation-android/pull/6693)
1414
- Added experimental `MapboxRouteLineOptions#shareLineGeometrySources` option to enable route line's GeoJson source data sharing between multiple instances of the map. [#6680](https://github.com/mapbox/mapbox-navigation-android/pull/6680)
15+
- Fixed issues in `ReplayRouteSession`. The routes observer was never unregistered. Alternative route selection resets replay to the beginning. DropInUi changing portrait and landscape modes resets replay to the beginning. [#6675](https://github.com/mapbox/mapbox-navigation-android/pull/6675)
1516

1617
## Mapbox Navigation SDK 2.9.4 - 08 December, 2022
1718
### Changelog

libnavigation-core/src/main/java/com/mapbox/navigation/core/replay/route/ReplayPolylineDecodeStream.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,15 @@ class ReplayPolylineDecodeStream(
9494
}
9595
return points
9696
}
97+
98+
/**
99+
* Skip the next [count] points of the geometry. Less points are skipped if there are less than
100+
* [count] points left in the iterator.
101+
*
102+
* @param count the number of points to skip.
103+
*/
104+
fun skip(count: Int) {
105+
var skipped = 0
106+
while (skipped++ <= count && hasNext()) { next() }
107+
}
97108
}

libnavigation-core/src/main/java/com/mapbox/navigation/core/replay/route/ReplayRouteSession.kt

Lines changed: 47 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.mapbox.android.core.permissions.PermissionsManager
99
import com.mapbox.api.directions.v5.DirectionsCriteria
1010
import com.mapbox.navigation.base.ExperimentalPreviewMapboxNavigationAPI
1111
import com.mapbox.navigation.base.route.NavigationRoute
12+
import com.mapbox.navigation.base.trip.model.RouteProgress
1213
import com.mapbox.navigation.core.MapboxNavigation
1314
import com.mapbox.navigation.core.directions.session.RoutesObserver
1415
import com.mapbox.navigation.core.lifecycle.MapboxNavigationApp
@@ -17,6 +18,7 @@ import com.mapbox.navigation.core.replay.MapboxReplayer
1718
import com.mapbox.navigation.core.replay.history.ReplayEventBase
1819
import com.mapbox.navigation.core.replay.history.ReplayEventUpdateLocation
1920
import com.mapbox.navigation.core.replay.history.ReplayEventsObserver
21+
import com.mapbox.navigation.core.trip.session.RouteProgressObserver
2022
import com.mapbox.navigation.utils.internal.logW
2123
import java.util.Collections
2224

@@ -54,15 +56,29 @@ class ReplayRouteSession : MapboxNavigationObserver {
5456

5557
private var options = ReplayRouteSessionOptions.Builder().build()
5658

57-
private lateinit var polylineDecodeStream: ReplayPolylineDecodeStream
5859
private lateinit var replayRouteMapper: ReplayRouteMapper
5960
private var mapboxNavigation: MapboxNavigation? = null
6061
private var lastLocationEvent: ReplayEventUpdateLocation? = null
61-
private var routesObserver: RoutesObserver? = null
62-
private var currentRouteId: String? = null
62+
private var polylineDecodeStream: ReplayPolylineDecodeStream? = null
63+
private var currentRoute: NavigationRoute? = null
64+
65+
private val routeProgressObserver = RouteProgressObserver { routeProgress ->
66+
if (currentRoute?.id != routeProgress.navigationRoute.id) {
67+
currentRoute = routeProgress.navigationRoute
68+
onRouteChanged(routeProgress)
69+
}
70+
}
71+
72+
private val routesObserver = RoutesObserver { result ->
73+
if (result.navigationRoutes.isEmpty()) {
74+
mapboxNavigation?.resetReplayLocation()
75+
currentRoute = null
76+
polylineDecodeStream = null
77+
}
78+
}
6379

6480
private val replayEventsObserver = ReplayEventsObserver { events ->
65-
if (isLastEventPlayed(events)) {
81+
if (currentRoute != null && isLastEventPlayed(events)) {
6682
pushMorePoints()
6783
}
6884
}
@@ -92,45 +108,44 @@ class ReplayRouteSession : MapboxNavigationObserver {
92108
this.mapboxNavigation = mapboxNavigation
93109
mapboxNavigation.stopTripSession()
94110
mapboxNavigation.startReplayTripSession()
95-
96-
routesObserver = RoutesObserver { result ->
97-
if (result.navigationRoutes.isEmpty()) {
98-
currentRouteId = null
99-
mapboxNavigation.resetReplayLocation()
100-
} else if (result.navigationRoutes.first().id != currentRouteId) {
101-
onRouteChanged(result.navigationRoutes.first())
102-
}
103-
}.also { mapboxNavigation.registerRoutesObserver(it) }
111+
mapboxNavigation.registerRouteProgressObserver(routeProgressObserver)
112+
mapboxNavigation.registerRoutesObserver(routesObserver)
104113
mapboxNavigation.mapboxReplayer.registerObserver(replayEventsObserver)
105-
mapboxNavigation.resetReplayLocation()
114+
mapboxNavigation.mapboxReplayer.play()
106115
}
107116

108117
private fun MapboxNavigation.resetReplayLocation() {
109118
mapboxReplayer.clearEvents()
110-
resetTripSession()
111-
if (options.locationResetEnabled) {
112-
val context = navigationOptions.applicationContext
113-
if (PermissionsManager.areLocationPermissionsGranted(context)) {
114-
pushRealLocation(context)
115-
} else {
116-
logW(LOG_CATEGORY) {
117-
"Location permission have not been accepted. If this is intentional, disable" +
118-
" this warning with ReplayRouteSessionOptions.locationResetEnabled."
119+
resetTripSession {
120+
if (options.locationResetEnabled) {
121+
val context = navigationOptions.applicationContext
122+
if (PermissionsManager.areLocationPermissionsGranted(context)) {
123+
pushRealLocation(context)
124+
} else {
125+
logW(LOG_CATEGORY) {
126+
"Location permissions have not been accepted. If this is intentional, " +
127+
"disable this warning with " +
128+
"ReplayRouteSessionOptions.locationResetEnabled."
129+
}
119130
}
120131
}
132+
mapboxReplayer.play()
121133
}
122-
mapboxReplayer.play()
123134
}
124135

125136
override fun onDetached(mapboxNavigation: MapboxNavigation) {
126-
this.mapboxNavigation = null
137+
mapboxNavigation.unregisterRoutesObserver(routesObserver)
138+
mapboxNavigation.unregisterRouteProgressObserver(routeProgressObserver)
127139
mapboxNavigation.mapboxReplayer.unregisterObserver(replayEventsObserver)
128140
mapboxNavigation.mapboxReplayer.stop()
129141
mapboxNavigation.mapboxReplayer.clearEvents()
130142
mapboxNavigation.stopTripSession()
143+
this.mapboxNavigation = null
144+
this.currentRoute = null
131145
}
132146

133-
private fun onRouteChanged(navigationRoute: NavigationRoute) {
147+
private fun onRouteChanged(routeProgress: RouteProgress) {
148+
val navigationRoute = routeProgress.navigationRoute
134149
val mapboxReplayer = mapboxNavigation?.mapboxReplayer ?: return
135150
mapboxReplayer.clearEvents()
136151
mapboxReplayer.play()
@@ -144,9 +159,12 @@ class ReplayRouteSession : MapboxNavigationObserver {
144159
}
145160
return
146161
}
147-
currentRouteId = navigationRoute.id
148162
polylineDecodeStream = ReplayPolylineDecodeStream(geometry, 6)
149-
mapboxNavigation?.resetTripSession()
163+
164+
// Skip up to the current geometry index. There is some imprecision here because the
165+
// distance traveled is not equal to a route index.
166+
polylineDecodeStream?.skip(routeProgress.currentRouteGeometryIndex)
167+
150168
pushMorePoints()
151169
}
152170

@@ -158,7 +176,7 @@ class ReplayRouteSession : MapboxNavigationObserver {
158176
}
159177

160178
private fun pushMorePoints() {
161-
val nextPoints = polylineDecodeStream.decode(options.decodeMinDistance)
179+
val nextPoints = polylineDecodeStream?.decode(options.decodeMinDistance) ?: return
162180
val nextReplayLocations = replayRouteMapper.mapPointList(nextPoints)
163181
lastLocationEvent = nextReplayLocations.lastOrNull { it is ReplayEventUpdateLocation }
164182
as? ReplayEventUpdateLocation

0 commit comments

Comments
 (0)