Skip to content

Commit

Permalink
Merge pull request #122 from mapbox/dan-custom-instruction
Browse files Browse the repository at this point in the history
Custom Instructions for Milestones
  • Loading branch information
danesfeder authored Jul 13, 2017
2 parents cda87aa + 799262a commit ebc743c
Show file tree
Hide file tree
Showing 8 changed files with 179 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.mapbox.services.android.navigation.ui.v5.NavigationMapRoute;
import com.mapbox.services.android.navigation.v5.MapboxNavigation;
import com.mapbox.services.android.navigation.v5.NavigationConstants;
import com.mapbox.services.android.navigation.v5.instruction.Instruction;
import com.mapbox.services.android.navigation.v5.listeners.NavigationEventListener;
import com.mapbox.services.android.navigation.v5.milestone.MilestoneEventListener;
import com.mapbox.services.android.navigation.v5.milestone.RouteMilestone;
Expand Down Expand Up @@ -91,6 +92,7 @@ protected void onCreate(Bundle savedInstanceState) {

navigation.addMilestone(new RouteMilestone.Builder()
.setIdentifier(BEGIN_ROUTE_MILESTONE)
.setInstruction(new BeginRouteInstruction())
.setTrigger(
Trigger.all(
Trigger.lt(TriggerProperty.STEP_INDEX, 3),
Expand Down Expand Up @@ -326,4 +328,12 @@ protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}

private class BeginRouteInstruction extends Instruction {

@Override
public String buildInstruction(RouteProgress routeProgress) {
return "Have a safe trip!";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

import com.mapbox.services.Experimental;
import com.mapbox.services.android.location.LostLocationEngine;
import com.mapbox.services.android.navigation.v5.instruction.Instruction;
import com.mapbox.services.android.navigation.v5.instruction.DefaultInstructionEngine;
import com.mapbox.services.android.navigation.v5.listeners.NavigationEventListener;
import com.mapbox.services.android.navigation.v5.offroute.OffRouteListener;
import com.mapbox.services.android.navigation.v5.routeprogress.ProgressChangeListener;
Expand Down Expand Up @@ -105,12 +107,16 @@ public MapboxNavigation(@NonNull Context context, @NonNull String accessToken,
offRouteListeners = new CopyOnWriteArrayList<>();
milestoneEventListeners = new CopyOnWriteArrayList<>();
milestones = new CopyOnWriteArrayList<>();
addDefaultMilestones();

if (options.defaultMilestonesEnabled()) {
addDefaultMilestones();
}
}

private void addDefaultMilestones() {
addMilestone(new StepMilestone.Builder()
.setIdentifier(NavigationConstants.URGENT_MILESTONE)
.setInstruction(new UrgentInstruction())
.setTrigger(
Trigger.all(
Trigger.gt(TriggerProperty.STEP_DISTANCE_TOTAL_METERS, 100d),
Expand All @@ -124,6 +130,7 @@ private void addDefaultMilestones() {

addMilestone(new StepMilestone.Builder()
.setIdentifier(NavigationConstants.IMMINENT_MILESTONE)
.setInstruction(new ImminentInstruction())
.setTrigger(
Trigger.all(
Trigger.gt(TriggerProperty.STEP_DISTANCE_TOTAL_METERS, 400d),
Expand All @@ -136,6 +143,7 @@ private void addDefaultMilestones() {

addMilestone(new StepMilestone.Builder()
.setIdentifier(NavigationConstants.NEW_STEP_MILESTONE)
.setInstruction(new NewStepInstruction())
.setTrigger(
Trigger.all(
Trigger.neq(TriggerProperty.NEW_STEP, TriggerProperty.FALSE),
Expand All @@ -146,6 +154,7 @@ private void addDefaultMilestones() {

addMilestone(new StepMilestone.Builder()
.setIdentifier(NavigationConstants.DEPARTURE_MILESTONE)
.setInstruction(new DepartureInstruction())
.setTrigger(
Trigger.all(
Trigger.eq(TriggerProperty.FIRST_STEP, TriggerProperty.TRUE),
Expand All @@ -155,6 +164,7 @@ private void addDefaultMilestones() {

addMilestone(new StepMilestone.Builder()
.setIdentifier(NavigationConstants.ARRIVAL_MILESTONE)
.setInstruction(new ArrivalInstruction())
.setTrigger(
Trigger.all(
Trigger.eq(TriggerProperty.LAST_STEP, TriggerProperty.TRUE),
Expand All @@ -163,6 +173,82 @@ private void addDefaultMilestones() {
).build());
}

/**
* Used to provide the {@link String} instruction in
* {@link MilestoneEventListener#onMilestoneEvent(RouteProgress, String, int)}
* for Arrival Milestones
*
* @since 0.4.0
*/
private class ArrivalInstruction extends Instruction {

@Override
public String buildInstruction(RouteProgress routeProgress) {
return DefaultInstructionEngine.createInstruction(routeProgress, NavigationConstants.ARRIVAL_MILESTONE);
}
}

/**
* Used to provide the {@link String} instruction in
* {@link MilestoneEventListener#onMilestoneEvent(RouteProgress, String, int)}
* for Departure Milestones
*
* @since 0.4.0
*/
private class DepartureInstruction extends Instruction {

@Override
public String buildInstruction(RouteProgress routeProgress) {
return DefaultInstructionEngine.createInstruction(routeProgress, NavigationConstants.DEPARTURE_MILESTONE);
}
}

/**
* Used to provide the {@link String} instruction in
* {@link MilestoneEventListener#onMilestoneEvent(RouteProgress, String, int)}
* for Imminent Milestones
*
* @since 0.4.0
*/
private class ImminentInstruction extends Instruction {

@Override
public String buildInstruction(RouteProgress routeProgress) {
return DefaultInstructionEngine.createInstruction(routeProgress, NavigationConstants.IMMINENT_MILESTONE);
}
}

/**
* Used to provide the {@link String} instruction in
* {@link MilestoneEventListener#onMilestoneEvent(RouteProgress, String, int)}
* for New Step Milestones
*
* @since 0.4.0
*/
private class NewStepInstruction extends Instruction {

@Override
public String buildInstruction(RouteProgress routeProgress) {
return DefaultInstructionEngine.createInstruction(routeProgress, NavigationConstants.NEW_STEP_MILESTONE);
}
}

/**
* Used to provide the {@link String} instruction in
* {@link MilestoneEventListener#onMilestoneEvent(RouteProgress, String, int)}
* for Urgent Milestones
*
* @since 0.4.0
*/
private class UrgentInstruction extends Instruction {

@Override
public String buildInstruction(RouteProgress routeProgress) {
return DefaultInstructionEngine.createInstruction(routeProgress, NavigationConstants.URGENT_MILESTONE);
}

}

@Override
public void onMilestoneEvent(RouteProgress routeProgress, String instruction, int identifier) {
if (identifier == NavigationConstants.ARRIVAL_MILESTONE) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class MapboxNavigationOptions {
private double userLocationSnapDistance;
private int secondsBeforeReroute;

private boolean defaultMilestonesEnabled = true;

@NavigationProfiles.Profile
private String profile;

Expand Down Expand Up @@ -113,6 +115,16 @@ public MapboxNavigationOptions setMaxManipulatedCourseAngle(
return this;
}

/**
* Will create a set of pre-defined Milestones for basic updates while navigating along a route.
*
* @param enabled - will create default milestones (default)
* @since 0.4.0
*/
public void setDefaultMilestonesEnabled(boolean enabled) {
this.defaultMilestonesEnabled = enabled;
}

/*
* Getters
*/
Expand Down Expand Up @@ -187,6 +199,10 @@ public double getUserLocationSnapDistance() {
return userLocationSnapDistance;
}

public boolean defaultMilestonesEnabled() {
return defaultMilestonesEnabled;
}

/**
* set the distance the user must stay within for snapping to route to occur.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@
import android.text.TextUtils;

import com.mapbox.services.Constants;
import com.mapbox.services.android.navigation.v5.instruction.DefaultInstruction;
import com.mapbox.services.android.navigation.v5.instruction.Instruction;
import com.mapbox.services.android.navigation.v5.milestone.Milestone;
import com.mapbox.services.android.navigation.v5.milestone.MilestoneEventListener;
import com.mapbox.services.android.navigation.v5.offroute.OffRoute;
Expand Down Expand Up @@ -103,9 +101,8 @@ && calculateSnappedDistanceToNextStep(location, previousRouteProgress) < options
for (Milestone milestone : milestones) {
if (milestone.isOccurring(previousRouteProgress, routeProgress)) {
for (MilestoneEventListener listener : milestoneEventListeners) {
// Create a new DefaultInstruction based on the current RouteProgress and Milestone identifier
Instruction instruction = new DefaultInstruction(routeProgress, milestone.getIdentifier());
listener.onMilestoneEvent(routeProgress, instruction.getInstruction(), milestone.getIdentifier());
String instruction = buildInstructionString(routeProgress, milestone);
listener.onMilestoneEvent(routeProgress, instruction, milestone.getIdentifier());
}
}
}
Expand All @@ -126,6 +123,15 @@ && calculateSnappedDistanceToNextStep(location, previousRouteProgress) < options
previousRouteProgress = routeProgress;
}

private String buildInstructionString(RouteProgress routeProgress, Milestone milestone) {
if (milestone.getInstruction() != null) {
// Create a new custom instruction based on the Instruction packaged with the Milestone
return milestone.getInstruction().buildInstruction(routeProgress);
} else {
return "";
}
}

private void notifyOffRouteChange(boolean isUserOffRoute, Location location) {
// Only report user off route once.

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*
* @since 0.4.0
*/
class DefaultInstructionEngine extends SparseArray<DefaultInstructionEngine.InstructionBuilder> {
public class DefaultInstructionEngine extends SparseArray<DefaultInstructionEngine.InstructionBuilder> {

private static final double MINIMUM_UPCOMING_STEP_DISTANCE = 15d;
private static final String DECIMAL_FORMAT = "###.#";
Expand All @@ -27,12 +27,32 @@ class DefaultInstructionEngine extends SparseArray<DefaultInstructionEngine.Inst
private static final String THEN_STRING_FORMAT = "%s then %s";
private static final String THEN_IN_STRING_FORMAT = "%s then in %s %s";
private static final String CONTINUE_STRING_FORMAT = "Continue on %s for %s";
private static final String EMPTY_STRING = "";

DefaultInstructionEngine() {
private DefaultInstructionEngine() {
super(5);
initDefaultBuilders();
}

/**
* Provides the {@link RouteProgress} and milestone identifier to the {@link DefaultInstructionEngine}
* which returns the appropriate instruction. Will return an empty {@link String} if the
* milestone identifier provided is not one of the default identifiers
*
* @param routeProgress for current route data / distance
* @param identifier for what type of instruction we want to build
* @return {@link String} instruction that has been created by the engine
* @since 0.4.0
*/
public static String createInstruction(RouteProgress routeProgress, int identifier) {
DefaultInstructionEngine defaultInstructionEngine = new DefaultInstructionEngine();
if (defaultInstructionEngine.get(identifier) != null) {
return defaultInstructionEngine.get(identifier).build(routeProgress);
} else {
return EMPTY_STRING;
}
}

private void initDefaultBuilders() {
this.put(NavigationConstants.DEPARTURE_MILESTONE, new InstructionBuilder() {
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.mapbox.services.android.navigation.v5.instruction;

import com.mapbox.services.android.navigation.v5.routeprogress.RouteProgress;

/**
* Base Instruction. Subclassed to provide concrete instructions.
*
Expand All @@ -13,5 +15,5 @@ public abstract class Instruction {
* @return {@link String} instruction that will be voiced on the client
* @since 0.4.0
*/
public abstract String getInstruction();
public abstract String buildInstruction(RouteProgress routeProgress);
}
Loading

0 comments on commit ebc743c

Please sign in to comment.