Skip to content

Commit b562551

Browse files
authored
Add RouteProgressState to RouteProgress for current route information from Navigator (#1502)
1 parent a17ce25 commit b562551

File tree

10 files changed

+104
-86
lines changed

10 files changed

+104
-86
lines changed

app/src/main/java/com/mapbox/services/android/navigation/testapp/activity/navigationui/WaypointNavigationActivity.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import android.support.annotation.Nullable;
77
import android.support.v7.app.AlertDialog;
88
import android.support.v7.app.AppCompatActivity;
9+
import android.widget.Toast;
910

1011
import com.mapbox.api.directions.v5.models.DirectionsResponse;
1112
import com.mapbox.api.directions.v5.models.DirectionsRoute;
@@ -153,6 +154,7 @@ public void onArrival() {
153154
if (!dropoffDialogShown && !points.isEmpty()) {
154155
showDropoffDialog();
155156
dropoffDialogShown = true; // Accounts for multiple arrival events
157+
Toast.makeText(this, "You have arrived!", Toast.LENGTH_SHORT).show();
156158
}
157159
}
158160

libandroid-navigation-ui/src/main/java/com/mapbox/services/android/navigation/ui/v5/NavigationViewModel.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ public void onProgressChange(Location location, RouteProgress routeProgress) {
300300
instructionModel.setValue(new InstructionModel(distanceFormatter, routeProgress));
301301
summaryModel.setValue(new SummaryModel(getApplication(), distanceFormatter, routeProgress, timeFormatType));
302302
navigationLocation.setValue(location);
303+
sendEventArrival(routeProgress);
303304
}
304305
};
305306

@@ -319,7 +320,6 @@ public void userOffRoute(Location location) {
319320
public void onMilestoneEvent(RouteProgress routeProgress, String instruction, Milestone milestone) {
320321
playVoiceAnnouncement(milestone);
321322
updateBannerInstruction(routeProgress, milestone);
322-
sendEventArrival(routeProgress, milestone);
323323
}
324324
};
325325

@@ -445,8 +445,8 @@ private void sendEventFeedback(FeedbackItem feedbackItem) {
445445
}
446446
}
447447

448-
private void sendEventArrival(RouteProgress routeProgress, Milestone milestone) {
449-
if (navigationViewEventDispatcher != null && routeUtils.isArrivalEvent(routeProgress, milestone)) {
448+
private void sendEventArrival(RouteProgress routeProgress) {
449+
if (navigationViewEventDispatcher != null && routeUtils.isArrivalEvent(routeProgress)) {
450450
navigationViewEventDispatcher.onArrival();
451451
}
452452
}

libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/NavigationEventDispatcher.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ void removeFasterRouteListener(@Nullable FasterRouteListener fasterRouteListener
132132
}
133133

134134
void onMilestoneEvent(RouteProgress routeProgress, String instruction, Milestone milestone) {
135-
checkForArrivalEvent(routeProgress, milestone);
135+
checkForArrivalEvent(routeProgress);
136136
for (MilestoneEventListener milestoneEventListener : milestoneEventListeners) {
137137
milestoneEventListener.onMilestoneEvent(routeProgress, instruction, milestone);
138138
}
@@ -172,8 +172,8 @@ void addMetricEventListeners(NavigationMetricListener eventListeners) {
172172
}
173173
}
174174

175-
private void checkForArrivalEvent(RouteProgress routeProgress, Milestone milestone) {
176-
if (metricEventListener != null && routeUtils.isArrivalEvent(routeProgress, milestone)) {
175+
private void checkForArrivalEvent(RouteProgress routeProgress) {
176+
if (metricEventListener != null && routeUtils.isArrivalEvent(routeProgress)) {
177177
metricEventListener.onArrival(routeProgress);
178178
if (routeUtils.isLastLeg(routeProgress)) {
179179
metricEventListener = null;

libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/navigation/NavigationRouteProcessor.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@
99
import com.mapbox.api.directions.v5.models.StepIntersection;
1010
import com.mapbox.geojson.Point;
1111
import com.mapbox.navigator.NavigationStatus;
12+
import com.mapbox.navigator.RouteState;
1213
import com.mapbox.navigator.VoiceInstruction;
1314
import com.mapbox.services.android.navigation.v5.routeprogress.CurrentLegAnnotation;
1415
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
16+
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgressState;
17+
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgressStateMap;
1518

1619
import java.util.List;
1720

@@ -27,6 +30,7 @@ class NavigationRouteProcessor {
2730

2831
private static final int ONE_INDEX = 1;
2932
private static final double ONE_SECOND_IN_MILLISECONDS = 1000.0;
33+
private final RouteProgressStateMap progressStateMap = new RouteProgressStateMap();
3034
private RouteProgress previousRouteProgress;
3135
private DirectionsRoute route;
3236
private RouteLeg currentLeg;
@@ -79,6 +83,8 @@ private RouteProgress buildRouteProgressFrom(NavigationStatus status) {
7983
StepIntersection upcomingIntersection = findUpcomingIntersection(
8084
currentIntersections, upcomingStep, currentIntersection
8185
);
86+
RouteState routeState = status.getRouteState();
87+
RouteProgressState currentRouteState = progressStateMap.get(routeState);
8288

8389
RouteProgress.Builder progressBuilder = RouteProgress.builder()
8490
.distanceRemaining(routeDistanceRemaining)
@@ -95,7 +101,8 @@ private RouteProgress buildRouteProgressFrom(NavigationStatus status) {
95101
.upcomingIntersection(upcomingIntersection)
96102
.intersectionDistancesAlongStep(currentIntersectionDistances)
97103
.currentLegAnnotation(currentLegAnnotation)
98-
.inTunnel(status.getInTunnel());
104+
.inTunnel(status.getInTunnel())
105+
.currentState(currentRouteState);
99106

100107
// TODO build banner instructions from status here
101108
addVoiceInstructions(status, progressBuilder);

libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/routeprogress/RouteProgress.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,15 @@ public int remainingWaypoints() {
168168
@Nullable
169169
public abstract VoiceInstruction voiceInstruction();
170170

171+
/**
172+
* Returns the current state of progress along the route. Provides route and location tracking
173+
* information.
174+
*
175+
* @return the current state of progress along the route.
176+
*/
177+
@Nullable
178+
public abstract RouteProgressState currentState();
179+
171180
public abstract RouteProgress.Builder toBuilder();
172181

173182
abstract int stepIndex();
@@ -255,6 +264,8 @@ public abstract Builder intersectionDistancesAlongStep(
255264

256265
public abstract Builder voiceInstruction(@Nullable VoiceInstruction voiceInstruction);
257266

267+
public abstract Builder currentState(@Nullable RouteProgressState currentState);
268+
258269
abstract RouteProgress autoBuild(); // not public
259270

260271
public RouteProgress build() {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.mapbox.services.android.navigation.v5.routeprogress;
2+
3+
import com.mapbox.api.directions.v5.models.DirectionsRoute;
4+
5+
/**
6+
* Contains the various progress states that can occur while navigating.
7+
*/
8+
public enum RouteProgressState {
9+
10+
/**
11+
* The {@link com.mapbox.api.directions.v5.models.DirectionsRoute} provided
12+
* via {@link com.mapbox.services.android.navigation.v5.navigation.MapboxNavigation#startNavigation(DirectionsRoute)}
13+
* is not valid.
14+
*/
15+
ROUTE_INVALID,
16+
17+
/**
18+
* The {@link DirectionsRoute} is valid
19+
* and {@link com.mapbox.services.android.navigation.v5.navigation.MapboxNavigation} is waiting for
20+
* sufficient {@link android.location.Location} updates
21+
* from the {@link com.mapbox.android.core.location.LocationEngine}.
22+
*/
23+
ROUTE_INITIALIZED,
24+
25+
/**
26+
* The user has arrived at the destination of the given {@link com.mapbox.api.directions.v5.models.RouteLeg}.
27+
*/
28+
ROUTE_ARRIVED,
29+
30+
/**
31+
* {@link com.mapbox.services.android.navigation.v5.navigation.MapboxNavigation} is now confidently tracking the
32+
* location updates and processing them against the route.
33+
*/
34+
LOCATION_TRACKING,
35+
36+
/**
37+
* A lack of {@link android.location.Location} updates from the phone has caused lack of confidence in the
38+
* progress updates being sent.
39+
*/
40+
LOCATION_STALE
41+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.mapbox.services.android.navigation.v5.routeprogress;
2+
3+
import com.mapbox.navigator.RouteState;
4+
5+
import java.util.HashMap;
6+
7+
public final class RouteProgressStateMap extends HashMap<RouteState, RouteProgressState> {
8+
9+
public RouteProgressStateMap() {
10+
put(RouteState.INVALID, RouteProgressState.ROUTE_INVALID);
11+
put(RouteState.INITIALIZED, RouteProgressState.ROUTE_INITIALIZED);
12+
put(RouteState.COMPLETE, RouteProgressState.ROUTE_ARRIVED);
13+
put(RouteState.TRACKING, RouteProgressState.LOCATION_TRACKING);
14+
put(RouteState.STALE, RouteProgressState.LOCATION_STALE);
15+
put(RouteState.OFFROUTE, null); // Ignore off-route (info already provided via listener)
16+
}
17+
}

libandroid-navigation/src/main/java/com/mapbox/services/android/navigation/v5/utils/RouteUtils.java

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@
1414
import com.mapbox.api.directions.v5.models.VoiceInstructions;
1515
import com.mapbox.core.utils.TextUtils;
1616
import com.mapbox.geojson.Point;
17-
import com.mapbox.services.android.navigation.v5.milestone.BannerInstructionMilestone;
18-
import com.mapbox.services.android.navigation.v5.milestone.Milestone;
1917
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
18+
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgressState;
2019

2120
import java.util.ArrayList;
2221
import java.util.Arrays;
@@ -77,31 +76,15 @@ public boolean isNewRoute(@Nullable RouteProgress previousRouteProgress,
7776
}
7877

7978
/**
80-
* Looks at the current {@link RouteProgress} maneuverType for type "arrival", then
81-
* checks if the arrival meter threshold has been hit.
79+
* Looks at the current {@link RouteProgressState} and returns if
80+
* is {@link RouteProgressState#ROUTE_ARRIVED}.
8281
*
8382
* @param routeProgress the current route progress
84-
* @param milestone the current milestone from the MilestoneEventListener
8583
* @return true if in arrival state, false if not
86-
* @since 0.8.0
8784
*/
88-
public boolean isArrivalEvent(@NonNull RouteProgress routeProgress, @NonNull Milestone milestone) {
89-
if (!(milestone instanceof BannerInstructionMilestone)) {
90-
return false;
91-
}
92-
boolean isValidArrivalManeuverType = upcomingStepIsArrivalManeuverType(routeProgress)
93-
|| currentStepIsArrivalManeuverType(routeProgress);
94-
if (isValidArrivalManeuverType) {
95-
LegStep currentStep = routeProgress.currentLegProgress().currentStep();
96-
BannerInstructions currentInstructions = ((BannerInstructionMilestone) milestone).getBannerInstructions();
97-
List<BannerInstructions> bannerInstructions = currentStep.bannerInstructions();
98-
if (hasValidInstructions(bannerInstructions, currentInstructions)) {
99-
int lastInstructionIndex = bannerInstructions.size() - 1;
100-
BannerInstructions lastInstructions = bannerInstructions.get(lastInstructionIndex);
101-
return currentInstructions.equals(lastInstructions);
102-
}
103-
}
104-
return false;
85+
public boolean isArrivalEvent(@NonNull RouteProgress routeProgress) {
86+
RouteProgressState currentState = routeProgress.currentState();
87+
return currentState != null && currentState == RouteProgressState.ROUTE_ARRIVED;
10588
}
10689

10790
/**

libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/navigation/NavigationEventDispatcherTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ public void setNavigationMetricListener_didNotGetTriggeredBeforeArrival() throws
315315
String instruction = "";
316316
BannerInstructionMilestone milestone = mock(BannerInstructionMilestone.class);
317317
RouteUtils routeUtils = mock(RouteUtils.class);
318-
when(routeUtils.isArrivalEvent(routeProgress, milestone)).thenReturn(false);
318+
when(routeUtils.isArrivalEvent(routeProgress)).thenReturn(false);
319319
NavigationEventDispatcher navigationEventDispatcher = new NavigationEventDispatcher(routeUtils);
320320
navigationEventDispatcher.addMetricEventListeners(metricEventListener);
321321

@@ -329,7 +329,7 @@ public void setNavigationMetricListener_doesGetTriggeredUponArrival() throws Exc
329329
String instruction = "";
330330
BannerInstructionMilestone milestone = mock(BannerInstructionMilestone.class);
331331
RouteUtils routeUtils = mock(RouteUtils.class);
332-
when(routeUtils.isArrivalEvent(routeProgress, milestone)).thenReturn(true);
332+
when(routeUtils.isArrivalEvent(routeProgress)).thenReturn(true);
333333
NavigationEventDispatcher navigationEventDispatcher = new NavigationEventDispatcher(routeUtils);
334334
navigationEventDispatcher.addMetricEventListeners(metricEventListener);
335335

@@ -344,7 +344,7 @@ public void onArrivalDuringLastLeg_metricEventListenerIsRemoved() {
344344
Location location = mock(Location.class);
345345
BannerInstructionMilestone milestone = mock(BannerInstructionMilestone.class);
346346
RouteUtils routeUtils = mock(RouteUtils.class);
347-
when(routeUtils.isArrivalEvent(routeProgress, milestone)).thenReturn(true);
347+
when(routeUtils.isArrivalEvent(routeProgress)).thenReturn(true);
348348
when(routeUtils.isLastLeg(routeProgress)).thenReturn(true);
349349
NavigationEventDispatcher dispatcher = buildEventDispatcherHasArrived(instruction, routeUtils, milestone);
350350

@@ -359,7 +359,7 @@ public void onArrivalAlreadyOccurred_arrivalCheckIsIgnored() {
359359
Location location = mock(Location.class);
360360
BannerInstructionMilestone milestone = mock(BannerInstructionMilestone.class);
361361
RouteUtils routeUtils = mock(RouteUtils.class);
362-
when(routeUtils.isArrivalEvent(routeProgress, milestone)).thenReturn(true);
362+
when(routeUtils.isArrivalEvent(routeProgress)).thenReturn(true);
363363
when(routeUtils.isLastLeg(routeProgress)).thenReturn(true);
364364
NavigationEventDispatcher dispatcher = buildEventDispatcherHasArrived(instruction, routeUtils, milestone);
365365

libandroid-navigation/src/test/java/com/mapbox/services/android/navigation/v5/utils/RouteUtilsTest.java

Lines changed: 9 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
import com.mapbox.api.directions.v5.models.BannerText;
88
import com.mapbox.api.directions.v5.models.DirectionsRoute;
99
import com.mapbox.api.directions.v5.models.LegStep;
10-
import com.mapbox.api.directions.v5.models.RouteLeg;
1110
import com.mapbox.api.directions.v5.models.RouteOptions;
1211
import com.mapbox.api.directions.v5.models.VoiceInstructions;
1312
import com.mapbox.geojson.Point;
1413
import com.mapbox.services.android.navigation.v5.BaseTest;
1514
import com.mapbox.services.android.navigation.v5.milestone.BannerInstructionMilestone;
1615
import com.mapbox.services.android.navigation.v5.routeprogress.RouteLegProgress;
1716
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;
17+
import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgressState;
1818

1919
import org.junit.Test;
2020

@@ -65,66 +65,23 @@ public void isNewRoute_returnsTrueWhenGeometriesDoNotEqual() throws Exception {
6565
}
6666

6767
@Test
68-
public void isArrivalEvent_returnsTrueWhenManeuverTypeIsArrival_andIsLastInstruction() throws Exception {
69-
DirectionsRoute route = buildTestDirectionsRoute();
70-
int first = 0;
71-
int lastInstruction = 1;
72-
RouteLeg routeLeg = route.legs().get(first);
73-
List<LegStep> routeSteps = routeLeg.steps();
74-
int currentStepIndex = routeSteps.size() - 2;
75-
int upcomingStepIndex = routeSteps.size() - 1;
76-
LegStep currentStep = routeSteps.get(currentStepIndex);
77-
LegStep upcomingStep = routeSteps.get(upcomingStepIndex);
78-
RouteProgress routeProgress = buildRouteProgress(first, route, currentStep, upcomingStep);
79-
BannerInstructionMilestone bannerInstructionMilestone = mock(BannerInstructionMilestone.class);
80-
List<BannerInstructions> currentStepBannerInstructions = currentStep.bannerInstructions();
81-
buildBannerInstruction(lastInstruction, bannerInstructionMilestone, currentStepBannerInstructions);
82-
68+
public void isArrivalEvent_returnsTrueWhenRouteProgressStateIsArrived() {
69+
RouteProgress routeProgress = mock(RouteProgress.class);
70+
when(routeProgress.currentState()).thenReturn(RouteProgressState.ROUTE_ARRIVED);
8371
RouteUtils routeUtils = new RouteUtils();
8472

85-
boolean isArrivalEvent = routeUtils.isArrivalEvent(routeProgress, bannerInstructionMilestone);
73+
boolean isArrivalEvent = routeUtils.isArrivalEvent(routeProgress);
8674

8775
assertTrue(isArrivalEvent);
8876
}
8977

9078
@Test
91-
public void isArrivalEvent_returnsFalseWhenManeuverTypeIsArrival_andIsNotLastInstruction() throws Exception {
92-
DirectionsRoute route = buildTestDirectionsRoute();
93-
int first = 0;
94-
RouteLeg routeLeg = route.legs().get(first);
95-
List<LegStep> routeSteps = routeLeg.steps();
96-
int currentStepIndex = routeSteps.size() - 2;
97-
int upcomingStepIndex = routeSteps.size() - 1;
98-
LegStep currentStep = routeSteps.get(currentStepIndex);
99-
LegStep upcomingStep = routeSteps.get(upcomingStepIndex);
100-
RouteProgress routeProgress = buildRouteProgress(first, route, currentStep, upcomingStep);
101-
BannerInstructionMilestone bannerInstructionMilestone = mock(BannerInstructionMilestone.class);
102-
List<BannerInstructions> currentStepBannerInstructions = currentStep.bannerInstructions();
103-
buildBannerInstruction(first, bannerInstructionMilestone, currentStepBannerInstructions);
104-
105-
RouteUtils routeUtils = new RouteUtils();
106-
107-
boolean isArrivalEvent = routeUtils.isArrivalEvent(routeProgress, bannerInstructionMilestone);
108-
109-
assertFalse(isArrivalEvent);
110-
}
111-
112-
@Test
113-
public void isArrivalEvent_returnsFalseWhenManeuverTypeIsNotArrival() throws Exception {
114-
DirectionsRoute route = buildTestDirectionsRoute();
115-
int first = 0;
116-
RouteLeg routeLeg = route.legs().get(first);
117-
List<LegStep> routeSteps = routeLeg.steps();
118-
LegStep currentStep = routeSteps.get(first);
119-
LegStep upcomingStep = routeSteps.get(first + 1);
120-
RouteProgress routeProgress = buildRouteProgress(first, route, currentStep, upcomingStep);
121-
BannerInstructionMilestone bannerInstructionMilestone = mock(BannerInstructionMilestone.class);
122-
List<BannerInstructions> currentStepBannerInstructions = currentStep.bannerInstructions();
123-
buildBannerInstruction(first, bannerInstructionMilestone, currentStepBannerInstructions);
124-
79+
public void isArrivalEvent_returnsFalseWhenRouteProgressStateIsNotArrived() {
80+
RouteProgress routeProgress = mock(RouteProgress.class);
81+
when(routeProgress.currentState()).thenReturn(RouteProgressState.LOCATION_TRACKING);
12582
RouteUtils routeUtils = new RouteUtils();
12683

127-
boolean isArrivalEvent = routeUtils.isArrivalEvent(routeProgress, bannerInstructionMilestone);
84+
boolean isArrivalEvent = routeUtils.isArrivalEvent(routeProgress);
12885

12986
assertFalse(isArrivalEvent);
13087
}

0 commit comments

Comments
 (0)