GuidesFlutter API ReferencesHERE SDK for Android API referencesHERE SDK for iOS API references
Guides

Update traffic information

Keep your routes up-to-date with the latest traffic conditions. This section explains how to refresh traffic data on existing routes and how to leverage dynamic routing during navigation to find better alternatives when traffic changes.

Update traffic on route

Traffic information for a route can be refreshed by invoking either calculateTrafficOnRoute() or refreshRoute().

  • The refreshRoute() method can be used when updates to the starting point or route metadata are required.
  • In scenarios where only traffic information needs to be updated, the calculateTrafficOnRoute() method can be utilized to provide a TrafficOnRoute object. It contains detailed information on the current traffic flow and incidents per TrafficOnSection. TrafficOnSection contains granular traffic information per span provided as a list of TrafficOnSpan objects.

Note that both methods do not change the route distance and geometry.

Note (only for Navigate)

Alternatively, you can use the DynamicRoutingEngine to find improved routes during navigation. These routes are optimized based on the current traffic flow. As a result, they may also include new route geometry to bypass heavy traffic. For more details about the DynamicRoutingEngine, refer to the Navigation section.

Update traffic during route preview using TrafficOnRoute

The routingEngine.calculateTrafficOnRoute(..) method updates traffic on a specific section or an entire route after it has been created. It allows to calculated this during navigation or in a route preview context.

It does this by recalculating traffic from the last traveled route section, using its index and an offset (in meters) from the last visited position. In a route preview context you can set lastTraveledSectionIndex traveledDistanceOnLastSectionInMeters to 0 in order to update traffic for the entire route.

Here's how the method can be utilized in screens primarily designed for route previews:

public void updateTrafficOnRoute(Route route) {
    // Since traffic is being calculated for the entire route, lastTraveledSectionIndex and traveledDistanceOnLastSectionInMeters are set to 0.
    int lastTraveledSectionIndex = 0;
    int traveledDistanceOnLastSectionInMeters = 0;

    routingEngine.calculateTrafficOnRoute(route, lastTraveledSectionIndex, traveledDistanceOnLastSectionInMeters, new CalculateTrafficOnRouteCallback() {
        @Override
        public void onTrafficOnRouteCalculated(@Nullable RoutingError routingError, @Nullable TrafficOnRoute trafficOnRoute) {
            if (routingError != null) {
                Log.d(TAG, "CalculateTrafficOnRoute error: " + routingError.name());
            } else {
                showUpdatedETA(trafficOnRoute);
            }
        }
    });
}

The updated ETA from TrafficOnRoute is available through TrafficOnSpan. Each TrafficOnSpan provides traffic information along the route. The following method can be used to extract the updated ETA:

private void showUpdatedETA(TrafficOnRoute trafficOnRoute) {
    for (TrafficOnSection section : trafficOnRoute.trafficSections) {
        List<TrafficOnSpan> spans = section.trafficSpans;

        long updatedETAInSeconds = spans.stream()
                .mapToLong(span -> span.duration.getSeconds())
                .sum();

        long updatedTrafficDelayInSeconds = spans.stream()
                .mapToLong(span -> span.trafficDelay.getSeconds())
                .sum();

        String updatedETAString = String.format("Updated ETA %s\nUpdated traffic delay %s",
                timeUtils.formatTime(updatedETAInSeconds),
                timeUtils.formatTime(updatedTrafficDelayInSeconds));
        showDialog("Updated traffic", updatedETAString);
    }
}

Note

Traffic updates use predictive models to forecast conditions along your route, which may differ from real-time traffic shown on map layers. For details on these differences, see Real-time versus predictive traffic data sources.

Update traffic during turn-by-turn navigation (only for HERE SDK for Navigate)

During turn-by-turn navigation, it is recommended to calculate a dedicated TrafficOnRoute object by calling calculateTrafficOnRoute(). Since the traffic situation can change frequently while being on a trip, an application should repeat this call periodically.

The example implementation provided below ensures that traffic updates are performed at an configurable interval.

Upon completion of calculateTrafficOnRoute(), the VisualNavigator can be updated with the new TrafficOnRoute object, which adjusts the information on the duration provided by the RouteProgress object (only for HERE SDK for Navigate).

public void updateTrafficOnRoute(RouteProgress routeProgress, VisualNavigator visualNavigator) {
    Route currentRoute = visualNavigator.getRoute();
    if (currentRoute == null) {
        // Should never happen.
        return;
    }

    // Below, we use 10 minutes. A common range is between 5 and 15 minutes.
    long trafficUpdateIntervalInMilliseconds = 10 * 60000; // 10 minutes.
    long now = System.currentTimeMillis();
    if ((now - lastTrafficUpdateInMilliseconds) < trafficUpdateIntervalInMilliseconds) {
        return;
    }
    // Store the current time when we update trafficOnRoute.
    lastTrafficUpdateInMilliseconds = now;

    List<SectionProgress> sectionProgressList = routeProgress.sectionProgress;
    SectionProgress lastSectionProgress = sectionProgressList.get(sectionProgressList.size() - 1);
    int traveledDistanceOnLastSectionInMeters = currentRoute.getLengthInMeters() - lastSectionProgress.remainingDistanceInMeters;
    int lastTraveledSectionIndex = routeProgress.routeMatchedLocation.sectionIndex;

    routingEngine.calculateTrafficOnRoute(currentRoute, lastTraveledSectionIndex, traveledDistanceOnLastSectionInMeters, new CalculateTrafficOnRouteCallback() {
        @Override
        public void onTrafficOnRouteCalculated(@Nullable RoutingError routingError, @Nullable TrafficOnRoute trafficOnRoute) {
            if (routingError != null) {
                Log.d(TAG, "CalculateTrafficOnRoute error: " + routingError.name());
                return;
            }

            // Sets traffic data for the current route, affecting RouteProgress duration in SectionProgress,
            // while preserving route distance and geometry.
            visualNavigator.setTrafficOnRoute(trafficOnRoute);
            Log.d(TAG, "Updated traffic on route.");
        }
    });
}

Note

This code initiates periodic calls to the HERE Routing backend. Depending on your contract, each call may be charged separately. It is the application's responsibility to decide how and how often this code should be executed.

The visualNavigator.setTrafficOnRoute() method does not take effect immediately. Instead, the updated travel duration (ETA) is reflected in the next RouteProgress event. For details on extracting the ETA from a RouteProgress event, see the ETA section.