Skip to content

Commit

Permalink
Merge pull request #355 from heremaps/esd/42050
Browse files Browse the repository at this point in the history
Update example apps for release 4.20.5.0
  • Loading branch information
KarmveerKumarHere authored Nov 26, 2024
2 parents 0fb4493 + 0b2540c commit 9653e8a
Show file tree
Hide file tree
Showing 116 changed files with 3,070 additions and 1,952 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ For an overview of the existing features, please check the _Developer Guide_ for

> For now, the _Navigate Edition_ is only available upon request. Please contact your HERE representative to receive access including a set of evaluation credentials.
## List of Available Example Apps (Version 4.20.4.0)
## List of Available Example Apps (Version 4.20.5.0)

- **HelloMap**: Shows the classic 'Hello World'.
- **HelloMapKotlin**: Shows the classic 'Hello World' using Kotlin language (Android only).
Expand Down
2 changes: 1 addition & 1 deletion examples/latest/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
This folder contains the HERE SDK examples apps for version: 4.20.4.0
This folder contains the HERE SDK examples apps for version: 4.20.5.0

- HERE SDK for Android ([Lite Edition](lite/android/), [Explore Edition](explore/android/), [Navigate Edition](navigate/android/))
- HERE SDK for iOS ([Lite Edition](lite/ios/), [Explore Edition](explore/ios/), [Navigate Edition](navigate/ios/))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ private void logTollDetails(Route route) {
}
for (Toll toll : tolls) {
Log.d(TAG, "Toll information valid for this list of spans:");
Log.d(TAG, "Toll system: " + toll.tollSystem);
Log.d(TAG, "Toll systems: " + toll.tollSystems);
Log.d(TAG, "Toll country code (ISO-3166-1 alpha-3): " + toll.countryCode);
Log.d(TAG, "Toll fare information: ");
for (TollFare tollFare : toll.fares) {
Expand Down
2 changes: 1 addition & 1 deletion examples/latest/explore/android/Traffic/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
The Traffic example app shows how to toggle traffic flow and traffic incidents visualization on a map. You can find how this is done in [TrafficExample.java](app/src/main/java/com/here/traffic/TrafficExample.java).
The Traffic example app shows how to toggle traffic flow and traffic incidents visualization on a map and how to use the TrafficEngine to query such data in realtime, for example, along a route. You can find how this is done in [TrafficExample.java](app/src/main/java/com/here/traffic/TrafficExample.java) and [RoutingExample.java](app/src/main/java/com/here/traffic/RoutingExample.java).

Build instructions:
-------------------
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public class MainActivity extends AppCompatActivity {
private PermissionsRequestor permissionsRequestor;
private MapView mapView;
private TrafficExample trafficExample;
private RoutingExample routingExample;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand Down Expand Up @@ -96,11 +97,12 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis

private void loadMapScene() {
// Load a scene from the HERE SDK to render the map with a map scheme.
mapView.getMapScene().loadScene(MapScheme.NORMAL_DAY, new MapScene.LoadSceneCallback() {
mapView.getMapScene().loadScene(MapScheme.LITE_DAY, new MapScene.LoadSceneCallback() {
@Override
public void onLoadScene(@Nullable MapError mapError) {
if (mapError == null) {
trafficExample = new TrafficExample(MainActivity.this, mapView);
routingExample = new RoutingExample(MainActivity.this, mapView);
} else {
Log.d(TAG, "onLoadScene failed: " + mapError.toString());
}
Expand All @@ -116,6 +118,14 @@ public void disableAllButtonClicked(View view) {
trafficExample.disableAll();
}

public void addRouteClicked(View view) {
routingExample.addRoute();
}

public void clearMapClicked(View view) {
routingExample.clearMap();
}

@Override
protected void onPause() {
mapView.onPause();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
/*
* Copyright (C) 2019-2024 HERE Europe B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* License-Filename: LICENSE
*/

package com.here.traffic;

import android.content.Context;
import android.util.Log;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;

import com.here.sdk.core.Color;
import com.here.sdk.core.GeoCoordinates;
import com.here.sdk.core.GeoCorridor;
import com.here.sdk.core.GeoPolyline;
import com.here.sdk.core.Point2D;
import com.here.sdk.core.errors.InstantiationErrorException;
import com.here.sdk.mapview.LineCap;
import com.here.sdk.mapview.MapCamera;
import com.here.sdk.mapview.MapMeasure;
import com.here.sdk.mapview.MapMeasureDependentRenderSize;
import com.here.sdk.mapview.MapPolyline;
import com.here.sdk.mapview.MapView;
import com.here.sdk.mapview.RenderSize;
import com.here.sdk.routing.CarOptions;
import com.here.sdk.routing.Route;
import com.here.sdk.routing.RoutingEngine;
import com.here.sdk.routing.Waypoint;
import com.here.sdk.traffic.TrafficEngine;
import com.here.sdk.traffic.TrafficFlow;
import com.here.sdk.traffic.TrafficFlowQueryCallback;
import com.here.sdk.traffic.TrafficFlowQueryOptions;
import com.here.sdk.traffic.TrafficQueryError;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

// This example shows how to request and visualize realtime traffic flow information
// with the TrafficEngine along a route corridor.
// Note that the request time may differ from the refresh cycle for TRAFFIC_FLOWs.
// Note that this does not consider future traffic predictions that are available based on
// the traffic information of the route object based on the ETA and historical traffic patterns.
public class RoutingExample {

private static final String TAG = RoutingExample.class.getName();

private final Context context;
private final MapView mapView;
private final List<MapPolyline> mapPolylines = new ArrayList<>();
private final RoutingEngine routingEngine;
private final TrafficEngine trafficEngine;

public RoutingExample(Context context, MapView mapView) {
this.context = context;
this.mapView = mapView;

// Configure the map.
MapCamera camera = mapView.getCamera();
double distanceInMeters = 1000 * 10;
MapMeasure mapMeasureZoom = new MapMeasure(MapMeasure.Kind.DISTANCE, distanceInMeters);
camera.lookAt(new GeoCoordinates(52.520798, 13.409408), mapMeasureZoom);

try {
routingEngine = new RoutingEngine();
} catch (InstantiationErrorException e) {
throw new RuntimeException("Initialization of RoutingEngine failed: " + e.error.name());
}

try {
// The traffic engine can be used to request additional information about
// the current traffic situation anywhere on the road network.
trafficEngine = new TrafficEngine();
} catch (InstantiationErrorException e) {
throw new RuntimeException("Initialization of TrafficEngine failed: " + e.error.name());
}
}

public void addRoute() {
Waypoint startWaypoint = new Waypoint(createRandomGeoCoordinatesAroundMapCenter());
Waypoint destinationWaypoint = new Waypoint(createRandomGeoCoordinatesAroundMapCenter());

List<Waypoint> waypoints =
new ArrayList<>(Arrays.asList(startWaypoint, destinationWaypoint));

routingEngine.calculateRoute(
waypoints,
new CarOptions(),
(routingError, routes) -> {
if (routingError == null) {
Route route = routes.get(0);
showRouteOnMap(route);
} else {
showDialog("Error while calculating a route:", routingError.toString());
}
});
}

private void showRouteOnMap(Route route) {
// Optionally, clear any previous route.
clearMap();

// Show route as polyline.
GeoPolyline routeGeoPolyline = route.getGeometry();
float widthInPixels = 20;
Color polylineColor = new Color(0, (float) 0.56, (float) 0.54, (float) 0.63);
MapPolyline routeMapPolyline = null;

try {
routeMapPolyline = new MapPolyline(routeGeoPolyline, new MapPolyline.SolidRepresentation(
new MapMeasureDependentRenderSize(RenderSize.Unit.PIXELS, widthInPixels),
polylineColor,
LineCap.ROUND));
} catch (MapPolyline.Representation.InstantiationException e) {
Log.e("MapPolyline Representation Exception:", e.error.name());
} catch (MapMeasureDependentRenderSize.InstantiationException e) {
Log.e("MapMeasureDependentRenderSize Exception:", e.error.name());
}

mapView.getMapScene().addMapPolyline(routeMapPolyline);
mapPolylines.add(routeMapPolyline);

if (route.getLengthInMeters() / 1000 > 5000) {
showDialog("Note", "Skipped showing traffic-on-route for longer routes.");
return;
}

requestRealtimeTrafficOnRoute(route);
}

public void clearMap() {
for (MapPolyline mapPolyline : mapPolylines) {
mapView.getMapScene().removeMapPolyline(mapPolyline);
}
mapPolylines.clear();
}

// This code uses the TrafficEngine to request the current state of the traffic situation
// along the specified route corridor. Note that this information might dynamically change while
// traveling along a route and it might not relate with the given ETA for the route.
// Whereas the traffic-flow map feature shows pre-rendered vector tiles to achieve a smooth
// map performance, the TrafficEngine requests the same information only for a specified area.
// Depending on the time of the request and other backend factors like rendering the traffic
// vector tiles, there can be cases, where both results differ.
// Note that the HERE SDK allows to specify how often to request updates for the traffic-flow
// map feature. It is recommended to not show traffic-flow and traffic-on-route together as it
// might lead to redundant information. Instead, consider to show the traffic-flow map feature
// side-by-side with the route's polyline (not shown in the method below). See Routing app for an
// example.
private void requestRealtimeTrafficOnRoute(Route route) {
// We are interested to see traffic also for side paths.
int halfWidthInMeters = 500;

GeoCorridor geoCorridor = new GeoCorridor(route.getGeometry().vertices, halfWidthInMeters);
TrafficFlowQueryOptions trafficFlowQueryOptions = new TrafficFlowQueryOptions();
trafficEngine.queryForFlow(geoCorridor, trafficFlowQueryOptions, new TrafficFlowQueryCallback() {
@Override
public void onTrafficFlowFetched(@Nullable TrafficQueryError trafficQueryError,
@Nullable List<TrafficFlow> list) {
if (trafficQueryError == null) {
for (TrafficFlow trafficFlow : list) {
Double confidence = trafficFlow.getConfidence();
if (confidence != null && confidence <= 0.5) {
// Exclude speed-limit data and include only real-time and historical
// flow information.
continue;
}

// Visualize all polylines unfiltered as we get them from the TrafficEngine.
GeoPolyline trafficGeoPolyline = trafficFlow.getLocation().polyline;
addTrafficPolylines(trafficFlow.getJamFactor(), trafficGeoPolyline);
}
} else {
showDialog("Error while fetching traffic flow:", trafficQueryError.toString());
}
}
});
}

private void addTrafficPolylines(double jamFactor, GeoPolyline geoPolyline) {
Color lineColor = getTrafficColor(jamFactor);
if (lineColor == null) {
// We skip rendering low traffic.
return;
}
float widthInPixels = 10;
MapPolyline trafficSpanMapPolyline = null;
try {
trafficSpanMapPolyline = new MapPolyline(geoPolyline, new MapPolyline.SolidRepresentation(
new MapMeasureDependentRenderSize(RenderSize.Unit.PIXELS, widthInPixels),
lineColor,
LineCap.ROUND));
} catch (MapPolyline.Representation.InstantiationException e) {
Log.e("MapPolyline Representation Exception:", e.error.name());
} catch (MapMeasureDependentRenderSize.InstantiationException e) {
Log.e("MapMeasureDependentRenderSize Exception:", e.error.name());
}

mapView.getMapScene().addMapPolyline(trafficSpanMapPolyline);
mapPolylines.add(trafficSpanMapPolyline);
}

// Define a traffic color scheme based on the traffic jam factor.
// 0 <= jamFactor < 4: No or light traffic.
// 4 <= jamFactor < 8: Moderate or slow traffic.
// 8 <= jamFactor < 10: Severe traffic.
// jamFactor = 10: No traffic, ie. the road is blocked.
// Returns null in case of no or light traffic.
@Nullable
private Color getTrafficColor(Double jamFactor) {
if (jamFactor == null || jamFactor < 4) {
return null;
} else if (jamFactor >= 4 && jamFactor < 8) {
return Color.valueOf(1, 1, 0, 0.63f); // Yellow
} else if (jamFactor >= 8 && jamFactor < 10) {
return Color.valueOf(1, 0, 0, 0.63f); // Red
}
return Color.valueOf(0, 0, 0, 0.63f); // Black
}

private GeoCoordinates createRandomGeoCoordinatesAroundMapCenter() {
GeoCoordinates centerGeoCoordinates = mapView.viewToGeoCoordinates(
new Point2D(mapView.getWidth() / 2, mapView.getHeight() / 2));
if (centerGeoCoordinates == null) {
// Should never happen for center coordinates.
throw new RuntimeException("CenterGeoCoordinates are null");
}
double lat = centerGeoCoordinates.latitude;
double lon = centerGeoCoordinates.longitude;
return new GeoCoordinates(getRandom(lat - 0.02, lat + 0.02),
getRandom(lon - 0.02, lon + 0.02));
}

private double getRandom(double min, double max) {
return min + Math.random() * (max - min);
}

private void showDialog(String title, String message) {
AlertDialog.Builder builder =
new AlertDialog.Builder(context);
builder.setTitle(title);
builder.setMessage(message);
builder.show();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import com.here.sdk.core.errors.InstantiationErrorException;
import com.here.sdk.mapview.LineCap;
import com.here.sdk.mapview.MapCamera;
import com.here.sdk.mapview.MapContentSettings;
import com.here.sdk.mapview.MapFeatureModes;
import com.here.sdk.mapview.MapFeatures;
import com.here.sdk.mapview.MapMeasure;
Expand All @@ -53,12 +54,14 @@
import com.here.sdk.traffic.TrafficIncidentsQueryCallback;
import com.here.sdk.traffic.TrafficIncidentsQueryOptions;
import com.here.sdk.traffic.TrafficQueryError;
import com.here.time.Duration;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// This example shows how to query traffic info on incidents with the TrafficEngine.
public class TrafficExample {

private static final String TAG = TrafficExample.class.getName();
Expand All @@ -78,6 +81,8 @@ public TrafficExample(Context context, MapView mapView) {
camera.lookAt(new GeoCoordinates(52.520798, 13.409408), mapMeasureZoom);

try {
// The traffic engine can be used to request additional information about
// the current traffic situation anywhere on the road network.
trafficEngine = new TrafficEngine();
} catch (InstantiationErrorException e) {
throw new RuntimeException("Initialization of TrafficEngine failed: " + e.error.name());
Expand All @@ -100,6 +105,14 @@ public void disableAll() {
}

private void enableTrafficVisualization() {
// Try to refresh the TRAFFIC_FLOW vector tiles every minute.
// If MapFeatures.TRAFFIC_FLOW is disabled, no requests are made.
try {
MapContentSettings.setTrafficRefreshPeriod(Duration.ofMinutes(1));
} catch (MapContentSettings.TrafficRefreshPeriodException e) {
throw new RuntimeException("TrafficRefreshPeriodException: " + e.error.name());
}

Map<String, String> mapFeatures = new HashMap<>();
// Once these traffic layers are added to the map, they will be automatically updated while panning the map.
mapFeatures.put(MapFeatures.TRAFFIC_FLOW, MapFeatureModes.TRAFFIC_FLOW_WITH_FREE_FLOW);
Expand Down
Loading

0 comments on commit 9653e8a

Please sign in to comment.