Skip to content

Commit

Permalink
Add LocationEngineRequest APIs for MapboxNavigation
Browse files Browse the repository at this point in the history
  • Loading branch information
danesfeder committed Jan 8, 2019
1 parent 40b7d47 commit c687ea0
Show file tree
Hide file tree
Showing 5 changed files with 251 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,60 +9,79 @@
import com.mapbox.android.core.location.LocationEngineRequest;
import com.mapbox.android.core.location.LocationEngineResult;

import java.lang.ref.WeakReference;

import timber.log.Timber;

class LocationUpdater implements LocationEngineCallback<LocationEngineResult> {
class LocationUpdater {

private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 500;
private final LocationEngineCallback<LocationEngineResult> callback = new CurrentLocationEngineCallback(this);
private final RouteProcessorBackgroundThread thread;
private LocationEngine locationEngine;
private LocationEngineRequest request;

@SuppressLint("MissingPermission")
LocationUpdater(RouteProcessorBackgroundThread thread, LocationEngine locationEngine) {
LocationUpdater(RouteProcessorBackgroundThread thread, LocationEngine locationEngine,
LocationEngineRequest request) {
this.thread = thread;
this.locationEngine = locationEngine;
this.request = request;
requestInitialLocationUpdates(locationEngine, request);
}

LocationEngineRequest request = buildEngineRequest();
locationEngine.getLastLocation(this);
locationEngine.requestLocationUpdates(request, this, thread.getLooper());
void updateLocationEngine(LocationEngine locationEngine) {
requestLocationUpdates(request, locationEngine);
this.locationEngine = locationEngine;
}

@Override
public void onSuccess(LocationEngineResult result) {
Location location = result.getLastLocation();
onLocationChanged(location);
void updateLocationEngineRequest(LocationEngineRequest request) {
requestLocationUpdates(request, locationEngine);
this.request = request;
}

@Override
public void onFailure(@NonNull Exception exception) {
Timber.e(exception);
void onLocationChanged(Location location) {
if (location != null) {
thread.updateLocation(location);
NavigationTelemetry.getInstance().updateLocation(location);
}
}

void removeLocationUpdates() {
locationEngine.removeLocationUpdates(this);
locationEngine.removeLocationUpdates(callback);
}

@SuppressLint("MissingPermission")
void updateLocationEngine(LocationEngine locationEngine) {
this.locationEngine.removeLocationUpdates(this);
LocationEngineRequest request = buildEngineRequest();
locationEngine.requestLocationUpdates(request, this, thread.getLooper());
this.locationEngine = locationEngine;
private void requestInitialLocationUpdates(LocationEngine locationEngine, LocationEngineRequest request) {
locationEngine.getLastLocation(callback);
locationEngine.requestLocationUpdates(request, callback, null);
}

@NonNull
private LocationEngineRequest buildEngineRequest() {
return new LocationEngineRequest.Builder(UPDATE_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS)
.build();
@SuppressLint("MissingPermission")
private void requestLocationUpdates(LocationEngineRequest request, LocationEngine locationEngine) {
this.locationEngine.removeLocationUpdates(callback);
locationEngine.requestLocationUpdates(request, callback, null);
}

private void onLocationChanged(Location location) {
if (location != null) {
thread.updateLocation(location);
NavigationTelemetry.getInstance().updateLocation(location);
static class CurrentLocationEngineCallback implements LocationEngineCallback<LocationEngineResult> {

private final WeakReference<LocationUpdater> updaterWeakReference;

CurrentLocationEngineCallback(LocationUpdater locationUpdater) {
this.updaterWeakReference = new WeakReference<>(locationUpdater);
}

@Override
public void onSuccess(LocationEngineResult result) {
LocationUpdater locationUpdater = updaterWeakReference.get();
if (locationUpdater != null) {
Location location = result.getLastLocation();
locationUpdater.onLocationChanged(location);
}
}

@Override
public void onFailure(@NonNull Exception exception) {
Timber.e(exception);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.android.core.location.LocationEngineRequest;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.navigator.Navigator;
import com.mapbox.services.android.navigation.v5.milestone.BannerInstructionMilestone;
Expand Down Expand Up @@ -50,6 +51,8 @@
*/
public class MapboxNavigation implements ServiceConnection {

private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 1000;
private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 500;
private NavigationEventDispatcher navigationEventDispatcher;
private NavigationEngineFactory navigationEngineFactory;
private NavigationTelemetry navigationTelemetry = null;
Expand All @@ -58,6 +61,7 @@ public class MapboxNavigation implements ServiceConnection {
private DirectionsRoute directionsRoute;
private MapboxNavigationOptions options;
private LocationEngine locationEngine = null;
private LocationEngineRequest locationEngineRequest = null;
private Set<Milestone> milestones;
private final String accessToken;
private Context applicationContext;
Expand Down Expand Up @@ -253,29 +257,18 @@ public void removeMilestone(int milestoneIdentifier) {

/**
* Navigation needs an instance of location engine in order to acquire user location information
* and handle events based off of the current information. By default, a LOST location engine is
* created with the optimal navigation settings. Passing in a custom location engine using this
* API assumes you have set it to the ideal parameters which are specified below.
* and handle events based off of the current information. By default, a {@link LocationEngine} is
* created using {@link LocationEngineProvider#getBestLocationEngine(Context)}.
* <p>
* Although it is not required to set your location engine to these parameters, these values are
* what we found works best. Note that this also depends on which underlying location service you
* are using. Reference the corresponding location service documentation for more information and
* way's you could improve the performance.
* </p><p>
* An ideal conditions, the Navigation SDK will receive location updates once every second with
* In ideal conditions, the Navigation SDK will receive location updates once every second with
* mild to high horizontal accuracy. The location update must also contain all information an
* Android location object would expect including bearing, speed, timestamp, and
* latitude/longitude.
* </p><p>
* Listed below are the ideal conditions for both a LOST location engine and a Google Play
* Services Location engine.
* </p><p><ul>
* <li>Set the location priority to {@code HIGH_ACCURACY}.</li>
* <li>The fastest interval should be set around 1 second (1000ms). Note that the interval isn't
* a guaranteed to match this value exactly and is only an estimate.</li>
* <li>Setting the location engine interval to 0 will result in location updates occurring as
* quickly as possible within the fastest interval limit placed on it.</li>
* </ul>
* </p>
* <p>
* This method can be called during an active navigation session. The active {@link LocationEngine} will be
* replaced and the new one (passed via this method) will be activated with the current {@link LocationEngineRequest}.
* </p>
*
* @param locationEngine a {@link LocationEngine} used for the navigation session
* @since 0.1.0
Expand Down Expand Up @@ -305,6 +298,41 @@ public LocationEngine getLocationEngine() {
return locationEngine;
}

/**
* This method updates the {@link LocationEngineRequest} that is used with the {@link LocationEngine}.
* <p>
* If a request is not provided via {@link MapboxNavigation#setLocationEngineRequest(LocationEngineRequest)},
* a default will be provided with optimized settings for navigation.
* </p>
* <p>
* This method can be called during an active navigation session. The active {@link LocationEngineRequest} will be
* replaced and the new one (passed via this method) will be activated with the current {@link LocationEngine}.
* </p>
*
* @param locationEngineRequest to be used with the current {@link LocationEngine}
*/
public void setLocationEngineRequest(@NonNull LocationEngineRequest locationEngineRequest) {
this.locationEngineRequest = locationEngineRequest;

if (isServiceAvailable()) {
navigationService.updateLocationEngineRequest(locationEngineRequest);
}
}

/**
* Returns the current {@link LocationEngineRequest} either being used or going to be used
* by the SDK for {@link android.location.Location} updates.
* <p>
* If a request is not provided via {@link MapboxNavigation#setLocationEngineRequest(LocationEngineRequest)},
* a default will be provided with optimized settings for navigation.
*
* @return the current {@link LocationEngineRequest} used by the SDK
*/
@NonNull
public LocationEngineRequest getLocationEngineRequest() {
return locationEngineRequest;
}

/**
* Calling This begins a new navigation session using the provided directions route. this API is
* also intended to be used when a reroute occurs passing in the updated directions route.
Expand Down Expand Up @@ -709,7 +737,7 @@ public void cancelFeedback(String feedbackId) {
/**
* Use this method to update the leg index of the current {@link DirectionsRoute}
* being traveled along.
*
* <p>
* An index passed here that is not valid will be ignored. Please note, the leg index
* will automatically increment by default. To disable this,
* use {@link MapboxNavigationOptions#enableAutoIncrementLegIndex()}.
Expand Down Expand Up @@ -785,7 +813,8 @@ private void initializeForTest() {
// Initialize event dispatcher and add internal listeners
navigationEventDispatcher = new NavigationEventDispatcher();
navigationEngineFactory = new NavigationEngineFactory();
initializeDefaultLocationEngine();
locationEngine = obtainLocationEngine();
locationEngineRequest = obtainLocationEngineRequest();
initializeTelemetry();

// Create and add default milestones if enabled.
Expand All @@ -806,7 +835,8 @@ private void initialize() {
mapboxNavigator = new MapboxNavigator(new Navigator());
navigationEventDispatcher = new NavigationEventDispatcher();
navigationEngineFactory = new NavigationEngineFactory();
initializeDefaultLocationEngine();
locationEngine = obtainLocationEngine();
locationEngineRequest = obtainLocationEngineRequest();
initializeTelemetry();

// Create and add default milestones if enabled.
Expand Down Expand Up @@ -836,14 +866,7 @@ private NavigationTelemetry obtainTelemetry() {
return navigationTelemetry;
}

/**
* Since navigation requires location information there should always be a valid location engine
* which we can use to get information. Therefore, by default we build one.
*/
private void initializeDefaultLocationEngine() {
locationEngine = obtainLocationEngine();
}

@NonNull
private LocationEngine obtainLocationEngine() {
if (locationEngine == null) {
return LocationEngineProvider.getBestLocationEngine(applicationContext);
Expand All @@ -852,6 +875,18 @@ private LocationEngine obtainLocationEngine() {
return locationEngine;
}

@NonNull
private LocationEngineRequest obtainLocationEngineRequest() {
if (locationEngineRequest == null) {
return new LocationEngineRequest.Builder(UPDATE_INTERVAL_IN_MILLISECONDS)
.setPriority(LocationEngineRequest.PRIORITY_HIGH_ACCURACY)
.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS)
.build();
}

return locationEngineRequest;
}

private void startNavigationWith(@NonNull DirectionsRoute directionsRoute) {
ValidationUtils.validDirectionsRoute(directionsRoute, options.defaultMilestonesEnabled());
this.directionsRoute = directionsRoute;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import android.support.annotation.Nullable;

import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.core.location.LocationEngineRequest;
import com.mapbox.api.directions.v5.models.DirectionsRoute;
import com.mapbox.services.android.navigation.v5.navigation.notification.NavigationNotification;
import com.mapbox.services.android.navigation.v5.route.FasterRoute;
Expand Down Expand Up @@ -76,23 +77,21 @@ void endNavigation() {
thread.quit();
}

/**
* Called with {@link MapboxNavigation#setLocationEngine(LocationEngine)}.
* Updates this service with the new {@link LocationEngine}.
*
* @param locationEngine to update the provider
*/
void updateLocationEngine(LocationEngine locationEngine) {
locationUpdater.updateLocationEngine(locationEngine);
}

void updateLocationEngineRequest(LocationEngineRequest request) {
locationUpdater.updateLocationEngineRequest(request);
}

private void initialize(MapboxNavigation mapboxNavigation) {
NavigationEventDispatcher dispatcher = mapboxNavigation.getEventDispatcher();
String accessToken = mapboxNavigation.obtainAccessToken();
initializeRouteFetcher(dispatcher, accessToken, mapboxNavigation.retrieveEngineFactory());
initializeNotificationProvider(mapboxNavigation);
initializeRouteProcessorThread(mapboxNavigation, dispatcher, routeFetcher, notificationProvider);
initializeLocationProvider(mapboxNavigation);
initializeLocationUpdater(mapboxNavigation);
}

private void initializeRouteFetcher(NavigationEventDispatcher dispatcher, String accessToken,
Expand All @@ -117,9 +116,10 @@ private void initializeRouteProcessorThread(MapboxNavigation mapboxNavigation,
thread = new RouteProcessorBackgroundThread(mapboxNavigation, new Handler(), listener);
}

private void initializeLocationProvider(MapboxNavigation mapboxNavigation) {
private void initializeLocationUpdater(MapboxNavigation mapboxNavigation) {
LocationEngine locationEngine = mapboxNavigation.getLocationEngine();
locationUpdater = new LocationUpdater(thread, locationEngine);
LocationEngineRequest locationEngineRequest = mapboxNavigation.getLocationEngineRequest();
locationUpdater = new LocationUpdater(thread, locationEngine, locationEngineRequest);
}

private void startForegroundNotification(NavigationNotification navigationNotification) {
Expand Down
Loading

0 comments on commit c687ea0

Please sign in to comment.