Skip to content

Commit b2ac0cb

Browse files
Cameron Macezugaldia
authored andcommitted
Navigation improvements (#426)
* isolated listeners in seperate subpackage and handle ending the route when user arrives to final destination * only report the user is off route once and don't call listener again * added update route method * support multiple listeners * fixed a few issues * removed unused imports * fixed offroute to match same logic used in ios * added back some logic into monitorrouteprogress * fixed boolean being reversed for user off route * added bearing snapping logic * fixed checkstyle
1 parent a5cef53 commit b2ac0cb

12 files changed

Lines changed: 441 additions & 258 deletions

File tree

mapbox/app/src/main/java/com/mapbox/services/android/testapp/nav/NavigationActivity.java

Lines changed: 54 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@
2424
import com.mapbox.mapboxsdk.maps.MapboxMap;
2525
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
2626
import com.mapbox.services.Constants;
27-
import com.mapbox.services.android.navigation.v5.AlertLevelChangeListener;
2827
import com.mapbox.services.android.navigation.v5.MapboxNavigation;
29-
import com.mapbox.services.android.navigation.v5.NavigationEventListener;
30-
import com.mapbox.services.android.navigation.v5.ProgressChangeListener;
28+
import com.mapbox.services.android.navigation.v5.listeners.AlertLevelChangeListener;
29+
import com.mapbox.services.android.navigation.v5.listeners.NavigationEventListener;
30+
import com.mapbox.services.android.navigation.v5.listeners.OffRouteListener;
31+
import com.mapbox.services.android.navigation.v5.listeners.ProgressChangeListener;
3132
import com.mapbox.services.android.telemetry.location.LocationEngine;
3233
import com.mapbox.services.android.telemetry.location.LocationEnginePriority;
3334
import com.mapbox.services.android.telemetry.permissions.PermissionsManager;
@@ -55,7 +56,7 @@
5556
import static com.mapbox.services.android.Constants.NONE_ALERT_LEVEL;
5657

5758
public class NavigationActivity extends AppCompatActivity implements OnMapReadyCallback, OnMapClickListener,
58-
ProgressChangeListener, NavigationEventListener, AlertLevelChangeListener {
59+
ProgressChangeListener, NavigationEventListener, AlertLevelChangeListener, OffRouteListener {
5960

6061
// Map variables
6162
private MapView mapView;
@@ -68,12 +69,21 @@ public class NavigationActivity extends AppCompatActivity implements OnMapReadyC
6869
private MapboxNavigation navigation;
6970
private Button startRouteButton;
7071
private DirectionsRoute route;
72+
private Position destination;
7173

7274
@Override
7375
protected void onCreate(Bundle savedInstanceState) {
7476
super.onCreate(savedInstanceState);
7577
setContentView(R.layout.activity_navigation_activity);
7678

79+
mapView = (MapView) findViewById(R.id.mapView);
80+
mapView.onCreate(savedInstanceState);
81+
mapView.getMapAsync(this);
82+
83+
locationEngine = LocationSource.getLocationEngine(this);
84+
85+
navigation = new MapboxNavigation(this, Mapbox.getAccessToken());
86+
7787

7888
startRouteButton = (Button) findViewById(R.id.startRouteButton);
7989
startRouteButton.setOnClickListener(new View.OnClickListener() {
@@ -85,9 +95,9 @@ public void onClick(View view) {
8595
startRouteButton.setVisibility(View.INVISIBLE);
8696

8797
// Attach all of our navigation listeners.
88-
navigation.setNavigationEventListener(NavigationActivity.this);
89-
navigation.setProgressChangeListener(NavigationActivity.this);
90-
navigation.setAlertLevelChangeListener(NavigationActivity.this);
98+
navigation.addNavigationEventListener(NavigationActivity.this);
99+
navigation.addProgressChangeListener(NavigationActivity.this);
100+
navigation.addAlertLevelChangeListener(NavigationActivity.this);
91101

92102
// Adjust location engine to force a gps reading every second. This isn't required but gives an overall
93103
// better navigation experience for users. The updating only occurs if the user moves 3 meters or further
@@ -102,16 +112,6 @@ public void onClick(View view) {
102112
}
103113
}
104114
});
105-
106-
mapView = (MapView) findViewById(R.id.mapView);
107-
mapView.onCreate(savedInstanceState);
108-
109-
110-
locationEngine = LocationSource.getLocationEngine(this);
111-
112-
navigation = new MapboxNavigation(this, Mapbox.getAccessToken());
113-
114-
mapView.getMapAsync(this);
115115
}
116116

117117
@Override
@@ -136,7 +136,9 @@ public void onMapClick(@NonNull LatLng point) {
136136
destinationMarker = mapboxMap.addMarker(new MarkerOptions().position(point));
137137

138138
startRouteButton.setVisibility(View.VISIBLE);
139-
calculateRoute(Position.fromCoordinates(point.getLongitude(), point.getLatitude()));
139+
140+
this.destination = Position.fromCoordinates(point.getLongitude(), point.getLatitude());
141+
calculateRoute();
140142
}
141143

142144
private void drawRouteLine(DirectionsRoute route) {
@@ -157,22 +159,20 @@ private void drawRouteLine(DirectionsRoute route) {
157159
.width(5f));
158160
}
159161

160-
private void calculateRoute(Position destination) {
162+
private void calculateRoute() {
161163
Location userLocation = mapboxMap.getMyLocation();
162164
if (userLocation == null) {
163165
Timber.d("calculateRoute: User location is null, therefore, origin can't be set.");
164166
return;
165167
}
166168

167-
navigation.setOrigin(Position.fromCoordinates(userLocation.getLongitude(), userLocation.getLatitude()));
168-
navigation.setDestination(destination);
169-
navigation.getRoute(new Callback<DirectionsResponse>() {
169+
Position origin = (Position.fromCoordinates(userLocation.getLongitude(), userLocation.getLatitude()));
170+
navigation.getRoute(origin, destination, new Callback<DirectionsResponse>() {
170171
@Override
171172
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
172173
DirectionsRoute route = response.body().getRoutes().get(0);
173174
NavigationActivity.this.route = route;
174175
drawRouteLine(route);
175-
176176
}
177177

178178
@Override
@@ -197,7 +197,7 @@ public void onRunning(boolean running) {
197197

198198
@Override
199199
public void onProgressChange(Location location, RouteProgress routeProgress) {
200-
Timber.d("onProgressChange: fraction of route traveled: %d", routeProgress.getFractionTraveled());
200+
Timber.d("onProgressChange: fraction of route traveled: %f", routeProgress.getFractionTraveled());
201201
}
202202

203203
@Override
@@ -226,6 +226,27 @@ public void onAlertLevelChange(int alertLevel, RouteProgress routeProgress) {
226226
}
227227
}
228228

229+
@Override
230+
public void userOffRoute(Location location) {
231+
Position newOrigin = Position.fromCoordinates(location.getLongitude(), location.getLatitude());
232+
navigation.updateRoute(newOrigin, destination, new Callback<DirectionsResponse>() {
233+
@Override
234+
public void onResponse(Call<DirectionsResponse> call, Response<DirectionsResponse> response) {
235+
DirectionsRoute route = response.body().getRoutes().get(0);
236+
NavigationActivity.this.route = route;
237+
238+
// Remove old route line from map and draw the new one.
239+
mapboxMap.removePolyline(routeLine);
240+
drawRouteLine(route);
241+
}
242+
243+
@Override
244+
public void onFailure(Call<DirectionsResponse> call, Throwable throwable) {
245+
Timber.e("onFailure: navigation.getRoute()", throwable);
246+
}
247+
});
248+
}
249+
229250
/*
230251
* Activity lifecycle methods
231252
*/
@@ -266,6 +287,15 @@ public void onLowMemory() {
266287
protected void onDestroy() {
267288
super.onDestroy();
268289
mapView.onDestroy();
290+
291+
// Remove all navigation listeners
292+
navigation.removeAlertLevelChangeListener(this);
293+
navigation.removeNavigationEventListener(this);
294+
navigation.removeProgressChangeListener(this);
295+
navigation.removeOffRouteListener(this);
296+
297+
// End the navigation session
298+
navigation.endNavigation();
269299
}
270300

271301
@Override

mapbox/libandroid-services/src/main/java/com/mapbox/services/android/Constants.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,22 @@ public class Constants {
7979
*/
8080
@Experimental public static final int MINIMUM_DISTANCE_FOR_MEDIUM_ALERT = 400;
8181

82+
/**
83+
* Maximum number of meters the user can travel away from step before the
84+
* {@link com.mapbox.services.android.navigation.v5.listeners.OffRouteListener}'s called.
85+
*/
86+
@Experimental public static final double MAXIMUM_DISTANCE_BEFORE_OFF_ROUTE = 50;
87+
88+
/**
89+
* When calculating whether or not the user is on the route, we look where the user will be given their speed and
90+
* this variable.
91+
*/
92+
@Experimental public static final double DEAD_RECKONING_TIME_INTERVAL = 1.0;
93+
94+
/**
95+
* Maximum angle the user puck will be rotated when snapping the user's course to the route line.
96+
*/
97+
@Experimental public static final double MAX_MANIPULATED_COURSE_ANGLE = 25;
98+
8299
}
100+

0 commit comments

Comments
 (0)