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 applicable 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:

func updateTrafficOnRoute(route: Route?) {
    // Since traffic is being calculated for the entire route, lastTraveledSectionIndex and traveledDistanceOnLastSectionInMeters are set to 0.
    let lastTraveledSectionIndex = 0
    let traveledDistanceOnLastSectionInMeters = 0

    // Note: calculateTrafficOnRoute requires a route with routeHandle.
    // Enable it by setting routeOptions.enableRouteHandle to true when creating the route.
    routingEngine.calculateTrafficOnRoute(
        route: route!,
        lastTraveledSectionIndex: Int32(lastTraveledSectionIndex),
        traveledDistanceOnLastSectionInMeters: Int32(traveledDistanceOnLastSectionInMeters)
    ) { routingError, trafficOnRoute in
        if let error = routingError {
            print("CalculateTrafficOnRoute error: \(error)")
        } else if let trafficOnRoute = trafficOnRoute {
            self.showUpdatedETA(trafficOnRoute: 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 func showUpdatedETA(trafficOnRoute: TrafficOnRoute) {
    for section in trafficOnRoute.trafficSections {
        var updatedETAInSeconds = 0.0;
        section.trafficSpans.forEach{ updatedETAInSeconds = updatedETAInSeconds + Double($0.duration)}
        var updatedTrafficDelayInSeconds = 0.0;
        section.trafficSpans.forEach{ updatedTrafficDelayInSeconds = updatedTrafficDelayInSeconds + Double($0.trafficDelay)}
        let updatedETAString = String(format: "Updated travel duration %@\nUpdated traffic delay %@",
                                      timeUtils.formatTime(sec: updatedETAInSeconds),
                                      timeUtils.formatTime(sec: updatedTrafficDelayInSeconds))
        showDialog(title: "Updated traffic", message: 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 Traffic.

Update traffic during turn-by-turn navigation (only available 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.

func updateTrafficOnRoute(routeProgress: RouteProgress) {
    guard let currentRoute = visualNavigator.route else {
        // Should never happen.
        return
    }

    // Below, we use 10 minutes. A common range is between 5 and 15 minutes.
    let trafficUpdateIntervalInMilliseconds = 10 * 60000 // 10 minutes
    let now = Int(Date().timeIntervalSince1970 * 1000) // Current time in milliseconds
    if (now - lastTrafficUpdateInMilliseconds) < trafficUpdateIntervalInMilliseconds {
        return
    }
    // Store the current time when we update trafficOnRoute.
    lastTrafficUpdateInMilliseconds = now

    let sectionProgressList = routeProgress.sectionProgress
    guard let lastSectionProgress = sectionProgressList.last else {
        // Should never happen if the list is valid.
        return
    }
    let traveledDistanceOnLastSectionInMeters =
    currentRoute.lengthInMeters - lastSectionProgress.remainingDistanceInMeters
    let lastTraveledSectionIndex = routeProgress.routeMatchedLocation.sectionIndex

    routeCalculator.calculateTrafficOnRoute(
        currentRoute: currentRoute,
        lastTraveledSectionIndex: Int(lastTraveledSectionIndex),
        traveledDistanceOnLastSectionInMeters: Int(traveledDistanceOnLastSectionInMeters)
    ) { routingError, trafficOnRoute in
        if let routingError = routingError {
            print("CalculateTrafficOnRoute error: \(routingError)")
            return
        }

        // Sets traffic data for the current route, affecting RouteProgress duration in SectionProgress,
        // while preserving route distance and geometry.
        self.visualNavigator.trafficOnRoute = trafficOnRoute
        print("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.