HERE Android SDK Developer's Guide

Car and Pedestrian Routing

The HERE Android SDK supports route calculation with multiple waypoints, optimized for walking or driving. A route describes a path between at least two waypoints, the starting point and the destination, with optional intermediate waypoints in between. Applications can provide route information to users in two ways:

  • A line rendered on a map that displays a connecting path between all waypoints
  • Turn-by-turn directions in text format

Routing Example on GitHub

You can find an example that demonstrates this feature at https://github.com/heremaps/.

Route Calculation Classes

This section introduces the following classes that are used for route calculations:
  • CoreRouter
  • RoutePlan
  • RouteWaypoint
  • RouteOptions

The CoreRouter class is responsible for calculating car, pedestrian, and truck routes. An application can initiate a route calculation by calling the CoreRouter.calculateRoute(RoutePlan, CoreRouter.Listener) method, providing options and waypoints through RoutePlan, and receive progress events through the Router.Listener instance.

Note: The CoreRouter can also calculate routes with traffic taken into account by using Route.TrafficPenaltyMode and setDynamicPenalty(DynamicPenalty) before calling calculateRoute(). For more information on the DynamicPenalty class, see Dynamic Routing Penalty.

RoutePlan is a waypoint container that is used for route calculation. A RoutePlan object is comprised of a list of waypoint objects and an optional RouteOptions. If RouteOptions is not specified, default values are used.

You can use RouteWaypoint to add more waypoint details to a route calculation. These details include whether a waypoint is a deliberate stopover or a via point that the route must pass through. This affects routing, as routes containing stopovers or via waypoints may be different. For example, a calculated route may suggest a U-turn maneuver after a stopover, while a route containing the same location as a via waypoint suggests continuing on the same street. The via waypoint type is only supported in car routes, and it is not supported in other route types.

The RouteOptions class is a model of the parameters required to calculate one route. It encapsulates "building block" parameters for a route such as:

  • The desired number of routes
  • The direction of travel that the route should start in
  • The routing type, such as fastest travel time or shortest distance
  • The departure time
  • The allowed types of route segments, such as dirt roads or highways
Note: Routing type describes different optimizations that can be applied during the route calculation:
  • Fastest - route calculation from start to destination optimized by travel time. In some cases, the route returned by the fastest mode may not be the route with the shortest possible travel time. For example, it may favor a route that remains on a highway, even if a shorter travel time can be achieved by taking a detour or shortcut through a side road.
  • Shortest - route calculation from start to destination disregarding any speed information. In this mode, the distance of the route is minimized, while keeping the route sensible. This includes, for example, penalizing turns. Because of that, the resulting route will not necessarily be the one with minimal distance.
  • Balanced - route calculation from start to destination optimizing based on combination of travel time and distance.

The HERE SDK supports alternate routes between two waypoints. The alternate route feature allows more than one route to be returned after a route calculation. You can use the RouteOptions class to set the desired number of routes, and the HERE SDK then returns different routes according to this limit. Note that the first element of the returned list of RouteResult is the main route, and the rest of the returned routes are not listed in any specific order.

Note: Do not set more than three desired routes in offline mode, as these route calculations take significantly more time to complete.
Note: In some cases, specifying a higher route count than a previous working query can result in a GRAPH_DISCONNECTED error. This is due to a limit on the complexity and size of the calculated routes that can be processed. The higher the route count and the more complex a route is, the more likely that this limit is exceeded.

RouteResult and Route

The RouteResult class represents a route calculation result. Applications can retrieve a Route object and the corresponding set of violated routing conditions. Violated routing options are the conditions that a routing result was unable to adhere to. For example, after specifying a route calculation that avoids tolls and ferries, you may get a RouteResult that contains a Route object along with RouteResult.ViolatedOption.AVOID_TOLL_ROADS. This indicates that although a route was found, this route goes through at least one toll road—violating a condition of your route request.

The Route class is a distinct calculated path connecting two or more waypoints, consisting of a list of maneuvers and route links. By using CoreRouter.calculateRoute(RoutePlan, CoreRouter.Listener) to trigger a route calculation, your application can use the CoreRouter.Listener to monitor the calculation and trigger callback methods. These callback methods have parameters that include a list of the calculated RouteResult objects. Using these RouteResult objects, you can call getRoute() to retrieve the routes.

The Route class also provides the getTtaIncludingTraffic and the getTtaUsingDownloadedTraffic methods which provide a different set of RouteTta results that take traffic into account. If the route was originally calculated with setting a traffic penalty mode, the getTtaIncludingTraffic method will return the estimated time to arrival with traffic conditions at the time of the route calculation. The value is calculated once at the time of the route calculation and does not change with time. The getTtaUsingDownloadedTraffic should be used in cases where the time elapsed since a route was returned is large enough to make the time to arrival (as obtained using getTtaIncludingTraffic), no longer accurate given changing traffic conditions. This method will provide a more up-to-date time to arrival estimate provided traffic data is first downloaded for the route using the TrafficUpdater class.

The MapRoute map object

The MapRoute class is a type of MapObject that displays a calculated route on a map. Typically, an application creates a MapRoute after a route calculation, passing the relevant Route object as a parameter to the MapRoute(Route) constructor before adding the MapRoute to the map by calling Map.addMapObject(MapRoute).

You can customize map route colors by using RenderType and MapRoute APIs. There are three supported render type values: PRIMARY, SECONDARY, and USER_DEFINED. By default, a MapRoute is set to the Primary set of pre-defined colors, and the secondary render type is designed to denote alternate routes. By using RenderType.USER_DEFINED, you can call setColor(int) and setTraveledColor(int) and set the route colors to any ARGB color.

Figure 1. Using Primary RenderType
Figure 2. Using Secondary RenderType
Figure 3. User-Defined Route Color
Note: MapRoute.setRenderType(RenderType) can only be called after the MapRoute is added to a Map.
Figure 4. Calculate Route

For example, if you want to render a route that connects two waypoints (start and destination), you can add the following application logic:

  1. Declare a CoreRouter instance.
    // Declare the variable (the CoreRouter)
    CoreRouter router = new CoreRouter();
    
  2. Create a RoutePlan and add two GeoCoordinate waypoints.
    // Create the RoutePlan and add two waypoints
    RoutePlan routePlan = new RoutePlan();
    routePlan.addWaypoint(new RouteWaypoint(new GeoCoordinate(49.1966286, -123.0053635)));
    routePlan.addWaypoint(new RouteWaypoint(new GeoCoordinate(49.1947289, -123.1762924)));
    
  3. Create a new RouteOptions object, set its Type and TransportMode values by calling appropriate RouteOptions methods, and then add it to RoutePlan.
    // Create the RouteOptions and set its transport mode & routing type
    RouteOptions routeOptions = new RouteOptions();
    routeOptions.setTransportMode(RouteOptions.TransportMode.CAR);
    routeOptions.setRouteType(RouteOptions.Type.FASTEST);
    
    routePlan.setRouteOptions(routeOptions);
    
  4. To make sure route calculation can handle returning a Route object that in turn can be used to create a MapRoute instance for rendering on the map, add an inner class by implementing CoreRouter.Listener in the appropriate activity class.
    private class RouteListener implements CoreRouter.Listener {
    
      // Method defined in Listener
      public void onProgress(int percentage) {
        // Display a message indicating calculation progress
      }
    
      // Method defined in Listener
      public void onCalculateRouteFinished(List<RouteResult> routeResult, RoutingError error) {
        // If the route was calculated successfully
        if (error == RoutingError.NONE) {
          // Render the route on the map
          mapRoute = new MapRoute(routeResult.get(0).getRoute());
          map.addMapObject(mapRoute);
        }
        else {
          // Display a message indicating route calculation failure
        }
      }
    }
  5. After adding the inner listener class (named RouteListener for this example), calculate the route by calling CoreRouter.calculateRoute(RoutePlan, CoreRouter.Listener). Note that CoreRouter.Listener extends Router.Listener<List<RouteResult>, RoutingError>.
    // Calculate the route
    router.calculateRoute(routePlan, new RouteListener());
    

Dynamic Routing Penalty

You can use DynamicPenalty to create a policy of roads and area restriction factors that are applied during routing calculations. For example, you can use this class to indicate that the travel speed in an area is 50 percent slower than usual. The DynamicPenalty class also allows you to set the mode used for handling traffic events in a route calculation through the setTrafficPenaltyMode(TrafficPenaltyMode) method.

You can change the active policy by calling CoreRouter.setDynamicPenalty(DynamicPenalty). The policy must be set before a route calculation for the restrictions to be taken into account.

Retrieving Traffic Event Objects

You can use the TrafficUpdater class to retrieve traffic events such as road closures or congestions. Before using the traffic updater, it must be be enabled via TrafficUpdater.enableUpdate(boolean update) for the traffic requests to take effect.

Using the TrafficUpdater is a two-step process. First, create a TrafficUpdater.Listener and use it with one of the following methods:
  • request(GeoCoordinate center, Listener listener) - request traffic with given center coordinates and the default radius
  • request(GeoCoordinate center, int radius, Listener listener) - request traffic with given center coordinates and radius
  • request(Route route, Listener listener) - request traffic for the given route and default radius around each waypoint
  • request(Route route, int radius, Listener listener) - request traffic for given route and radius around each waypoint
  • request(RouteElements elements, Listener listener) - request traffic for a route element (RouteElement) object
Upon the successful callback from TrafficUpdater.Listener (with the state TrafficUpdater.RequestState.DONE), you should retrieve a list of traffic events that affect the given route or route element by using one of the following methods:
  • getEvents(Route route, GetEventsListener listener)
  • getEvents(RouteElement element, GetEventsListener listener)
  • getEvents(List<RouteElement> elements, GetEventsListener listener)
  • getEvents(RouteElements elements, GetEventsListener listener)

TrafficUpdater.GetEventsListener contains one callback method, onComplete(List<TrafficEvent> events, Error error), which provides a newly updated list of traffic events.

Routing-related Enumerations

Route calculations make use of HERE SDK enumerations that include:

  • The Route.TrafficPenaltyMode enum - represents values describing how the CoreRouter should handle traffic events in a route calculation, such as DISABLED, AVOID_LONG_TERM_CLOSURES, or OPTIMAL.
  • The RouteOptions.Type enum - represents values describing different routing types, such as FASTEST or SHORTEST
  • The RouteOptions.TransportMode enum - represents values describing different transport modes, such as CAR, TRUCK, TRACK (which connects waypoints using straight lines), or PEDESTRIAN
  • The RoutingError enum - represents values describing possible route calculation errors, such as NONE or VIOLATES_OPTIONS
  • The RouteResult.ViolatedOption enum - represents values describing possible route option violations, such as AVOID_HIGHWAYS or AVOID_FERRIES