Optimize Traffic Vector Tiles usage in HERE SDK
Context
Developers may observe that certain configurations in their application can lead to a significant volume of network requests for Traffic Vector Tiles (TVT). This is typically associated with implementation choices designed for comprehensive, map-wide traffic visualization, where traffic flow is displayed across the entire viewport. While powerful, this approach may not be optimal for all use cases, particularly those focused on turn-by-turn navigation.
### Implementation Considerations
The volume of network requests is directly related to the features enabled and their configuration. Two key areas to consider are:
1. Map-Wide Traffic Flow: The feature MapFeatureModes.TRAFFIC_FLOW_WITH_FREE_FLOW is designed to render a rich traffic layer across the entire visible map area. It functions as intended by continuously downloading traffic tiles to cover the current viewport, which naturally increases data consumption during map interaction (panning and zooming).
2. Traffic Incident Refresh Rate: The frequency at which the application polls for traffic incident data also contributes to the total number of network requests.
---
### Recommended Optimization Strategy
For applications where the primary use case is active guidance or turn-by-turn navigation, we recommend a more data-efficient strategy. This approach focuses on providing the most relevant traffic information to the user - the traffic on their specific route. This involves three key steps:
1. Disable General Traffic Flow: Stop rendering the traffic layer across the entire map.
2. Adjust Traffic Refresh Rate: Increase the refresh interval for traffic incidents to a more reasonable value, like 5 minutes.
3. Implement On-Route Traffic with VisualNavigator: Use the VisualNavigator API to display traffic conditions directly and only on the calculated route.
---
### Implementation Guide
Follow these steps and use the provided code snippets to implement the optimization.
#### 1. Disable General Traffic Flow Layer
For navigation-focused use cases, we recommend enabling only traffic incidents on the general map view and relying on VisualNavigator for traffic flow during active guidance. Ensure that you are not enabling the TRAFFIC_FLOW_WITH_FREE_FLOW map feature. This is the most critical step to reduce unnecessary tile requests. Instead, you should only enable TRAFFIC_INCIDENTS for displaying icons for road events.
// DO NOT USE THIS: This setting causes high data consumption.
// mapFeatures.put(MapFeatures.TRAFFIC_FLOW, MapFeatureModes.TRAFFIC_FLOW_WITH_FREE_FLOW);
// INSTEAD, enable only traffic incidents for the map view.
Map mapFeatures = new HashMap<>();
mapFeatures.put(MapFeatures.TRAFFIC_INCIDENTS, MapFeatureModes.TRAFFIC_INCIDENTS_ALL);
mapView.getMapScene().enableFeatures(mapFeatures);
#### 2. Set the Traffic Refresh Period
To reduce the frequency of background data polling for traffic incidents, set the refresh period to 300 seconds (5 minutes). This is a static method and should be called once during your application's initialization.
import com.here.sdk.mapview.MapContentSettings;
import com.here.time.Duration;
...
try {
// Set the refresh period to 300 seconds (5 minutes).
// The value must be between 60 and 300 seconds.
MapContentSettings.setTrafficRefreshPeriod(Duration.ofSeconds(300));
} catch (MapContentSettings.TrafficRefreshPeriodException e) {
Log.e(TAG, "Failed to set traffic refresh period: " + e.getMessage());
}
#### 3. Use VisualNavigator for On-Route Traffic Visualization
The VisualNavigator provides an efficient way to show real-time traffic directly on the user's route line during active navigation without fetching tiles for the entire map.
##### Enable and Configure Traffic on the Route
First, enable the traffic visualization feature on your VisualNavigator instance. You can also customize the colors used to represent different traffic conditions.
import com.here.sdk.navigation.VisualNavigator;
import com.here.sdk.navigation.VisualNavigatorColors;
import com.here.sdk.navigation.TrafficOnRouteColors;
...
// Enable the traffic-on-route feature
visualNavigator.setTrafficOnRouteVisible(true);
// Optionally, customize the colors for traffic visualization
VisualNavigatorColors visualNavigatorColors = VisualNavigatorColors.dayColors();
TrafficOnRouteColors trafficOnRouteColors = new TrafficOnRouteColors(
GUIDANCE_CONDITION_SLOW_COLOR, // Color for slow traffic
GUIDANCE_CONDITION_OBSTRUCTION_COLOR, // Color for blocked/closed traffic
GUIDANCE_CONDITION_OBSTRUCTION_COLOR // Color for other obstructions
);
visualNavigatorColors.setTrafficOnRouteColors(trafficOnRouteColors);
visualNavigator.setColors(visualNavigatorColors);
##### Periodically Update Traffic Data for the Route
During navigation, you need to periodically request traffic updates for the current route. This is done using the routingEngine.calculateTrafficOnRoute() method. This lightweight call fetches traffic data only for the route's geometry and updates the travel time and visualization without requiring a full route recalculation.
The result is then passed to the visualNavigator using setTrafficOnRoute(). We recommend calling this function at a reasonable interval, such as every 5-10 minutes.
// Periodically updates the traffic information for the current route.
public void updateTrafficOnRoute(RouteProgress routeProgress, VisualNavigator visualNavigator) {
Route currentRoute = visualNavigator.getRoute();
if (currentRoute == null) {
return;
}
// Set an update interval to avoid excessive calls. 5 minutes is recommended.
long trafficUpdateIntervalInMilliseconds = 1000 * 60 * 5;
long now = System.currentTimeMillis();
if ((now - lastTrafficUpdateInMilliseconds) < trafficUpdateIntervalInMilliseconds) {
return; // Not time to update yet.
}
lastTrafficUpdateInMilliseconds = now;
// Ensure you are using the online RoutingEngine
if (routingEngine instanceof OfflineRoutingEngine) {
return;
}
// Calculate traffic on the existing route handle
((RoutingEngine) routingEngine).calculateTrafficOnRoute(
currentRoute,
(routingError, trafficOnRoute) -> {
if (routingError == null && trafficOnRoute != null) {
// This updates the route line visualization and ETA in RouteProgress.
visualNavigator.setTrafficOnRoute(trafficOnRoute);
Log.d(TAG, "Successfully updated traffic on route.");
} else {
Log.d(TAG, "CalculateTrafficOnRoute error: " + routingError);
}
});
}
Adopting this strategy helps create a more data-efficient application that provides an excellent user experience with relevant, on-route traffic information, lower your data consumption, and maintain an excellent user experience with relevant, on-route traffic information.
Please download the full attached sample to integrate that includes background positioning and managing network state as well.
Important API Ref:
1) setTrafficRefreshPeriod
2) VisualNavigatorColors
3) setTrafficOnRoute
4) setTrafficOnRouteVisible
Developers may observe that certain configurations in their application can lead to a significant volume of network requests for Traffic Vector Tiles (TVT). This is typically associated with implementation choices designed for comprehensive, map-wide traffic visualization, where traffic flow is displayed across the entire viewport. While powerful, this approach may not be optimal for all use cases, particularly those focused on turn-by-turn navigation.
### Implementation Considerations
The volume of network requests is directly related to the features enabled and their configuration. Two key areas to consider are:
1. Map-Wide Traffic Flow: The feature
MapFeatureModes.TRAFFIC_FLOW_WITH_FREE_FLOW is designed to render a rich traffic layer across the entire visible map area. It functions as intended by continuously downloading traffic tiles to cover the current viewport, which naturally increases data consumption during map interaction (panning and zooming).2. Traffic Incident Refresh Rate: The frequency at which the application polls for traffic incident data also contributes to the total number of network requests.
---
### Recommended Optimization Strategy
For applications where the primary use case is active guidance or turn-by-turn navigation, we recommend a more data-efficient strategy. This approach focuses on providing the most relevant traffic information to the user - the traffic on their specific route. This involves three key steps:
1. Disable General Traffic Flow: Stop rendering the traffic layer across the entire map.
2. Adjust Traffic Refresh Rate: Increase the refresh interval for traffic incidents to a more reasonable value, like 5 minutes.
3. Implement On-Route Traffic with
VisualNavigator: Use the VisualNavigator API to display traffic conditions directly and only on the calculated route.---
### Implementation Guide
Follow these steps and use the provided code snippets to implement the optimization.
#### 1. Disable General Traffic Flow Layer
For navigation-focused use cases, we recommend enabling only traffic incidents on the general map view and relying on
VisualNavigator for traffic flow during active guidance. Ensure that you are not enabling the TRAFFIC_FLOW_WITH_FREE_FLOW map feature. This is the most critical step to reduce unnecessary tile requests. Instead, you should only enable TRAFFIC_INCIDENTS for displaying icons for road events.// DO NOT USE THIS: This setting causes high data consumption. // mapFeatures.put(MapFeatures.TRAFFIC_FLOW, MapFeatureModes.TRAFFIC_FLOW_WITH_FREE_FLOW);// INSTEAD, enable only traffic incidents for the map view. Map mapFeatures = new HashMap<>(); mapFeatures.put(MapFeatures.TRAFFIC_INCIDENTS, MapFeatureModes.TRAFFIC_INCIDENTS_ALL); mapView.getMapScene().enableFeatures(mapFeatures);#### 2. Set the Traffic Refresh Period
To reduce the frequency of background data polling for traffic incidents, set the refresh period to 300 seconds (5 minutes). This is a static method and should be called once during your application's initialization.
import com.here.sdk.mapview.MapContentSettings; import com.here.time.Duration;...try { // Set the refresh period to 300 seconds (5 minutes). // The value must be between 60 and 300 seconds. MapContentSettings.setTrafficRefreshPeriod(Duration.ofSeconds(300)); } catch (MapContentSettings.TrafficRefreshPeriodException e) { Log.e(TAG, "Failed to set traffic refresh period: " + e.getMessage()); }#### 3. Use
VisualNavigator for On-Route Traffic VisualizationThe
VisualNavigator provides an efficient way to show real-time traffic directly on the user's route line during active navigation without fetching tiles for the entire map.##### Enable and Configure Traffic on the Route
First, enable the traffic visualization feature on your
VisualNavigator instance. You can also customize the colors used to represent different traffic conditions.import com.here.sdk.navigation.VisualNavigator; import com.here.sdk.navigation.VisualNavigatorColors; import com.here.sdk.navigation.TrafficOnRouteColors;...// Enable the traffic-on-route feature visualNavigator.setTrafficOnRouteVisible(true);// Optionally, customize the colors for traffic visualization VisualNavigatorColors visualNavigatorColors = VisualNavigatorColors.dayColors(); TrafficOnRouteColors trafficOnRouteColors = new TrafficOnRouteColors( GUIDANCE_CONDITION_SLOW_COLOR, // Color for slow traffic GUIDANCE_CONDITION_OBSTRUCTION_COLOR, // Color for blocked/closed traffic GUIDANCE_CONDITION_OBSTRUCTION_COLOR // Color for other obstructions ); visualNavigatorColors.setTrafficOnRouteColors(trafficOnRouteColors); visualNavigator.setColors(visualNavigatorColors);##### Periodically Update Traffic Data for the Route
During navigation, you need to periodically request traffic updates for the current route. This is done using the
routingEngine.calculateTrafficOnRoute() method. This lightweight call fetches traffic data only for the route's geometry and updates the travel time and visualization without requiring a full route recalculation.The result is then passed to the
visualNavigator using setTrafficOnRoute(). We recommend calling this function at a reasonable interval, such as every 5-10 minutes.// Periodically updates the traffic information for the current route. public void updateTrafficOnRoute(RouteProgress routeProgress, VisualNavigator visualNavigator) { Route currentRoute = visualNavigator.getRoute(); if (currentRoute == null) { return; }// Set an update interval to avoid excessive calls. 5 minutes is recommended. long trafficUpdateIntervalInMilliseconds = 1000 * 60 * 5; long now = System.currentTimeMillis(); if ((now - lastTrafficUpdateInMilliseconds) < trafficUpdateIntervalInMilliseconds) { return; // Not time to update yet. } lastTrafficUpdateInMilliseconds = now;// Ensure you are using the online RoutingEngine if (routingEngine instanceof OfflineRoutingEngine) { return; }// Calculate traffic on the existing route handle ((RoutingEngine) routingEngine).calculateTrafficOnRoute( currentRoute, (routingError, trafficOnRoute) -> { if (routingError == null && trafficOnRoute != null) { // This updates the route line visualization and ETA in RouteProgress. visualNavigator.setTrafficOnRoute(trafficOnRoute); Log.d(TAG, "Successfully updated traffic on route."); } else { Log.d(TAG, "CalculateTrafficOnRoute error: " + routingError); } }); }Adopting this strategy helps create a more data-efficient application that provides an excellent user experience with relevant, on-route traffic information, lower your data consumption, and maintain an excellent user experience with relevant, on-route traffic information.
Please download the full attached sample to integrate that includes background positioning and managing network state as well.
Important API Ref:
1) setTrafficRefreshPeriod
2) VisualNavigatorColors
3) setTrafficOnRoute
4) setTrafficOnRouteVisible