diff --git a/README.md b/README.md index 68af8665..abadfcbe 100644 --- a/README.md +++ b/README.md @@ -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.5.0) +## List of Available Example Apps (Version 4.21.0.0) - **HelloMap**: Shows the classic 'Hello World'. - **HelloMapKotlin**: Shows the classic 'Hello World' using Kotlin language (Android only). diff --git a/examples/latest/README.md b/examples/latest/README.md index ec08ff98..a33ac4b0 100644 --- a/examples/latest/README.md +++ b/examples/latest/README.md @@ -1,4 +1,4 @@ -This folder contains the HERE SDK examples apps for version: 4.20.5.0 +This folder contains the HERE SDK examples apps for version: 4.21.0.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/)) diff --git a/examples/latest/explore/android/Camera/app/build.gradle b/examples/latest/explore/android/Camera/app/build.gradle index d757e2c4..9d577f60 100644 --- a/examples/latest/explore/android/Camera/app/build.gradle +++ b/examples/latest/explore/android/Camera/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.camera" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/Camera/build.gradle b/examples/latest/explore/android/Camera/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/explore/android/Camera/build.gradle +++ b/examples/latest/explore/android/Camera/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/Camera/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/Camera/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/Camera/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/Camera/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/CameraKeyframeTracks/app/build.gradle b/examples/latest/explore/android/CameraKeyframeTracks/app/build.gradle index d731a4e7..a00b7e63 100644 --- a/examples/latest/explore/android/CameraKeyframeTracks/app/build.gradle +++ b/examples/latest/explore/android/CameraKeyframeTracks/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.camerakeyframetracks" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/CameraKeyframeTracks/build.gradle b/examples/latest/explore/android/CameraKeyframeTracks/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/explore/android/CameraKeyframeTracks/build.gradle +++ b/examples/latest/explore/android/CameraKeyframeTracks/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/CameraKeyframeTracks/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/CameraKeyframeTracks/gradle/wrapper/gradle-wrapper.properties index 29e28c6a..87287e6a 100644 --- a/examples/latest/explore/android/CameraKeyframeTracks/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/CameraKeyframeTracks/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Mar 22 17:05:56 IST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/examples/latest/explore/android/CustomMapStyles/app/build.gradle b/examples/latest/explore/android/CustomMapStyles/app/build.gradle index b5cc6b2b..39a05217 100644 --- a/examples/latest/explore/android/CustomMapStyles/app/build.gradle +++ b/examples/latest/explore/android/CustomMapStyles/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.custommapstyles" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/CustomMapStyles/build.gradle b/examples/latest/explore/android/CustomMapStyles/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/explore/android/CustomMapStyles/build.gradle +++ b/examples/latest/explore/android/CustomMapStyles/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/CustomMapStyles/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/CustomMapStyles/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/CustomMapStyles/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/CustomMapStyles/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/CustomPointTileSource/app/build.gradle b/examples/latest/explore/android/CustomPointTileSource/app/build.gradle index 95dd74b3..27d2eda5 100644 --- a/examples/latest/explore/android/CustomPointTileSource/app/build.gradle +++ b/examples/latest/explore/android/CustomPointTileSource/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.custompointtilesource" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/CustomPointTileSource/build.gradle b/examples/latest/explore/android/CustomPointTileSource/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/explore/android/CustomPointTileSource/build.gradle +++ b/examples/latest/explore/android/CustomPointTileSource/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/CustomPointTileSource/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/CustomPointTileSource/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/CustomPointTileSource/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/CustomPointTileSource/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/CustomPolygonLayers/app/build.gradle b/examples/latest/explore/android/CustomPolygonLayers/app/build.gradle index 29fda995..a5f7a0cc 100644 --- a/examples/latest/explore/android/CustomPolygonLayers/app/build.gradle +++ b/examples/latest/explore/android/CustomPolygonLayers/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.custompolygonlayers" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/CustomPolygonLayers/build.gradle b/examples/latest/explore/android/CustomPolygonLayers/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/explore/android/CustomPolygonLayers/build.gradle +++ b/examples/latest/explore/android/CustomPolygonLayers/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/CustomPolygonLayers/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/CustomPolygonLayers/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/CustomPolygonLayers/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/CustomPolygonLayers/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/CustomRasterLayers/app/build.gradle b/examples/latest/explore/android/CustomRasterLayers/app/build.gradle index 107e512e..74986567 100644 --- a/examples/latest/explore/android/CustomRasterLayers/app/build.gradle +++ b/examples/latest/explore/android/CustomRasterLayers/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.customrasterlayers" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/CustomRasterLayers/app/src/main/java/com/here/sdk/customrasterlayers/CustomRasterLayersExample.java b/examples/latest/explore/android/CustomRasterLayers/app/src/main/java/com/here/sdk/customrasterlayers/CustomRasterLayersExample.java index 73a31d33..723c46f9 100644 --- a/examples/latest/explore/android/CustomRasterLayers/app/src/main/java/com/here/sdk/customrasterlayers/CustomRasterLayersExample.java +++ b/examples/latest/explore/android/CustomRasterLayers/app/src/main/java/com/here/sdk/customrasterlayers/CustomRasterLayersExample.java @@ -112,9 +112,9 @@ private RasterDataSource createRasterDataSource(String dataSourceName) { } private MapLayer createMapLayer(String dataSourceName) { - // The layer should be rendered on top of other layers except the "labels" layer + // The layer should be rendered on top of other layers including the "labels" layer // so that we don't overlap the raster layer over POI markers. - MapLayerPriority priority = new MapLayerPriorityBuilder().renderedBeforeLayer("labels").build(); + MapLayerPriority priority = new MapLayerPriorityBuilder().renderedAfterLayer("labels").build(); // And it should be visible for all zoom levels. MapLayerVisibilityRange range = new MapLayerVisibilityRange(0, 22 + 1); diff --git a/examples/latest/explore/android/CustomRasterLayers/build.gradle b/examples/latest/explore/android/CustomRasterLayers/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/explore/android/CustomRasterLayers/build.gradle +++ b/examples/latest/explore/android/CustomRasterLayers/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/CustomRasterLayers/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/CustomRasterLayers/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/CustomRasterLayers/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/CustomRasterLayers/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/CustomRasterTileSource/app/build.gradle b/examples/latest/explore/android/CustomRasterTileSource/app/build.gradle index 9ed077eb..16c40969 100644 --- a/examples/latest/explore/android/CustomRasterTileSource/app/build.gradle +++ b/examples/latest/explore/android/CustomRasterTileSource/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.customrastertilesource" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/CustomRasterTileSource/app/src/main/java/com/here/sdk/customrastertilesource/CustomRasterTileSourceExample.java b/examples/latest/explore/android/CustomRasterTileSource/app/src/main/java/com/here/sdk/customrastertilesource/CustomRasterTileSourceExample.java index bdc89ec1..1b583bef 100644 --- a/examples/latest/explore/android/CustomRasterTileSource/app/src/main/java/com/here/sdk/customrastertilesource/CustomRasterTileSourceExample.java +++ b/examples/latest/explore/android/CustomRasterTileSource/app/src/main/java/com/here/sdk/customrastertilesource/CustomRasterTileSourceExample.java @@ -80,9 +80,9 @@ private RasterDataSource createRasterDataSource(String dataSourceName) { } private MapLayer createMapLayer(String dataSourceName) { - // The layer should be rendered on top of other layers except the "labels" layer + // The layer should be rendered on top of other layers including the "labels" layer // so that we don't overlap the raster layer over POI markers. - MapLayerPriority priority = new MapLayerPriorityBuilder().renderedBeforeLayer("labels").build(); + MapLayerPriority priority = new MapLayerPriorityBuilder().renderedAfterLayer("labels").build(); // And it should be visible for all zoom levels. MapLayerVisibilityRange range = new MapLayerVisibilityRange(0, 22 + 1); diff --git a/examples/latest/explore/android/CustomRasterTileSource/build.gradle b/examples/latest/explore/android/CustomRasterTileSource/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/explore/android/CustomRasterTileSource/build.gradle +++ b/examples/latest/explore/android/CustomRasterTileSource/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/CustomRasterTileSource/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/CustomRasterTileSource/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/CustomRasterTileSource/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/CustomRasterTileSource/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/EVRouting/app/build.gradle b/examples/latest/explore/android/EVRouting/app/build.gradle index 68f92b42..8a6d5682 100644 --- a/examples/latest/explore/android/EVRouting/app/build.gradle +++ b/examples/latest/explore/android/EVRouting/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.evrouting" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/EVRouting/app/src/main/java/com/here/evrouting/EVRoutingExample.java b/examples/latest/explore/android/EVRouting/app/src/main/java/com/here/evrouting/EVRoutingExample.java index 270fc570..4686a14f 100644 --- a/examples/latest/explore/android/EVRouting/app/src/main/java/com/here/evrouting/EVRoutingExample.java +++ b/examples/latest/explore/android/EVRouting/app/src/main/java/com/here/evrouting/EVRoutingExample.java @@ -63,7 +63,9 @@ import com.here.sdk.routing.Section; import com.here.sdk.routing.SectionNotice; import com.here.sdk.routing.Waypoint; +import com.here.sdk.search.CategoryQuery; import com.here.sdk.search.Place; +import com.here.sdk.search.PlaceCategory; import com.here.sdk.search.SearchCallback; import com.here.sdk.search.SearchEngine; import com.here.sdk.search.SearchError; @@ -302,14 +304,15 @@ private void searchAlongARoute(Route route) { // within a max distance of xx meters from any point of the route. int halfWidthInMeters = 200; GeoCorridor routeCorridor = new GeoCorridor(route.getGeometry().vertices, halfWidthInMeters); - TextQuery.Area queryArea = new TextQuery.Area(routeCorridor, mapView.getCamera().getState().targetCoordinates); - TextQuery textQuery = new TextQuery("charging station", queryArea); + PlaceCategory placeCategory = new PlaceCategory(PlaceCategory.BUSINESS_AND_SERVICES_EV_CHARGING_STATION); + CategoryQuery.Area categoryQueryArea = new CategoryQuery.Area(routeCorridor, mapView.getCamera().getState().targetCoordinates); + CategoryQuery categoryQuery = new CategoryQuery(placeCategory, categoryQueryArea); SearchOptions searchOptions = new SearchOptions(); searchOptions.languageCode = LanguageCode.EN_US; searchOptions.maxItems = 30; - searchEngine.searchByText(textQuery, searchOptions, new SearchCallback() { + searchEngine.searchByCategory(categoryQuery, searchOptions, new SearchCallback() { @Override public void onSearchCompleted(SearchError searchError, List items) { if (searchError != null) { diff --git a/examples/latest/explore/android/EVRouting/build.gradle b/examples/latest/explore/android/EVRouting/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/explore/android/EVRouting/build.gradle +++ b/examples/latest/explore/android/EVRouting/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/EVRouting/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/EVRouting/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/EVRouting/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/EVRouting/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/Gestures/app/build.gradle b/examples/latest/explore/android/Gestures/app/build.gradle index a67030f3..3c26c8bf 100644 --- a/examples/latest/explore/android/Gestures/app/build.gradle +++ b/examples/latest/explore/android/Gestures/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.gestures" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/Gestures/build.gradle b/examples/latest/explore/android/Gestures/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/explore/android/Gestures/build.gradle +++ b/examples/latest/explore/android/Gestures/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/explore/android/Gestures/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/Gestures/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/Gestures/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/Gestures/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/HelloMap/README.md b/examples/latest/explore/android/HelloMap/README.md index 3847c02c..d2a7a551 100644 --- a/examples/latest/explore/android/HelloMap/README.md +++ b/examples/latest/explore/android/HelloMap/README.md @@ -9,4 +9,4 @@ Note: If your AAR version is different than the version shown in the _Developer 2) Open Android Studio and sync the project. -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `MainActivity.java` file. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials in the `MainActivity.java` file. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/android/HelloMap/app/build.gradle b/examples/latest/explore/android/HelloMap/app/build.gradle index fbda9d9b..acf4279e 100644 --- a/examples/latest/explore/android/HelloMap/app/build.gradle +++ b/examples/latest/explore/android/HelloMap/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomap" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/HelloMap/app/src/main/java/com/here/hellomap/MainActivity.java b/examples/latest/explore/android/HelloMap/app/src/main/java/com/here/hellomap/MainActivity.java index ae0b0338..3f0eb9a9 100644 --- a/examples/latest/explore/android/HelloMap/app/src/main/java/com/here/hellomap/MainActivity.java +++ b/examples/latest/explore/android/HelloMap/app/src/main/java/com/here/hellomap/MainActivity.java @@ -29,6 +29,7 @@ import com.here.hellomap.PermissionsRequestor.ResultListener; import com.here.sdk.core.GeoCoordinates; +import com.here.sdk.core.engine.AuthenticationMode; import com.here.sdk.core.engine.SDKNativeEngine; import com.here.sdk.core.engine.SDKOptions; import com.here.sdk.core.errors.InstantiationErrorException; @@ -74,7 +75,9 @@ private void initializeHERESDK() { // Set your credentials for the HERE SDK. String accessKeyID = "YOUR_ACCESS_KEY_ID"; String accessKeySecret = "YOUR_ACCESS_KEY_SECRET"; - SDKOptions options = new SDKOptions(accessKeyID, accessKeySecret); + AuthenticationMode authenticationMode = AuthenticationMode.withKeySecret(accessKeyID, accessKeySecret); + SDKOptions options = new SDKOptions(authenticationMode); + try { Context context = this; SDKNativeEngine.makeSharedInstance(context, options); diff --git a/examples/latest/explore/android/HelloMap/build.gradle b/examples/latest/explore/android/HelloMap/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/explore/android/HelloMap/build.gradle +++ b/examples/latest/explore/android/HelloMap/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/HelloMap/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/HelloMap/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/HelloMap/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/HelloMap/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/HelloMapAndroidAuto/app/build.gradle b/examples/latest/explore/android/HelloMapAndroidAuto/app/build.gradle index 65bda53f..ef6bbfbb 100644 --- a/examples/latest/explore/android/HelloMapAndroidAuto/app/build.gradle +++ b/examples/latest/explore/android/HelloMapAndroidAuto/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomapandroidauto" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/HelloMapAndroidAuto/build.gradle b/examples/latest/explore/android/HelloMapAndroidAuto/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/explore/android/HelloMapAndroidAuto/build.gradle +++ b/examples/latest/explore/android/HelloMapAndroidAuto/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/HelloMapAndroidAuto/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/HelloMapAndroidAuto/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/HelloMapAndroidAuto/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/HelloMapAndroidAuto/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/HelloMapKotlin/app/build.gradle b/examples/latest/explore/android/HelloMapKotlin/app/build.gradle index 49fdec68..f94c0ac4 100644 --- a/examples/latest/explore/android/HelloMapKotlin/app/build.gradle +++ b/examples/latest/explore/android/HelloMapKotlin/app/build.gradle @@ -2,11 +2,11 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomap" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/MainActivity.kt b/examples/latest/explore/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/MainActivity.kt index dbfdeb7a..70fb7f91 100644 --- a/examples/latest/explore/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/MainActivity.kt +++ b/examples/latest/explore/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/MainActivity.kt @@ -23,6 +23,7 @@ import android.util.Log import androidx.appcompat.app.AppCompatActivity import com.here.hellomap.PermissionsRequestor.ResultListener import com.here.sdk.core.GeoCoordinates +import com.here.sdk.core.engine.AuthenticationMode import com.here.sdk.core.engine.SDKNativeEngine import com.here.sdk.core.engine.SDKOptions import com.here.sdk.core.errors.InstantiationErrorException @@ -58,7 +59,8 @@ class MainActivity : AppCompatActivity() { // Set your credentials for the HERE SDK. var accessKeyID = "YOUR_ACCESS_KEY_ID" var accessKeySecret = "YOUR_ACCESS_KEY_SECRET" - var options = SDKOptions(accessKeyID, accessKeySecret) + var authenticationMode = AuthenticationMode.withKeySecret(accessKeyID, accessKeySecret) + var options = SDKOptions(authenticationMode) try { var context = this SDKNativeEngine.makeSharedInstance(context, options) diff --git a/examples/latest/explore/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/PermissionsRequestor.kt b/examples/latest/explore/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/PermissionsRequestor.kt index 0b892465..6706f133 100644 --- a/examples/latest/explore/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/PermissionsRequestor.kt +++ b/examples/latest/explore/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/PermissionsRequestor.kt @@ -48,27 +48,28 @@ class PermissionsRequestor(private val activity: Activity) { } private val permissionsToRequest: Array - private get() { + get() { val permissionList = ArrayList() try { - @Suppress("DEPRECATION") - val packageInfo = activity.packageManager.getPackageInfo( - activity.packageName, PackageManager.GET_PERMISSIONS) + val packageInfo = activity.packageManager.getPackageInfo(activity.packageName, PackageManager.GET_PERMISSIONS) if (packageInfo.requestedPermissions != null) { - for (permission in packageInfo.requestedPermissions) { - if (ContextCompat.checkSelfPermission( - activity, permission) != PackageManager.PERMISSION_GRANTED) { - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M && permission == Manifest.permission.CHANGE_NETWORK_STATE) { - // Exclude CHANGE_NETWORK_STATE as it does not require explicit user approval. - // This workaround is needed for devices running Android 6.0.0, - // see https://issuetracker.google.com/issues/37067994 - continue + val permissions = packageInfo.requestedPermissions + if (permissions != null) { + for (permission in permissions) { + if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M + && permission == Manifest.permission.CHANGE_NETWORK_STATE) { + // Exclude CHANGE_NETWORK_STATE as it does not require explicit user approval. + // This workaround is needed for devices running Android 6.0.0, + // see https://issuetracker.google.com/issues/37067994 + continue + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && + permission == Manifest.permission.ACCESS_BACKGROUND_LOCATION) { + continue + } + permissionList.add(permission) } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && - permission == Manifest.permission.ACCESS_BACKGROUND_LOCATION) { - continue - } - permissionList.add(permission) } } } diff --git a/examples/latest/explore/android/HelloMapKotlin/build.gradle b/examples/latest/explore/android/HelloMapKotlin/build.gradle index 1e6378cb..7d294cdd 100644 --- a/examples/latest/explore/android/HelloMapKotlin/build.gradle +++ b/examples/latest/explore/android/HelloMapKotlin/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/explore/android/HelloMapKotlin/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/HelloMapKotlin/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/HelloMapKotlin/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/HelloMapKotlin/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/HelloMapSurface/app/build.gradle b/examples/latest/explore/android/HelloMapSurface/app/build.gradle index 80841071..661b8f4f 100644 --- a/examples/latest/explore/android/HelloMapSurface/app/build.gradle +++ b/examples/latest/explore/android/HelloMapSurface/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomapsurface" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/HelloMapSurface/build.gradle b/examples/latest/explore/android/HelloMapSurface/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/explore/android/HelloMapSurface/build.gradle +++ b/examples/latest/explore/android/HelloMapSurface/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/HelloMapSurface/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/HelloMapSurface/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/HelloMapSurface/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/HelloMapSurface/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/MapItems/app/build.gradle b/examples/latest/explore/android/MapItems/app/build.gradle index 3e33242b..426648e8 100644 --- a/examples/latest/explore/android/MapItems/app/build.gradle +++ b/examples/latest/explore/android/MapItems/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.mapitems" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/MapItems/build.gradle b/examples/latest/explore/android/MapItems/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/explore/android/MapItems/build.gradle +++ b/examples/latest/explore/android/MapItems/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/explore/android/MapItems/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/MapItems/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/MapItems/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/MapItems/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/MultiDisplays/app/build.gradle b/examples/latest/explore/android/MultiDisplays/app/build.gradle index 9a08c246..48d0e334 100644 --- a/examples/latest/explore/android/MultiDisplays/app/build.gradle +++ b/examples/latest/explore/android/MultiDisplays/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.multidisplays" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/MultiDisplays/build.gradle b/examples/latest/explore/android/MultiDisplays/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/explore/android/MultiDisplays/build.gradle +++ b/examples/latest/explore/android/MultiDisplays/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/MultiDisplays/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/MultiDisplays/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/MultiDisplays/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/MultiDisplays/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/OffscreenMapSurface/app/build.gradle b/examples/latest/explore/android/OffscreenMapSurface/app/build.gradle index 23c99103..6ec4c1b2 100644 --- a/examples/latest/explore/android/OffscreenMapSurface/app/build.gradle +++ b/examples/latest/explore/android/OffscreenMapSurface/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.offscreenmap" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/OffscreenMapSurface/build.gradle b/examples/latest/explore/android/OffscreenMapSurface/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/explore/android/OffscreenMapSurface/build.gradle +++ b/examples/latest/explore/android/OffscreenMapSurface/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/explore/android/OffscreenMapSurface/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/OffscreenMapSurface/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/OffscreenMapSurface/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/OffscreenMapSurface/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/PublicTransit/app/build.gradle b/examples/latest/explore/android/PublicTransit/app/build.gradle index 21102fba..b0d3b3c9 100644 --- a/examples/latest/explore/android/PublicTransit/app/build.gradle +++ b/examples/latest/explore/android/PublicTransit/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.routing" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/PublicTransit/build.gradle b/examples/latest/explore/android/PublicTransit/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/explore/android/PublicTransit/build.gradle +++ b/examples/latest/explore/android/PublicTransit/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/explore/android/PublicTransit/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/PublicTransit/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/PublicTransit/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/PublicTransit/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/Routing/app/build.gradle b/examples/latest/explore/android/Routing/app/build.gradle index 21102fba..b0d3b3c9 100644 --- a/examples/latest/explore/android/Routing/app/build.gradle +++ b/examples/latest/explore/android/Routing/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.routing" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/Routing/build.gradle b/examples/latest/explore/android/Routing/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/explore/android/Routing/build.gradle +++ b/examples/latest/explore/android/Routing/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/explore/android/Routing/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/android/Routing/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/explore/android/Routing/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/android/Routing/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/explore/android/Search/app/build.gradle b/examples/latest/explore/android/Search/app/build.gradle index 04878aee..52ef7993 100644 --- a/examples/latest/explore/android/Search/app/build.gradle +++ b/examples/latest/explore/android/Search/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.search" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/explore/android/Search/app/src/main/res/layout/activity_main.xml b/examples/latest/explore/android/Search/app/src/main/res/layout/activity_main.xml index 698b49ce..b220deea 100644 --- a/examples/latest/explore/android/Search/app/src/main/res/layout/activity_main.xml +++ b/examples/latest/explore/android/Search/app/src/main/res/layout/activity_main.xml @@ -10,10 +10,11 @@ - + android:layout_height="0dp" + app:layout_constraintBottom_toBottomOf="parent" /> ? items) { + _searchEngine.searchByCategory(categoryQuery, searchOptions, (SearchError? searchError, List? items) { if (searchError != null) { print("Search: No charging stations found along the route. Error: $searchError"); return; diff --git a/examples/latest/explore/flutter/gestures_app/android/app/build.gradle b/examples/latest/explore/flutter/gestures_app/android/app/build.gradle index 10a2a1dc..05d00d19 100644 --- a/examples/latest/explore/flutter/gestures_app/android/app/build.gradle +++ b/examples/latest/explore/flutter/gestures_app/android/app/build.gradle @@ -24,7 +24,7 @@ if (flutterVersionName == null) { android { namespace "com.here.sdk.examples.gestures_app" - compileSdkVersion 34 + compileSdk 35 lintOptions { disable 'InvalidPackage' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.here.sdk.examples.gestures_app" minSdkVersion 24 - targetSdkVersion 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -44,6 +44,7 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/examples/latest/explore/flutter/gestures_app/android/app/proguard-rules.pro b/examples/latest/explore/flutter/gestures_app/android/app/proguard-rules.pro new file mode 100644 index 00000000..9cc5b94c --- /dev/null +++ b/examples/latest/explore/flutter/gestures_app/android/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# This is to fix a known bug in Android Gradle Plugin, see https://issuetracker.google.com/issues/282544776 +# With newer versions of the Android Gradle Plugin a build might fail with an error, otherwise. +# +-dontwarn com.here.sdk.R$id +-dontwarn com.here.sdk.R$layout +-dontwarn com.here.sdk.R$string +-dontwarn com.here.sdk.R$styleable diff --git a/examples/latest/explore/flutter/gestures_app/android/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/flutter/gestures_app/android/gradle/wrapper/gradle-wrapper.properties index 6b665338..7aeeb11c 100644 --- a/examples/latest/explore/flutter/gestures_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/flutter/gestures_app/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/examples/latest/explore/flutter/gestures_app/android/settings.gradle b/examples/latest/explore/flutter/gestures_app/android/settings.gradle index 9b1a1012..03e70fe4 100644 --- a/examples/latest/explore/flutter/gestures_app/android/settings.gradle +++ b/examples/latest/explore/flutter/gestures_app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false + id "com.android.application" version "8.6.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/examples/latest/explore/flutter/hello_map_app/android/app/build.gradle b/examples/latest/explore/flutter/hello_map_app/android/app/build.gradle index 5f134af9..3a70ad69 100644 --- a/examples/latest/explore/flutter/hello_map_app/android/app/build.gradle +++ b/examples/latest/explore/flutter/hello_map_app/android/app/build.gradle @@ -24,7 +24,7 @@ if (flutterVersionName == null) { android { namespace "com.here.sdk.examples.hello_map_app" - compileSdkVersion 34 + compileSdk 35 lintOptions { disable 'InvalidPackage' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.here.sdk.examples.hello_map_app" minSdkVersion 24 - targetSdkVersion 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -44,6 +44,7 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/examples/latest/explore/flutter/hello_map_app/android/app/proguard-rules.pro b/examples/latest/explore/flutter/hello_map_app/android/app/proguard-rules.pro new file mode 100644 index 00000000..9cc5b94c --- /dev/null +++ b/examples/latest/explore/flutter/hello_map_app/android/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# This is to fix a known bug in Android Gradle Plugin, see https://issuetracker.google.com/issues/282544776 +# With newer versions of the Android Gradle Plugin a build might fail with an error, otherwise. +# +-dontwarn com.here.sdk.R$id +-dontwarn com.here.sdk.R$layout +-dontwarn com.here.sdk.R$string +-dontwarn com.here.sdk.R$styleable diff --git a/examples/latest/explore/flutter/hello_map_app/android/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/flutter/hello_map_app/android/gradle/wrapper/gradle-wrapper.properties index 6b665338..7aeeb11c 100644 --- a/examples/latest/explore/flutter/hello_map_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/flutter/hello_map_app/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/examples/latest/explore/flutter/hello_map_app/android/settings.gradle b/examples/latest/explore/flutter/hello_map_app/android/settings.gradle index 599ca9d6..6d743468 100644 --- a/examples/latest/explore/flutter/hello_map_app/android/settings.gradle +++ b/examples/latest/explore/flutter/hello_map_app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false + id "com.android.application" version "8.6.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/examples/latest/explore/flutter/hello_map_app/lib/main.dart b/examples/latest/explore/flutter/hello_map_app/lib/main.dart index fd15852a..1294c661 100644 --- a/examples/latest/explore/flutter/hello_map_app/lib/main.dart +++ b/examples/latest/explore/flutter/hello_map_app/lib/main.dart @@ -36,8 +36,11 @@ void _initializeHERESDK() async { // Set your credentials for the HERE SDK. String accessKeyId = "YOUR_ACCESS_KEY_ID"; - String accessKeySecret = "YOUR_ACCESS_KEY_SECRET"; - SDKOptions sdkOptions = SDKOptions.withAccessKeySecret(accessKeyId, accessKeySecret); + String accessKeySecret = + "YOUR_ACCESS_KEY_SECRET"; + AuthenticationMode authenticationMode = + AuthenticationMode.withKeySecret(accessKeyId, accessKeySecret); + SDKOptions sdkOptions = SDKOptions.withAuthenticationMode(authenticationMode); try { await SDKNativeEngine.makeSharedInstance(sdkOptions); @@ -58,11 +61,14 @@ class MyApp extends StatelessWidget { void _onMapCreated(HereMapController hereMapController) { // The camera can be configured before or after a scene is loaded. const double distanceToEarthInMeters = 8000; - MapMeasure mapMeasureZoom = MapMeasure(MapMeasureKind.distance, distanceToEarthInMeters); - hereMapController.camera.lookAtPointWithMeasure(GeoCoordinates(52.530932, 13.384915), mapMeasureZoom); + MapMeasure mapMeasureZoom = + MapMeasure(MapMeasureKind.distance, distanceToEarthInMeters); + hereMapController.camera.lookAtPointWithMeasure( + GeoCoordinates(52.530932, 13.384915), mapMeasureZoom); // Load the map scene using a map scheme to render the map with. - hereMapController.mapScene.loadSceneForMapScheme(MapScheme.normalDay, (MapError? error) { + hereMapController.mapScene.loadSceneForMapScheme(MapScheme.normalDay, + (MapError? error) { if (error != null) { print('Map scene not loaded. MapError: ${error.toString()}'); } diff --git a/examples/latest/explore/flutter/map_items_app/android/app/build.gradle b/examples/latest/explore/flutter/map_items_app/android/app/build.gradle index 05036490..671928b7 100644 --- a/examples/latest/explore/flutter/map_items_app/android/app/build.gradle +++ b/examples/latest/explore/flutter/map_items_app/android/app/build.gradle @@ -24,7 +24,7 @@ if (flutterVersionName == null) { android { namespace "com.here.sdk.examples.map_items_app" - compileSdkVersion 34 + compileSdk 35 lintOptions { disable 'InvalidPackage' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.here.sdk.examples.map_items_app" minSdkVersion 24 - targetSdkVersion 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -44,6 +44,7 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/examples/latest/explore/flutter/map_items_app/android/app/proguard-rules.pro b/examples/latest/explore/flutter/map_items_app/android/app/proguard-rules.pro new file mode 100644 index 00000000..9cc5b94c --- /dev/null +++ b/examples/latest/explore/flutter/map_items_app/android/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# This is to fix a known bug in Android Gradle Plugin, see https://issuetracker.google.com/issues/282544776 +# With newer versions of the Android Gradle Plugin a build might fail with an error, otherwise. +# +-dontwarn com.here.sdk.R$id +-dontwarn com.here.sdk.R$layout +-dontwarn com.here.sdk.R$string +-dontwarn com.here.sdk.R$styleable diff --git a/examples/latest/explore/flutter/map_items_app/android/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/flutter/map_items_app/android/gradle/wrapper/gradle-wrapper.properties index 6b665338..7aeeb11c 100644 --- a/examples/latest/explore/flutter/map_items_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/flutter/map_items_app/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/examples/latest/explore/flutter/map_items_app/android/settings.gradle b/examples/latest/explore/flutter/map_items_app/android/settings.gradle index 9b1a1012..03e70fe4 100644 --- a/examples/latest/explore/flutter/map_items_app/android/settings.gradle +++ b/examples/latest/explore/flutter/map_items_app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false + id "com.android.application" version "8.6.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/examples/latest/explore/flutter/public_transit_app/android/app/build.gradle b/examples/latest/explore/flutter/public_transit_app/android/app/build.gradle index 7fceb081..3bd08c25 100644 --- a/examples/latest/explore/flutter/public_transit_app/android/app/build.gradle +++ b/examples/latest/explore/flutter/public_transit_app/android/app/build.gradle @@ -24,7 +24,7 @@ if (flutterVersionName == null) { android { namespace "com.here.sdk.examples.public_transit_app" - compileSdkVersion 34 + compileSdk 35 lintOptions { disable 'InvalidPackage' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.here.sdk.examples.public_transit_app" minSdkVersion 24 - targetSdkVersion 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -44,6 +44,7 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/examples/latest/explore/flutter/public_transit_app/android/app/proguard-rules.pro b/examples/latest/explore/flutter/public_transit_app/android/app/proguard-rules.pro new file mode 100644 index 00000000..9cc5b94c --- /dev/null +++ b/examples/latest/explore/flutter/public_transit_app/android/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# This is to fix a known bug in Android Gradle Plugin, see https://issuetracker.google.com/issues/282544776 +# With newer versions of the Android Gradle Plugin a build might fail with an error, otherwise. +# +-dontwarn com.here.sdk.R$id +-dontwarn com.here.sdk.R$layout +-dontwarn com.here.sdk.R$string +-dontwarn com.here.sdk.R$styleable diff --git a/examples/latest/explore/flutter/public_transit_app/android/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/flutter/public_transit_app/android/gradle/wrapper/gradle-wrapper.properties index 6b665338..7aeeb11c 100644 --- a/examples/latest/explore/flutter/public_transit_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/flutter/public_transit_app/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/examples/latest/explore/flutter/public_transit_app/android/settings.gradle b/examples/latest/explore/flutter/public_transit_app/android/settings.gradle index 9b1a1012..03e70fe4 100644 --- a/examples/latest/explore/flutter/public_transit_app/android/settings.gradle +++ b/examples/latest/explore/flutter/public_transit_app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false + id "com.android.application" version "8.6.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/examples/latest/explore/flutter/routing_app/android/app/build.gradle b/examples/latest/explore/flutter/routing_app/android/app/build.gradle index 5b5ce874..28981613 100644 --- a/examples/latest/explore/flutter/routing_app/android/app/build.gradle +++ b/examples/latest/explore/flutter/routing_app/android/app/build.gradle @@ -24,7 +24,7 @@ if (flutterVersionName == null) { android { namespace "com.here.sdk.examples.routing_app" - compileSdkVersion 34 + compileSdk 35 lintOptions { disable 'InvalidPackage' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.here.sdk.examples.routing_app" minSdkVersion 24 - targetSdkVersion 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -44,6 +44,7 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/examples/latest/explore/flutter/routing_app/android/app/proguard-rules.pro b/examples/latest/explore/flutter/routing_app/android/app/proguard-rules.pro new file mode 100644 index 00000000..9cc5b94c --- /dev/null +++ b/examples/latest/explore/flutter/routing_app/android/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# This is to fix a known bug in Android Gradle Plugin, see https://issuetracker.google.com/issues/282544776 +# With newer versions of the Android Gradle Plugin a build might fail with an error, otherwise. +# +-dontwarn com.here.sdk.R$id +-dontwarn com.here.sdk.R$layout +-dontwarn com.here.sdk.R$string +-dontwarn com.here.sdk.R$styleable diff --git a/examples/latest/explore/flutter/routing_app/android/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/flutter/routing_app/android/gradle/wrapper/gradle-wrapper.properties index 6b665338..7aeeb11c 100644 --- a/examples/latest/explore/flutter/routing_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/flutter/routing_app/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/examples/latest/explore/flutter/routing_app/android/settings.gradle b/examples/latest/explore/flutter/routing_app/android/settings.gradle index 9b1a1012..03e70fe4 100644 --- a/examples/latest/explore/flutter/routing_app/android/settings.gradle +++ b/examples/latest/explore/flutter/routing_app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false + id "com.android.application" version "8.6.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/examples/latest/explore/flutter/search_app/android/app/build.gradle b/examples/latest/explore/flutter/search_app/android/app/build.gradle index 4b3484f3..cbdd2b07 100644 --- a/examples/latest/explore/flutter/search_app/android/app/build.gradle +++ b/examples/latest/explore/flutter/search_app/android/app/build.gradle @@ -24,7 +24,7 @@ if (flutterVersionName == null) { android { namespace "com.here.sdk.examples.search_app" - compileSdkVersion 34 + compileSdk 35 lintOptions { disable 'InvalidPackage' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.here.sdk.examples.search_app" minSdkVersion 24 - targetSdkVersion 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -44,6 +44,7 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/examples/latest/explore/flutter/search_app/android/app/proguard-rules.pro b/examples/latest/explore/flutter/search_app/android/app/proguard-rules.pro new file mode 100644 index 00000000..9cc5b94c --- /dev/null +++ b/examples/latest/explore/flutter/search_app/android/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# This is to fix a known bug in Android Gradle Plugin, see https://issuetracker.google.com/issues/282544776 +# With newer versions of the Android Gradle Plugin a build might fail with an error, otherwise. +# +-dontwarn com.here.sdk.R$id +-dontwarn com.here.sdk.R$layout +-dontwarn com.here.sdk.R$string +-dontwarn com.here.sdk.R$styleable diff --git a/examples/latest/explore/flutter/search_app/android/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/flutter/search_app/android/gradle/wrapper/gradle-wrapper.properties index 6b665338..7aeeb11c 100644 --- a/examples/latest/explore/flutter/search_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/flutter/search_app/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/examples/latest/explore/flutter/search_app/android/settings.gradle b/examples/latest/explore/flutter/search_app/android/settings.gradle index 9b1a1012..03e70fe4 100644 --- a/examples/latest/explore/flutter/search_app/android/settings.gradle +++ b/examples/latest/explore/flutter/search_app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false + id "com.android.application" version "8.6.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/examples/latest/explore/flutter/search_app/lib/main.dart b/examples/latest/explore/flutter/search_app/lib/main.dart index 7ca1686a..fd9413cb 100644 --- a/examples/latest/explore/flutter/search_app/lib/main.dart +++ b/examples/latest/explore/flutter/search_app/lib/main.dart @@ -66,11 +66,15 @@ class _MyAppState extends State { body: Stack( children: [ HereMap(onMapCreated: _onMapCreated), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + Column( children: [ - button('Search', _searchButtonClicked), - button('Geocoding', _geocodeAnAddressButtonClicked), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + button('Search', _searchButtonClicked), + button('Geocoding', _geocodeAnAddressButtonClicked), + ], + ), ], ), ], diff --git a/examples/latest/explore/flutter/traffic_app/android/app/build.gradle b/examples/latest/explore/flutter/traffic_app/android/app/build.gradle index 85a4a06f..b59b9557 100644 --- a/examples/latest/explore/flutter/traffic_app/android/app/build.gradle +++ b/examples/latest/explore/flutter/traffic_app/android/app/build.gradle @@ -24,7 +24,7 @@ if (flutterVersionName == null) { android { namespace "com.here.sdk.examples.traffic_app" - compileSdkVersion 34 + compileSdk 35 lintOptions { disable 'InvalidPackage' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.here.sdk.examples.traffic_app" minSdkVersion 24 - targetSdkVersion 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -44,6 +44,7 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/examples/latest/explore/flutter/traffic_app/android/app/proguard-rules.pro b/examples/latest/explore/flutter/traffic_app/android/app/proguard-rules.pro new file mode 100644 index 00000000..9cc5b94c --- /dev/null +++ b/examples/latest/explore/flutter/traffic_app/android/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# This is to fix a known bug in Android Gradle Plugin, see https://issuetracker.google.com/issues/282544776 +# With newer versions of the Android Gradle Plugin a build might fail with an error, otherwise. +# +-dontwarn com.here.sdk.R$id +-dontwarn com.here.sdk.R$layout +-dontwarn com.here.sdk.R$string +-dontwarn com.here.sdk.R$styleable diff --git a/examples/latest/explore/flutter/traffic_app/android/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/flutter/traffic_app/android/gradle/wrapper/gradle-wrapper.properties index cb18712d..6636b632 100644 --- a/examples/latest/explore/flutter/traffic_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/flutter/traffic_app/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/examples/latest/explore/flutter/traffic_app/android/settings.gradle b/examples/latest/explore/flutter/traffic_app/android/settings.gradle index 9b1a1012..03e70fe4 100644 --- a/examples/latest/explore/flutter/traffic_app/android/settings.gradle +++ b/examples/latest/explore/flutter/traffic_app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false + id "com.android.application" version "8.6.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/examples/latest/explore/flutter/unit_testing_app/android/app/build.gradle b/examples/latest/explore/flutter/unit_testing_app/android/app/build.gradle index 16b68d71..6aa785b9 100644 --- a/examples/latest/explore/flutter/unit_testing_app/android/app/build.gradle +++ b/examples/latest/explore/flutter/unit_testing_app/android/app/build.gradle @@ -24,7 +24,7 @@ if (flutterVersionName == null) { android { namespace "com.here.sdk.examples.unit_testing_app" - compileSdkVersion 34 + compileSdk 35 lintOptions { disable 'InvalidPackage' @@ -34,7 +34,7 @@ android { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "com.here.sdk.examples.unit_testing_app" minSdkVersion 24 - targetSdkVersion 34 + targetSdk 35 versionCode flutterVersionCode.toInteger() versionName flutterVersionName } @@ -44,6 +44,7 @@ android { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. signingConfig signingConfigs.debug + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } } diff --git a/examples/latest/explore/flutter/unit_testing_app/android/app/proguard-rules.pro b/examples/latest/explore/flutter/unit_testing_app/android/app/proguard-rules.pro new file mode 100644 index 00000000..9cc5b94c --- /dev/null +++ b/examples/latest/explore/flutter/unit_testing_app/android/app/proguard-rules.pro @@ -0,0 +1,29 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile + +# This is to fix a known bug in Android Gradle Plugin, see https://issuetracker.google.com/issues/282544776 +# With newer versions of the Android Gradle Plugin a build might fail with an error, otherwise. +# +-dontwarn com.here.sdk.R$id +-dontwarn com.here.sdk.R$layout +-dontwarn com.here.sdk.R$string +-dontwarn com.here.sdk.R$styleable diff --git a/examples/latest/explore/flutter/unit_testing_app/android/gradle/wrapper/gradle-wrapper.properties b/examples/latest/explore/flutter/unit_testing_app/android/gradle/wrapper/gradle-wrapper.properties index 6b665338..7aeeb11c 100644 --- a/examples/latest/explore/flutter/unit_testing_app/android/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/explore/flutter/unit_testing_app/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip diff --git a/examples/latest/explore/flutter/unit_testing_app/android/settings.gradle b/examples/latest/explore/flutter/unit_testing_app/android/settings.gradle index 9b1a1012..03e70fe4 100644 --- a/examples/latest/explore/flutter/unit_testing_app/android/settings.gradle +++ b/examples/latest/explore/flutter/unit_testing_app/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "7.4.2" apply false + id "com.android.application" version "8.6.0" apply false id "org.jetbrains.kotlin.android" version "1.7.10" apply false } diff --git a/examples/latest/explore/ios/Camera/README.md b/examples/latest/explore/ios/Camera/README.md index f5c981cd..d495237d 100644 --- a/examples/latest/explore/ios/Camera/README.md +++ b/examples/latest/explore/ios/Camera/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `CameraApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/CameraKeyframeTracks/README.md b/examples/latest/explore/ios/CameraKeyframeTracks/README.md index e7c78ac5..201e5c87 100644 --- a/examples/latest/explore/ios/CameraKeyframeTracks/README.md +++ b/examples/latest/explore/ios/CameraKeyframeTracks/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `CameraKeyframeTracksApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/CustomMapStyles/README.md b/examples/latest/explore/ios/CustomMapStyles/README.md index f2ac499c..368c50bf 100644 --- a/examples/latest/explore/ios/CustomMapStyles/README.md +++ b/examples/latest/explore/ios/CustomMapStyles/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `CustomMapStylesApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/CustomRasterLayers/CustomRasterLayers/CustomRasterLayersExample.swift b/examples/latest/explore/ios/CustomRasterLayers/CustomRasterLayers/CustomRasterLayersExample.swift index 09d10fb6..e3e39a44 100644 --- a/examples/latest/explore/ios/CustomRasterLayers/CustomRasterLayers/CustomRasterLayersExample.swift +++ b/examples/latest/explore/ios/CustomRasterLayers/CustomRasterLayers/CustomRasterLayersExample.swift @@ -103,9 +103,9 @@ class CustomRasterLayersExample { } private func createMapLayer(dataSourceName: String) -> MapLayer { - // The layer should be rendered on top of other layers except for the "labels" layer + // The layer should be rendered on top of other layers including the "labels" layer // so that we don't overlap the raster layer over POI markers. - let priority = MapLayerPriorityBuilder().renderedBeforeLayer(named: "labels").build() + let priority = MapLayerPriorityBuilder().renderedAfterLayer(named: "labels").build() // And it should be visible for all zoom levels. let range = MapLayerVisibilityRange(minimumZoomLevel: 0, maximumZoomLevel: 22 + 1) diff --git a/examples/latest/explore/ios/CustomRasterLayers/README.md b/examples/latest/explore/ios/CustomRasterLayers/README.md index 429588bb..601723a1 100644 --- a/examples/latest/explore/ios/CustomRasterLayers/README.md +++ b/examples/latest/explore/ios/CustomRasterLayers/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `CustomRasterLayersApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/CustomRasterTileSource/CustomRasterTileSource/CustomRasterTileSourceExample.swift b/examples/latest/explore/ios/CustomRasterTileSource/CustomRasterTileSource/CustomRasterTileSourceExample.swift index 6b77f643..322e9fa3 100644 --- a/examples/latest/explore/ios/CustomRasterTileSource/CustomRasterTileSource/CustomRasterTileSourceExample.swift +++ b/examples/latest/explore/ios/CustomRasterTileSource/CustomRasterTileSource/CustomRasterTileSourceExample.swift @@ -73,9 +73,9 @@ class CustomRasterTileSourceExample { } private func createMapLayer(dataSourceName: String) -> MapLayer { - // The layer should be rendered on top of other layers except for the "labels" layer + // The layer should be rendered on top of other layers including the "labels" layer // so that we don't overlap the raster layer over POI markers. - let priority = MapLayerPriorityBuilder().renderedBeforeLayer(named: "labels").build() + let priority = MapLayerPriorityBuilder().renderedAfterLayer(named: "labels").build() // And it should be visible for all zoom levels. let range = MapLayerVisibilityRange(minimumZoomLevel: 0, maximumZoomLevel: 22 + 1) diff --git a/examples/latest/explore/ios/CustomRasterTileSource/README.md b/examples/latest/explore/ios/CustomRasterTileSource/README.md index b45f33cd..2b15b83b 100644 --- a/examples/latest/explore/ios/CustomRasterTileSource/README.md +++ b/examples/latest/explore/ios/CustomRasterTileSource/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `CustomRasterTileSourceApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/EVRouting/EVRouting/EVRoutingExample.swift b/examples/latest/explore/ios/EVRouting/EVRouting/EVRoutingExample.swift index b6e5a9f5..6fb83b8e 100644 --- a/examples/latest/explore/ios/EVRouting/EVRouting/EVRoutingExample.swift +++ b/examples/latest/explore/ios/EVRouting/EVRouting/EVRoutingExample.swift @@ -245,12 +245,13 @@ class EVRoutingExample { // within a max distance of xx meters from any point of the route. let routeCorridor = GeoCorridor(polyline: route.geometry.vertices, halfWidthInMeters: Int32(200)) - let queryArea = TextQuery.Area(inCorridor: routeCorridor, near: mapView.camera.state.targetCoordinates) - let textQuery = TextQuery("charging station", area: queryArea) + let queryArea = CategoryQuery.Area(inCorridor: routeCorridor, near: mapView.camera.state.targetCoordinates) + let placeCategory = PlaceCategory(id: PlaceCategory.businessAndServicesEvChargingStation) + let categoryQuery = CategoryQuery(placeCategory, area: queryArea) let searchOptions = SearchOptions(languageCode: LanguageCode.enUs, maxItems: 30) - searchEngine.searchByText(textQuery, + searchEngine.searchByCategory(categoryQuery, options: searchOptions, completion: onSearchCompleted) } diff --git a/examples/latest/explore/ios/EVRouting/README.md b/examples/latest/explore/ios/EVRouting/README.md index c90254ac..8b6587c9 100644 --- a/examples/latest/explore/ios/EVRouting/README.md +++ b/examples/latest/explore/ios/EVRouting/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `EVRoutingApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/Gestures/README.md b/examples/latest/explore/ios/Gestures/README.md index d4efb590..713a874d 100644 --- a/examples/latest/explore/ios/Gestures/README.md +++ b/examples/latest/explore/ios/Gestures/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `GesturesApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/HelloMap/HelloMap/HelloMapApp.swift b/examples/latest/explore/ios/HelloMap/HelloMap/HelloMapApp.swift index d47be553..0d716c44 100644 --- a/examples/latest/explore/ios/HelloMap/HelloMap/HelloMapApp.swift +++ b/examples/latest/explore/ios/HelloMap/HelloMap/HelloMapApp.swift @@ -52,7 +52,9 @@ struct HelloMapApp: App { // Set your credentials for the HERE SDK. let accessKeyID = "YOUR_ACCESS_KEY_ID" let accessKeySecret = "YOUR_ACCESS_KEY_SECRET" - let options = SDKOptions(accessKeyId: accessKeyID, accessKeySecret: accessKeySecret) + let authenticationMode = AuthenticationMode.withKeySecret(accessKeyId: accessKeyID, + accessKeySecret: accessKeySecret) + let options = SDKOptions(authenticationMode: authenticationMode) do { try SDKNativeEngine.makeSharedInstance(options: options) } catch let engineInstantiationError { diff --git a/examples/latest/explore/ios/MapItems/README.md b/examples/latest/explore/ios/MapItems/README.md index 27b8eafc..307f8f50 100644 --- a/examples/latest/explore/ios/MapItems/README.md +++ b/examples/latest/explore/ios/MapItems/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `MapItemsApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/OffscreenMap/README.md b/examples/latest/explore/ios/OffscreenMap/README.md index 7f044936..bcd6c473 100644 --- a/examples/latest/explore/ios/OffscreenMap/README.md +++ b/examples/latest/explore/ios/OffscreenMap/README.md @@ -20,4 +20,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `exampleApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `OffscreenMapApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/PublicTransit/README.md b/examples/latest/explore/ios/PublicTransit/README.md index 966d2d2d..c53c0e0d 100644 --- a/examples/latest/explore/ios/PublicTransit/README.md +++ b/examples/latest/explore/ios/PublicTransit/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `PublicTransitApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/Routing/README.md b/examples/latest/explore/ios/Routing/README.md index c7847fd8..fc3cd09d 100644 --- a/examples/latest/explore/ios/Routing/README.md +++ b/examples/latest/explore/ios/Routing/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `RoutingApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/Search/README.md b/examples/latest/explore/ios/Search/README.md index b82e342d..c7ce39e0 100644 --- a/examples/latest/explore/ios/Search/README.md +++ b/examples/latest/explore/ios/Search/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `SearchApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/explore/ios/Search/Search.xcodeproj/project.pbxproj b/examples/latest/explore/ios/Search/Search.xcodeproj/project.pbxproj index 3a298d75..3a9e9501 100644 --- a/examples/latest/explore/ios/Search/Search.xcodeproj/project.pbxproj +++ b/examples/latest/explore/ios/Search/Search.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ diff --git a/examples/latest/explore/ios/Search/Search/ContentView.swift b/examples/latest/explore/ios/Search/Search/ContentView.swift index c61f2b63..b1305420 100644 --- a/examples/latest/explore/ios/Search/Search/ContentView.swift +++ b/examples/latest/explore/ios/Search/Search/ContentView.swift @@ -26,27 +26,29 @@ struct ContentView: View { @State private var searchExample: SearchExample? var body: some View { - // Show the views on top of each other. ZStack(alignment: .top) { - // The map view should fill the entire screen. WrappedMapView(mapView: $mapView) .edgesIgnoringSafeArea(.all) - HStack { - CustomButton(title: "Search example") { - searchExample?.onSearchButtonClicked() - } - CustomButton(title: "GeoCode example") { - searchExample?.onGeoCodeButtonClicked() + VStack(spacing: 10) { + HStack { + CustomButton(title: "Search ") { + searchExample?.onSearchButtonClicked() + } + + CustomButton(title: "GeoCode ") { + searchExample?.onGeoCodeButtonClicked() + } } } - } - .onAppear { - // ContentView appeared, now we init the example. - searchExample = SearchExample(mapView) - } - } + .padding() + } + .onAppear { + // ContentView appeared, now we init the example. + searchExample = SearchExample(mapView) + } + } } // The MapView provided by the HERE SDK conforms to a UIKit view, so it needs to be wrapped to conform diff --git a/examples/latest/explore/ios/Traffic/README.md b/examples/latest/explore/ios/Traffic/README.md index 16c2ff36..c126adc6 100644 --- a/examples/latest/explore/ios/Traffic/README.md +++ b/examples/latest/explore/ios/Traffic/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `TrafficApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/lite/android/CameraLite/app/build.gradle b/examples/latest/lite/android/CameraLite/app/build.gradle index d757e2c4..9d577f60 100644 --- a/examples/latest/lite/android/CameraLite/app/build.gradle +++ b/examples/latest/lite/android/CameraLite/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.camera" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/lite/android/CameraLite/build.gradle b/examples/latest/lite/android/CameraLite/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/lite/android/CameraLite/build.gradle +++ b/examples/latest/lite/android/CameraLite/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/lite/android/CameraLite/gradle/wrapper/gradle-wrapper.properties b/examples/latest/lite/android/CameraLite/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/lite/android/CameraLite/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/lite/android/CameraLite/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/lite/android/GesturesLite/app/build.gradle b/examples/latest/lite/android/GesturesLite/app/build.gradle index a67030f3..3c26c8bf 100644 --- a/examples/latest/lite/android/GesturesLite/app/build.gradle +++ b/examples/latest/lite/android/GesturesLite/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.gestures" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/lite/android/GesturesLite/build.gradle b/examples/latest/lite/android/GesturesLite/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/lite/android/GesturesLite/build.gradle +++ b/examples/latest/lite/android/GesturesLite/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/lite/android/GesturesLite/gradle/wrapper/gradle-wrapper.properties b/examples/latest/lite/android/GesturesLite/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/lite/android/GesturesLite/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/lite/android/GesturesLite/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/lite/android/HelloMapLite/app/build.gradle b/examples/latest/lite/android/HelloMapLite/app/build.gradle index fbda9d9b..acf4279e 100644 --- a/examples/latest/lite/android/HelloMapLite/app/build.gradle +++ b/examples/latest/lite/android/HelloMapLite/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomap" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/lite/android/HelloMapLite/app/src/main/java/com/here/hellomap/MainActivity.java b/examples/latest/lite/android/HelloMapLite/app/src/main/java/com/here/hellomap/MainActivity.java index 56ec2248..fb6fa42e 100644 --- a/examples/latest/lite/android/HelloMapLite/app/src/main/java/com/here/hellomap/MainActivity.java +++ b/examples/latest/lite/android/HelloMapLite/app/src/main/java/com/here/hellomap/MainActivity.java @@ -28,6 +28,7 @@ import com.here.hellomap.PermissionsRequestor.ResultListener; import com.here.sdk.core.GeoCoordinates; +import com.here.sdk.core.engine.AuthenticationMode; import com.here.sdk.core.engine.SDKNativeEngine; import com.here.sdk.core.engine.SDKOptions; import com.here.sdk.core.errors.InstantiationErrorException; @@ -61,7 +62,8 @@ private void initializeHERESDK() { // Set your credentials for the HERE SDK. String accessKeyID = "YOUR_ACCESS_KEY_ID"; String accessKeySecret = "YOUR_ACCESS_KEY_SECRET"; - SDKOptions options = new SDKOptions(accessKeyID, accessKeySecret); + AuthenticationMode authenticationMode = AuthenticationMode.withKeySecret(accessKeyID, accessKeySecret); + SDKOptions options = new SDKOptions(authenticationMode); try { Context context = this; SDKNativeEngine.makeSharedInstance(context, options); @@ -88,6 +90,7 @@ public void permissionsDenied() { @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); permissionsRequestor.onRequestPermissionsResult(requestCode, grantResults); } @@ -130,7 +133,7 @@ protected void onSaveInstanceState(@NonNull Bundle outState) { mapView.onSaveInstanceState(); super.onSaveInstanceState(outState); } - + private void disposeHERESDK() { // Free HERE SDK resources before the application shuts down. // Usually, this should be called only on application termination. diff --git a/examples/latest/lite/android/HelloMapLite/build.gradle b/examples/latest/lite/android/HelloMapLite/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/lite/android/HelloMapLite/build.gradle +++ b/examples/latest/lite/android/HelloMapLite/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/lite/android/HelloMapLite/gradle/wrapper/gradle-wrapper.properties b/examples/latest/lite/android/HelloMapLite/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/lite/android/HelloMapLite/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/lite/android/HelloMapLite/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/lite/android/MapItemsLite/app/build.gradle b/examples/latest/lite/android/MapItemsLite/app/build.gradle index c4c7c374..eaa7dd69 100644 --- a/examples/latest/lite/android/MapItemsLite/app/build.gradle +++ b/examples/latest/lite/android/MapItemsLite/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.mapitems" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/lite/android/MapItemsLite/build.gradle b/examples/latest/lite/android/MapItemsLite/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/lite/android/MapItemsLite/build.gradle +++ b/examples/latest/lite/android/MapItemsLite/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/lite/android/MapItemsLite/gradle/wrapper/gradle-wrapper.properties b/examples/latest/lite/android/MapItemsLite/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/lite/android/MapItemsLite/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/lite/android/MapItemsLite/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/lite/android/RoutingLite/app/build.gradle b/examples/latest/lite/android/RoutingLite/app/build.gradle index fb59ce28..a5e20406 100644 --- a/examples/latest/lite/android/RoutingLite/app/build.gradle +++ b/examples/latest/lite/android/RoutingLite/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.routing" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/lite/android/RoutingLite/build.gradle b/examples/latest/lite/android/RoutingLite/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/lite/android/RoutingLite/build.gradle +++ b/examples/latest/lite/android/RoutingLite/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/lite/android/RoutingLite/gradle/wrapper/gradle-wrapper.properties b/examples/latest/lite/android/RoutingLite/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/lite/android/RoutingLite/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/lite/android/RoutingLite/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/lite/android/SearchLite/app/build.gradle b/examples/latest/lite/android/SearchLite/app/build.gradle index 04878aee..52ef7993 100644 --- a/examples/latest/lite/android/SearchLite/app/build.gradle +++ b/examples/latest/lite/android/SearchLite/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.search" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/lite/android/SearchLite/build.gradle b/examples/latest/lite/android/SearchLite/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/lite/android/SearchLite/build.gradle +++ b/examples/latest/lite/android/SearchLite/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/lite/android/SearchLite/gradle/wrapper/gradle-wrapper.properties b/examples/latest/lite/android/SearchLite/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/lite/android/SearchLite/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/lite/android/SearchLite/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/lite/android/StandAloneEngineLite/app/build.gradle b/examples/latest/lite/android/StandAloneEngineLite/app/build.gradle index 895ead3d..28b3333d 100644 --- a/examples/latest/lite/android/StandAloneEngineLite/app/build.gradle +++ b/examples/latest/lite/android/StandAloneEngineLite/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.standaloneengine" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/lite/android/StandAloneEngineLite/build.gradle b/examples/latest/lite/android/StandAloneEngineLite/build.gradle index fd15a60d..b635d33a 100644 --- a/examples/latest/lite/android/StandAloneEngineLite/build.gradle +++ b/examples/latest/lite/android/StandAloneEngineLite/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/lite/android/StandAloneEngineLite/gradle/wrapper/gradle-wrapper.properties b/examples/latest/lite/android/StandAloneEngineLite/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/lite/android/StandAloneEngineLite/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/lite/android/StandAloneEngineLite/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/lite/android/TrafficLite/app/build.gradle b/examples/latest/lite/android/TrafficLite/app/build.gradle index c1df3435..7f2635d9 100644 --- a/examples/latest/lite/android/TrafficLite/app/build.gradle +++ b/examples/latest/lite/android/TrafficLite/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.traffic" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/lite/android/TrafficLite/build.gradle b/examples/latest/lite/android/TrafficLite/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/lite/android/TrafficLite/build.gradle +++ b/examples/latest/lite/android/TrafficLite/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/lite/android/TrafficLite/gradle/wrapper/gradle-wrapper.properties b/examples/latest/lite/android/TrafficLite/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/lite/android/TrafficLite/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/lite/android/TrafficLite/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/Camera/app/build.gradle b/examples/latest/navigate/android/Camera/app/build.gradle index d757e2c4..9d577f60 100644 --- a/examples/latest/navigate/android/Camera/app/build.gradle +++ b/examples/latest/navigate/android/Camera/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.camera" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/Camera/build.gradle b/examples/latest/navigate/android/Camera/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/navigate/android/Camera/build.gradle +++ b/examples/latest/navigate/android/Camera/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/Camera/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/Camera/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/Camera/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/Camera/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/CameraKeyframeTracks/app/build.gradle b/examples/latest/navigate/android/CameraKeyframeTracks/app/build.gradle index d731a4e7..a00b7e63 100644 --- a/examples/latest/navigate/android/CameraKeyframeTracks/app/build.gradle +++ b/examples/latest/navigate/android/CameraKeyframeTracks/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.camerakeyframetracks" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/CameraKeyframeTracks/build.gradle b/examples/latest/navigate/android/CameraKeyframeTracks/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/navigate/android/CameraKeyframeTracks/build.gradle +++ b/examples/latest/navigate/android/CameraKeyframeTracks/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/CameraKeyframeTracks/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/CameraKeyframeTracks/gradle/wrapper/gradle-wrapper.properties index 29e28c6a..87287e6a 100644 --- a/examples/latest/navigate/android/CameraKeyframeTracks/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/CameraKeyframeTracks/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Tue Mar 22 17:05:56 IST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/examples/latest/navigate/android/CartoPOIPicking/app/build.gradle b/examples/latest/navigate/android/CartoPOIPicking/app/build.gradle index 080ffe1d..ccecea5b 100644 --- a/examples/latest/navigate/android/CartoPOIPicking/app/build.gradle +++ b/examples/latest/navigate/android/CartoPOIPicking/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.cartopoipicking" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/CartoPOIPicking/build.gradle b/examples/latest/navigate/android/CartoPOIPicking/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/CartoPOIPicking/build.gradle +++ b/examples/latest/navigate/android/CartoPOIPicking/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/CartoPOIPicking/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/CartoPOIPicking/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/CartoPOIPicking/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/CartoPOIPicking/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/CustomMapStyles/app/build.gradle b/examples/latest/navigate/android/CustomMapStyles/app/build.gradle index b5cc6b2b..39a05217 100644 --- a/examples/latest/navigate/android/CustomMapStyles/app/build.gradle +++ b/examples/latest/navigate/android/CustomMapStyles/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.custommapstyles" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/CustomMapStyles/build.gradle b/examples/latest/navigate/android/CustomMapStyles/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/navigate/android/CustomMapStyles/build.gradle +++ b/examples/latest/navigate/android/CustomMapStyles/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/CustomMapStyles/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/CustomMapStyles/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/CustomMapStyles/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/CustomMapStyles/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/CustomPointTileSource/app/build.gradle b/examples/latest/navigate/android/CustomPointTileSource/app/build.gradle index 95dd74b3..27d2eda5 100644 --- a/examples/latest/navigate/android/CustomPointTileSource/app/build.gradle +++ b/examples/latest/navigate/android/CustomPointTileSource/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.custompointtilesource" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/CustomPointTileSource/build.gradle b/examples/latest/navigate/android/CustomPointTileSource/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/navigate/android/CustomPointTileSource/build.gradle +++ b/examples/latest/navigate/android/CustomPointTileSource/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/CustomPointTileSource/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/CustomPointTileSource/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/CustomPointTileSource/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/CustomPointTileSource/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/CustomPolygonLayers/app/build.gradle b/examples/latest/navigate/android/CustomPolygonLayers/app/build.gradle index 29fda995..a5f7a0cc 100644 --- a/examples/latest/navigate/android/CustomPolygonLayers/app/build.gradle +++ b/examples/latest/navigate/android/CustomPolygonLayers/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.custompolygonlayers" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/CustomPolygonLayers/build.gradle b/examples/latest/navigate/android/CustomPolygonLayers/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/navigate/android/CustomPolygonLayers/build.gradle +++ b/examples/latest/navigate/android/CustomPolygonLayers/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/CustomPolygonLayers/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/CustomPolygonLayers/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/CustomPolygonLayers/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/CustomPolygonLayers/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/CustomRasterLayers/app/build.gradle b/examples/latest/navigate/android/CustomRasterLayers/app/build.gradle index 107e512e..74986567 100644 --- a/examples/latest/navigate/android/CustomRasterLayers/app/build.gradle +++ b/examples/latest/navigate/android/CustomRasterLayers/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.customrasterlayers" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/CustomRasterLayers/app/src/main/java/com/here/sdk/customrasterlayers/CustomRasterLayersExample.java b/examples/latest/navigate/android/CustomRasterLayers/app/src/main/java/com/here/sdk/customrasterlayers/CustomRasterLayersExample.java index 73a31d33..723c46f9 100644 --- a/examples/latest/navigate/android/CustomRasterLayers/app/src/main/java/com/here/sdk/customrasterlayers/CustomRasterLayersExample.java +++ b/examples/latest/navigate/android/CustomRasterLayers/app/src/main/java/com/here/sdk/customrasterlayers/CustomRasterLayersExample.java @@ -112,9 +112,9 @@ private RasterDataSource createRasterDataSource(String dataSourceName) { } private MapLayer createMapLayer(String dataSourceName) { - // The layer should be rendered on top of other layers except the "labels" layer + // The layer should be rendered on top of other layers including the "labels" layer // so that we don't overlap the raster layer over POI markers. - MapLayerPriority priority = new MapLayerPriorityBuilder().renderedBeforeLayer("labels").build(); + MapLayerPriority priority = new MapLayerPriorityBuilder().renderedAfterLayer("labels").build(); // And it should be visible for all zoom levels. MapLayerVisibilityRange range = new MapLayerVisibilityRange(0, 22 + 1); diff --git a/examples/latest/navigate/android/CustomRasterLayers/build.gradle b/examples/latest/navigate/android/CustomRasterLayers/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/navigate/android/CustomRasterLayers/build.gradle +++ b/examples/latest/navigate/android/CustomRasterLayers/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/CustomRasterLayers/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/CustomRasterLayers/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/CustomRasterLayers/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/CustomRasterLayers/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/CustomRasterTileSource/app/build.gradle b/examples/latest/navigate/android/CustomRasterTileSource/app/build.gradle index 9ed077eb..16c40969 100644 --- a/examples/latest/navigate/android/CustomRasterTileSource/app/build.gradle +++ b/examples/latest/navigate/android/CustomRasterTileSource/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.customrastertilesource" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/CustomRasterTileSource/app/src/main/java/com/here/sdk/customrastertilesource/CustomRasterTileSourceExample.java b/examples/latest/navigate/android/CustomRasterTileSource/app/src/main/java/com/here/sdk/customrastertilesource/CustomRasterTileSourceExample.java index bdc89ec1..1b583bef 100644 --- a/examples/latest/navigate/android/CustomRasterTileSource/app/src/main/java/com/here/sdk/customrastertilesource/CustomRasterTileSourceExample.java +++ b/examples/latest/navigate/android/CustomRasterTileSource/app/src/main/java/com/here/sdk/customrastertilesource/CustomRasterTileSourceExample.java @@ -80,9 +80,9 @@ private RasterDataSource createRasterDataSource(String dataSourceName) { } private MapLayer createMapLayer(String dataSourceName) { - // The layer should be rendered on top of other layers except the "labels" layer + // The layer should be rendered on top of other layers including the "labels" layer // so that we don't overlap the raster layer over POI markers. - MapLayerPriority priority = new MapLayerPriorityBuilder().renderedBeforeLayer("labels").build(); + MapLayerPriority priority = new MapLayerPriorityBuilder().renderedAfterLayer("labels").build(); // And it should be visible for all zoom levels. MapLayerVisibilityRange range = new MapLayerVisibilityRange(0, 22 + 1); diff --git a/examples/latest/navigate/android/CustomRasterTileSource/build.gradle b/examples/latest/navigate/android/CustomRasterTileSource/build.gradle index 332ecec8..11121a30 100644 --- a/examples/latest/navigate/android/CustomRasterTileSource/build.gradle +++ b/examples/latest/navigate/android/CustomRasterTileSource/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/CustomRasterTileSource/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/CustomRasterTileSource/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/CustomRasterTileSource/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/CustomRasterTileSource/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/EVRouting/app/build.gradle b/examples/latest/navigate/android/EVRouting/app/build.gradle index 68f92b42..8a6d5682 100644 --- a/examples/latest/navigate/android/EVRouting/app/build.gradle +++ b/examples/latest/navigate/android/EVRouting/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.evrouting" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/EVRouting/app/src/main/java/com/here/evrouting/EVRoutingExample.java b/examples/latest/navigate/android/EVRouting/app/src/main/java/com/here/evrouting/EVRoutingExample.java index 270fc570..4686a14f 100644 --- a/examples/latest/navigate/android/EVRouting/app/src/main/java/com/here/evrouting/EVRoutingExample.java +++ b/examples/latest/navigate/android/EVRouting/app/src/main/java/com/here/evrouting/EVRoutingExample.java @@ -63,7 +63,9 @@ import com.here.sdk.routing.Section; import com.here.sdk.routing.SectionNotice; import com.here.sdk.routing.Waypoint; +import com.here.sdk.search.CategoryQuery; import com.here.sdk.search.Place; +import com.here.sdk.search.PlaceCategory; import com.here.sdk.search.SearchCallback; import com.here.sdk.search.SearchEngine; import com.here.sdk.search.SearchError; @@ -302,14 +304,15 @@ private void searchAlongARoute(Route route) { // within a max distance of xx meters from any point of the route. int halfWidthInMeters = 200; GeoCorridor routeCorridor = new GeoCorridor(route.getGeometry().vertices, halfWidthInMeters); - TextQuery.Area queryArea = new TextQuery.Area(routeCorridor, mapView.getCamera().getState().targetCoordinates); - TextQuery textQuery = new TextQuery("charging station", queryArea); + PlaceCategory placeCategory = new PlaceCategory(PlaceCategory.BUSINESS_AND_SERVICES_EV_CHARGING_STATION); + CategoryQuery.Area categoryQueryArea = new CategoryQuery.Area(routeCorridor, mapView.getCamera().getState().targetCoordinates); + CategoryQuery categoryQuery = new CategoryQuery(placeCategory, categoryQueryArea); SearchOptions searchOptions = new SearchOptions(); searchOptions.languageCode = LanguageCode.EN_US; searchOptions.maxItems = 30; - searchEngine.searchByText(textQuery, searchOptions, new SearchCallback() { + searchEngine.searchByCategory(categoryQuery, searchOptions, new SearchCallback() { @Override public void onSearchCompleted(SearchError searchError, List items) { if (searchError != null) { diff --git a/examples/latest/navigate/android/EVRouting/build.gradle b/examples/latest/navigate/android/EVRouting/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/EVRouting/build.gradle +++ b/examples/latest/navigate/android/EVRouting/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/EVRouting/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/EVRouting/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/EVRouting/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/EVRouting/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/Gestures/app/build.gradle b/examples/latest/navigate/android/Gestures/app/build.gradle index a67030f3..3c26c8bf 100644 --- a/examples/latest/navigate/android/Gestures/app/build.gradle +++ b/examples/latest/navigate/android/Gestures/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.gestures" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/Gestures/build.gradle b/examples/latest/navigate/android/Gestures/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/navigate/android/Gestures/build.gradle +++ b/examples/latest/navigate/android/Gestures/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/navigate/android/Gestures/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/Gestures/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/Gestures/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/Gestures/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/HelloMap/README.md b/examples/latest/navigate/android/HelloMap/README.md index 3847c02c..d2a7a551 100644 --- a/examples/latest/navigate/android/HelloMap/README.md +++ b/examples/latest/navigate/android/HelloMap/README.md @@ -9,4 +9,4 @@ Note: If your AAR version is different than the version shown in the _Developer 2) Open Android Studio and sync the project. -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `MainActivity.java` file. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials in the `MainActivity.java` file. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/android/HelloMap/app/build.gradle b/examples/latest/navigate/android/HelloMap/app/build.gradle index fbda9d9b..acf4279e 100644 --- a/examples/latest/navigate/android/HelloMap/app/build.gradle +++ b/examples/latest/navigate/android/HelloMap/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomap" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/HelloMap/app/src/main/java/com/here/hellomap/MainActivity.java b/examples/latest/navigate/android/HelloMap/app/src/main/java/com/here/hellomap/MainActivity.java index ae0b0338..3f0eb9a9 100644 --- a/examples/latest/navigate/android/HelloMap/app/src/main/java/com/here/hellomap/MainActivity.java +++ b/examples/latest/navigate/android/HelloMap/app/src/main/java/com/here/hellomap/MainActivity.java @@ -29,6 +29,7 @@ import com.here.hellomap.PermissionsRequestor.ResultListener; import com.here.sdk.core.GeoCoordinates; +import com.here.sdk.core.engine.AuthenticationMode; import com.here.sdk.core.engine.SDKNativeEngine; import com.here.sdk.core.engine.SDKOptions; import com.here.sdk.core.errors.InstantiationErrorException; @@ -74,7 +75,9 @@ private void initializeHERESDK() { // Set your credentials for the HERE SDK. String accessKeyID = "YOUR_ACCESS_KEY_ID"; String accessKeySecret = "YOUR_ACCESS_KEY_SECRET"; - SDKOptions options = new SDKOptions(accessKeyID, accessKeySecret); + AuthenticationMode authenticationMode = AuthenticationMode.withKeySecret(accessKeyID, accessKeySecret); + SDKOptions options = new SDKOptions(authenticationMode); + try { Context context = this; SDKNativeEngine.makeSharedInstance(context, options); diff --git a/examples/latest/navigate/android/HelloMap/build.gradle b/examples/latest/navigate/android/HelloMap/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/HelloMap/build.gradle +++ b/examples/latest/navigate/android/HelloMap/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/HelloMap/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/HelloMap/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/HelloMap/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/HelloMap/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/HelloMapAndroidAuto/app/build.gradle b/examples/latest/navigate/android/HelloMapAndroidAuto/app/build.gradle index 65bda53f..ef6bbfbb 100644 --- a/examples/latest/navigate/android/HelloMapAndroidAuto/app/build.gradle +++ b/examples/latest/navigate/android/HelloMapAndroidAuto/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomapandroidauto" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/HelloMapAndroidAuto/build.gradle b/examples/latest/navigate/android/HelloMapAndroidAuto/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/HelloMapAndroidAuto/build.gradle +++ b/examples/latest/navigate/android/HelloMapAndroidAuto/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/HelloMapAndroidAuto/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/HelloMapAndroidAuto/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/HelloMapAndroidAuto/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/HelloMapAndroidAuto/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/HelloMapKotlin/app/build.gradle b/examples/latest/navigate/android/HelloMapKotlin/app/build.gradle index 49fdec68..f94c0ac4 100644 --- a/examples/latest/navigate/android/HelloMapKotlin/app/build.gradle +++ b/examples/latest/navigate/android/HelloMapKotlin/app/build.gradle @@ -2,11 +2,11 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomap" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/MainActivity.kt b/examples/latest/navigate/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/MainActivity.kt index dbfdeb7a..70fb7f91 100644 --- a/examples/latest/navigate/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/MainActivity.kt +++ b/examples/latest/navigate/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/MainActivity.kt @@ -23,6 +23,7 @@ import android.util.Log import androidx.appcompat.app.AppCompatActivity import com.here.hellomap.PermissionsRequestor.ResultListener import com.here.sdk.core.GeoCoordinates +import com.here.sdk.core.engine.AuthenticationMode import com.here.sdk.core.engine.SDKNativeEngine import com.here.sdk.core.engine.SDKOptions import com.here.sdk.core.errors.InstantiationErrorException @@ -58,7 +59,8 @@ class MainActivity : AppCompatActivity() { // Set your credentials for the HERE SDK. var accessKeyID = "YOUR_ACCESS_KEY_ID" var accessKeySecret = "YOUR_ACCESS_KEY_SECRET" - var options = SDKOptions(accessKeyID, accessKeySecret) + var authenticationMode = AuthenticationMode.withKeySecret(accessKeyID, accessKeySecret) + var options = SDKOptions(authenticationMode) try { var context = this SDKNativeEngine.makeSharedInstance(context, options) diff --git a/examples/latest/navigate/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/PermissionsRequestor.kt b/examples/latest/navigate/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/PermissionsRequestor.kt index 0b892465..6706f133 100644 --- a/examples/latest/navigate/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/PermissionsRequestor.kt +++ b/examples/latest/navigate/android/HelloMapKotlin/app/src/main/java/com/here/hellomap/PermissionsRequestor.kt @@ -48,27 +48,28 @@ class PermissionsRequestor(private val activity: Activity) { } private val permissionsToRequest: Array - private get() { + get() { val permissionList = ArrayList() try { - @Suppress("DEPRECATION") - val packageInfo = activity.packageManager.getPackageInfo( - activity.packageName, PackageManager.GET_PERMISSIONS) + val packageInfo = activity.packageManager.getPackageInfo(activity.packageName, PackageManager.GET_PERMISSIONS) if (packageInfo.requestedPermissions != null) { - for (permission in packageInfo.requestedPermissions) { - if (ContextCompat.checkSelfPermission( - activity, permission) != PackageManager.PERMISSION_GRANTED) { - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M && permission == Manifest.permission.CHANGE_NETWORK_STATE) { - // Exclude CHANGE_NETWORK_STATE as it does not require explicit user approval. - // This workaround is needed for devices running Android 6.0.0, - // see https://issuetracker.google.com/issues/37067994 - continue + val permissions = packageInfo.requestedPermissions + if (permissions != null) { + for (permission in permissions) { + if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M + && permission == Manifest.permission.CHANGE_NETWORK_STATE) { + // Exclude CHANGE_NETWORK_STATE as it does not require explicit user approval. + // This workaround is needed for devices running Android 6.0.0, + // see https://issuetracker.google.com/issues/37067994 + continue + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && + permission == Manifest.permission.ACCESS_BACKGROUND_LOCATION) { + continue + } + permissionList.add(permission) } - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && - permission == Manifest.permission.ACCESS_BACKGROUND_LOCATION) { - continue - } - permissionList.add(permission) } } } diff --git a/examples/latest/navigate/android/HelloMapKotlin/build.gradle b/examples/latest/navigate/android/HelloMapKotlin/build.gradle index 1e6378cb..7d294cdd 100644 --- a/examples/latest/navigate/android/HelloMapKotlin/build.gradle +++ b/examples/latest/navigate/android/HelloMapKotlin/build.gradle @@ -6,7 +6,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/navigate/android/HelloMapKotlin/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/HelloMapKotlin/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/HelloMapKotlin/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/HelloMapKotlin/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/HelloMapSurface/app/build.gradle b/examples/latest/navigate/android/HelloMapSurface/app/build.gradle index 80841071..661b8f4f 100644 --- a/examples/latest/navigate/android/HelloMapSurface/app/build.gradle +++ b/examples/latest/navigate/android/HelloMapSurface/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.hellomapsurface" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/HelloMapSurface/build.gradle b/examples/latest/navigate/android/HelloMapSurface/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/HelloMapSurface/build.gradle +++ b/examples/latest/navigate/android/HelloMapSurface/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/HelloMapSurface/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/HelloMapSurface/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/HelloMapSurface/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/HelloMapSurface/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/HikingDiary/README.md b/examples/latest/navigate/android/HikingDiary/README.md index 7616468e..f25cfc57 100644 --- a/examples/latest/navigate/android/HikingDiary/README.md +++ b/examples/latest/navigate/android/HikingDiary/README.md @@ -1,4 +1,5 @@ -This app shows how to use positioning to calculate the distance travelled by a user. You can find how this is done in [HikingExample.java](app/src/main/java/com/here/hikingdiary/HikingApp.java). +This app shows how to use positioning to calculate the distance travelled by a user. You can find how this is done in [HikingApp.java](app/src/main/java/com/here/hikingdiary/HikingApp.java). +You can find a complete [tutorial](https://www.here.com/docs/bundle/sdk-for-android-navigate-developer-guide/page/topics/hiking-app-tutorial.html) on building this hiking diary app from scratch, featuring detailed explanations of the algorithms and concepts behind location accuracy and location filters used in building this application. Build instructions: ------------------- diff --git a/examples/latest/navigate/android/HikingDiary/app/build.gradle b/examples/latest/navigate/android/HikingDiary/app/build.gradle index eeec53c7..57090f3e 100644 --- a/examples/latest/navigate/android/HikingDiary/app/build.gradle +++ b/examples/latest/navigate/android/HikingDiary/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.HikingDiary" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/HikingDiary/app/src/main/java/com/here/hikingdiary/MainActivity.java b/examples/latest/navigate/android/HikingDiary/app/src/main/java/com/here/hikingdiary/MainActivity.java index db114f1c..32a1cc82 100644 --- a/examples/latest/navigate/android/HikingDiary/app/src/main/java/com/here/hikingdiary/MainActivity.java +++ b/examples/latest/navigate/android/HikingDiary/app/src/main/java/com/here/hikingdiary/MainActivity.java @@ -133,7 +133,7 @@ public void onClick(View view) { ArrayList entryDescriptions = hikingApp.getMenuEntryDescriptions() != null ? new ArrayList<>(hikingApp.getMenuEntryDescriptions()) : new ArrayList<>(); if (entryKeys.isEmpty()) { - hikingApp.setMessage("No hiking diary entries yet."); + hikingApp.setMessage("No hiking diary entries saved yet."); } else { Bundle bundle = new Bundle(); bundle.putStringArrayList("key_names", entryKeys); diff --git a/examples/latest/navigate/android/HikingDiary/app/src/main/java/com/here/hikingdiary/OutdoorRasterLayer.java b/examples/latest/navigate/android/HikingDiary/app/src/main/java/com/here/hikingdiary/OutdoorRasterLayer.java index b6e690b2..32b2dba3 100644 --- a/examples/latest/navigate/android/HikingDiary/app/src/main/java/com/here/hikingdiary/OutdoorRasterLayer.java +++ b/examples/latest/navigate/android/HikingDiary/app/src/main/java/com/here/hikingdiary/OutdoorRasterLayer.java @@ -16,7 +16,7 @@ * SPDX-License-Identifier: Apache-2.0 * License-Filename: LICENSE */ - + package com.here.hikingdiary; import com.here.sdk.mapview.MapContentType; @@ -98,6 +98,7 @@ private RasterDataSource createRasterDataSource(String dataSourceName) { private MapLayer createMapLayer(String dataSourceName) { // The layer should be rendered on top of other layers except the layers showing the location indicator and polylines/polygons. MapLayerPriority priority = new MapLayerPriorityBuilder() + .renderedAfterLayer("labels") .renderedBeforeLayer("&location_indicator_layer") .renderedBeforeLayer("&polyline_layer") .build(); diff --git a/examples/latest/navigate/android/HikingDiary/build.gradle b/examples/latest/navigate/android/HikingDiary/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/HikingDiary/build.gradle +++ b/examples/latest/navigate/android/HikingDiary/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/HikingDiary/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/HikingDiary/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/HikingDiary/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/HikingDiary/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/IndoorMap/app/build.gradle b/examples/latest/navigate/android/IndoorMap/app/build.gradle index b3a5991c..1bf2ebb9 100644 --- a/examples/latest/navigate/android/IndoorMap/app/build.gradle +++ b/examples/latest/navigate/android/IndoorMap/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.sdk.examples.venues" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/IndoorMap/app/src/main/java/com/here/sdk/examples/venues/MainActivity.java b/examples/latest/navigate/android/IndoorMap/app/src/main/java/com/here/sdk/examples/venues/MainActivity.java index ba4f87bb..373791aa 100644 --- a/examples/latest/navigate/android/IndoorMap/app/src/main/java/com/here/sdk/examples/venues/MainActivity.java +++ b/examples/latest/navigate/android/IndoorMap/app/src/main/java/com/here/sdk/examples/venues/MainActivity.java @@ -20,7 +20,6 @@ package com.here.sdk.examples.venues; import android.content.Context; -import android.content.DialogInterface; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; @@ -31,28 +30,22 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.Spinner; import android.widget.TextView; import android.widget.ToggleButton; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.google.android.material.bottomsheet.BottomSheetBehavior; -import com.google.android.material.bottomsheet.BottomSheetDialog; import com.here.sdk.core.Anchor2D; import com.here.sdk.core.GeoCoordinates; import com.here.sdk.core.Point2D; @@ -72,10 +65,9 @@ import com.here.sdk.venue.control.VenueMap; import com.here.sdk.venue.control.VenueSelectionListener; import com.here.sdk.venue.data.VenueGeometry; -import com.here.sdk.venue.data.VenueGeometryFilterType; import com.here.sdk.venue.data.VenueInfo; import com.here.sdk.venue.data.VenueModel; -import com.here.sdk.venue.service.VenueListener; +import com.here.sdk.venue.service.VenueMapListener; import com.here.sdk.venue.service.VenueService; import com.here.sdk.venue.service.VenueServiceInitStatus; import com.here.sdk.venue.service.VenueServiceListener; @@ -322,7 +314,7 @@ private void onVenueEngineInitCompleted() { // Add needed listeners. service.add(serviceListener); - service.add(venueListener); + service.add(venueMapListener); venueMap.add(venueSelectionListener); venueMap.add(venueInfoListListener); @@ -393,12 +385,12 @@ public void onVenueInfoListLoad(@NonNull final List venueInfoList) { }; // Listener for the venue loading event. - private final VenueListener venueListener = new VenueListener() { + private final VenueMapListener venueMapListener = new VenueMapListener() { @Override - public void onGetVenueCompleted(int venueId, @Nullable VenueModel venueModel, boolean b, @Nullable VenueStyle venueStyle) { + public void onGetVenueCompleted(String venueIdentifier, @Nullable VenueModel venueModel, boolean b, @Nullable VenueStyle venueStyle) { progressBar.setVisibility(View.GONE); if (venueModel == null) { - Log.e(TAG, "Failed to load the venue: " + venueId); + Log.e(TAG, "Failed to load the venue: " + venueIdentifier); } else { mapLoadDone = true; mapView.getCamera().zoomTo(18); @@ -409,7 +401,7 @@ public void onGetVenueCompleted(int venueId, @Nullable VenueModel venueModel, bo venue_search.setHint("Search for Spaces"); String venue_name = ""; for(VenueInfo venue : venueInfo) { - if(venue.getVenueId() == venueId) + if(venue.getVenueIdentifier() == venueIdentifier) venue_name = venue.getVenueName(); } venueName.setText(venue_name); @@ -442,7 +434,7 @@ public void onGetVenueCompleted(int venueId, @Nullable VenueModel venueModel, bo venue_search.setHint("Search for Spaces"); String venue_name = ""; for(VenueInfo venue : venueInfo) { - if(venue.getVenueId() == venueModel.getId()) + if(venue.getVenueIdentifier() == venueModel.getIdentifier()) venue_name = venue.getVenueName(); } venueName.setText(venue_name); @@ -547,7 +539,7 @@ protected void onDestroy() { VenueMap venueMap = venueEngine.getVenueMap(); // remove added listeners service.remove(serviceListener); - service.remove(venueListener); + service.remove(venueMapListener); venueMap.remove(venueSelectionListener); venueMap.remove(venueInfoListListener); venueEngine.destroy(); @@ -630,13 +622,13 @@ public void onVenueItemClicked(VenueInfo venueInfo) { progressBar.setVisibility(View.VISIBLE); try { // Try to parse a venue id. - final int venueId = venueInfo.getVenueId(); + final String venueIdentifier = venueInfo.getVenueIdentifier(); VenueMap venueMap = venueEngine.getVenueMap(); Venue selectedVenue = venueMap.getSelectedVenue(); hideKeyboard(); - if (selectedVenue == null || selectedVenue.getVenueModel().getId() != venueId) { + if (selectedVenue == null || !selectedVenue.getVenueModel().getIdentifier().equals(venueIdentifier)) { // Select a venue by id. - venueMap.selectVenueAsync(venueId, this ::onVenueLoadError); + venueMap.selectVenueAsync(venueIdentifier, this ::onVenueLoadError); } if(sheetBehavior.getState() != BottomSheetBehavior.STATE_COLLAPSED) sheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); diff --git a/examples/latest/navigate/android/IndoorMap/app/src/main/res/layout/activity_main.xml b/examples/latest/navigate/android/IndoorMap/app/src/main/res/layout/activity_main.xml index cac179b8..80fabee2 100644 --- a/examples/latest/navigate/android/IndoorMap/app/src/main/res/layout/activity_main.xml +++ b/examples/latest/navigate/android/IndoorMap/app/src/main/res/layout/activity_main.xml @@ -76,8 +76,9 @@ + + + + + + + + + + + + + + + + + + diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MainActivity.java b/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MainActivity.java new file mode 100644 index 00000000..86b70756 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MainActivity.java @@ -0,0 +1,332 @@ +/* + * 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.mapfeatures; + +import android.content.Context; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; + +import com.here.sdk.core.GeoCoordinates; +import com.here.sdk.core.engine.SDKNativeEngine; +import com.here.sdk.core.engine.SDKOptions; +import com.here.sdk.core.errors.InstantiationErrorException; +import com.here.sdk.mapview.MapError; +import com.here.sdk.mapview.MapMeasure; +import com.here.sdk.mapview.MapScene; +import com.here.sdk.mapview.MapScheme; +import com.here.sdk.mapview.MapView; + +import java.util.Map; + +public class MainActivity extends AppCompatActivity { + + private static final String TAG = MainActivity.class.getSimpleName(); + + private PermissionsRequestor permissionsRequestor; + private MapView mapViewGlobe, mapViewWebMercator; + private MapFeaturesExample mapFeaturesExample; + private MapSchemesExample mapSchemesExample; + private MapScene mapScene; + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Usually, you need to initialize the HERE SDK only once during the lifetime of an application. + initializeHERESDK(); + + setContentView(R.layout.activity_main); + + // Get a MapView instance from layout + mapViewGlobe = findViewById(R.id.map_view_globe); + mapViewGlobe.setVisibility(MapView.VISIBLE); + mapViewWebMercator = findViewById(R.id.map_view_web_mercator); + mapViewWebMercator.setVisibility(MapView.GONE); + mapViewWebMercator.onCreate(savedInstanceState); + mapViewGlobe.onCreate(savedInstanceState); + + handleAndroidPermissions(); + } + + private void initializeHERESDK() { + // Set your credentials for the HERE SDK. + String accessKeyID = "YOUR_ACCESS_KEY_ID"; + String accessKeySecret = "YOUR_ACCESS_KEY_SECRET"; + SDKOptions options = new SDKOptions(accessKeyID, accessKeySecret); + try { + Context context = this; + SDKNativeEngine.makeSharedInstance(context, options); + } catch (InstantiationErrorException e) { + throw new RuntimeException("Initialization of HERE SDK failed: " + e.error.name()); + } + } + + private MapView getCurrentVisibleMapView() { + return mapViewGlobe.getVisibility() == View.VISIBLE ? mapViewGlobe : mapViewWebMercator; + } + + private void changeMapProjection() { + Map enabledFeatures = mapFeaturesExample.getEnabledFeatures(); + MapView mapViewToHide = mapViewGlobe.getVisibility() == View.VISIBLE ? mapViewGlobe : mapViewWebMercator; + MapView mapViewToShow = mapViewGlobe.getVisibility() == View.VISIBLE ? mapViewWebMercator : mapViewGlobe; + + mapViewToHide.setVisibility(View.GONE); + mapViewToShow.setVisibility(View.VISIBLE); + + if (mapSchemesExample != null) { + MapScheme currentScheme = mapSchemesExample.getCurrentMapScheme(); + if (currentScheme == null) { + // Load a default scheme if none is currently set + currentScheme = MapScheme.NORMAL_DAY; + } + mapSchemesExample.loadSchemeForCurrentView(mapViewToShow, currentScheme); + } + + if (mapFeaturesExample != null) { + mapFeaturesExample = new MapFeaturesExample(mapViewToShow.getMapScene()); + mapFeaturesExample.applyEnabledFeaturesForMapScene(mapViewToShow.getMapScene()); + } + + for (Map.Entry feature : enabledFeatures.entrySet()) { + mapFeaturesExample.enableFeature(feature.getKey(), feature.getValue()); + } + } + + private void handleAndroidPermissions() { + permissionsRequestor = new PermissionsRequestor(this); + permissionsRequestor.request(new PermissionsRequestor.ResultListener(){ + + @Override + public void permissionsGranted() { + loadMapScene(); + } + + @Override + public void permissionsDenied() { + Log.e(TAG, "Permissions denied by user."); + } + }); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + permissionsRequestor.onRequestPermissionsResult(requestCode, grantResults); + } + + private void loadMapScene() { + MapView currentMapView = getCurrentVisibleMapView(); + currentMapView.getMapScene().loadScene(MapScheme.NORMAL_DAY, new MapScene.LoadSceneCallback() { + @Override + public void onLoadScene(@Nullable MapError mapError) { + if (mapError == null) { + mapSchemesExample = new MapSchemesExample(); + mapFeaturesExample = new MapFeaturesExample(currentMapView.getMapScene()); + mapFeaturesExample.applyEnabledFeaturesForMapScene(currentMapView.getMapScene()); + + double distanceInMeters = 1000 * 20; + MapMeasure mapMeasureZoom = new MapMeasure(MapMeasure.Kind.DISTANCE, distanceInMeters); + currentMapView.getCamera().lookAt(new GeoCoordinates(52.51760485151816, 13.380312380535472), mapMeasureZoom); + } else { + Log.d(TAG, "onLoadScene failed: " + mapError); + } + } + }); + } + + @Override + protected void onPause() { + mapViewGlobe.onPause(); + super.onPause(); + } + + @Override + protected void onResume() { + mapViewGlobe.onResume(); + super.onResume(); + } + + @Override + protected void onDestroy() { + mapViewGlobe.onDestroy(); + disposeHERESDK(); + super.onDestroy(); + } + + @Override + protected void onSaveInstanceState(@NonNull Bundle outState) { + mapViewGlobe.onSaveInstanceState(outState); + super.onSaveInstanceState(outState); + } + + private void disposeHERESDK() { + // Free HERE SDK resources before the application shuts down. + // Usually, this should be called only on application termination. + // Afterwards, the HERE SDK is no longer usable unless it is initialized again. + SDKNativeEngine sdkNativeEngine = SDKNativeEngine.getSharedInstance(); + if (sdkNativeEngine != null) { + sdkNativeEngine.dispose(); + // For safety reasons, we explicitly set the shared instance to null to avoid situations, + // where a disposed instance is accidentally reused. + SDKNativeEngine.setSharedInstance(null); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + MenuInflater inflater=getMenuInflater(); + inflater.inflate(R.menu.map_option_menu, menu); + return true; + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + MapView currentMapView = getCurrentVisibleMapView(); + switch (item.getItemId()){ + // Map Schemes: + case R.id.hybrid_day_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.HYBRID_DAY); + return true; + case R.id.hybrid_night_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.HYBRID_NIGHT); + return true; + case R.id.lite_day_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.LITE_DAY); + return true; + case R.id.lite_night_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.LITE_NIGHT); + return true; + case R.id.lite_hybrid_night_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.LITE_HYBRID_NIGHT); + return true; + case R.id.lite_hybrid_day_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.LITE_HYBRID_DAY); + return true; + case R.id.logistics_day_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.LOGISTICS_DAY); + return true; + case R.id.logistics_night_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.LOGISTICS_NIGHT); + return true; + case R.id.logistics_hybrid_day_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.LOGISTICS_HYBRID_DAY); + return true; + case R.id.logistics_hybrid_night_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.LOGISTICS_HYBRID_NIGHT); + return true; + case R.id.normal_day_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.NORMAL_DAY); + return true; + case R.id.normal_night_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.NORMAL_NIGHT); + return true; + case R.id.road_network_day_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.ROAD_NETWORK_DAY); + return true; + case R.id.road_network_night_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.ROAD_NETWORK_NIGHT); + return true; + case R.id.satellite_menu_item: + mapSchemesExample.loadSchemeForCurrentView(currentMapView, MapScheme.SATELLITE); + return true; + + // Map Features: + case R.id.clear_menu_item: + mapFeaturesExample.disableFeatures(); + return true; + case R.id.building_footprints_menu_item: + mapFeaturesExample.enableBuildingFootprints(); + return true; + case R.id.congestion_zone_menu_item: + mapFeaturesExample.enableCongestionZones(); + return true; + case R.id.environmental_zones_menu_item: + mapFeaturesExample.enableEnvironmentalZones(); + return true; + case R.id.extruded_buildings_menu_item: + mapFeaturesExample.enableExtrudedBuildings(); + return true; + case R.id.landmarks_textured_menu_item: + mapFeaturesExample.enableLandmarksTextured(); + return true; + case R.id.landmarks_textureless_menu_item: + mapFeaturesExample.enableLandmarksTextureless(); + return true; + case R.id.safety_cameras_menu_item: + mapFeaturesExample.enableSafetyCameras(); + return true; + case R.id.shadows_menu_item: + mapFeaturesExample.enableShadows(); + return true; + case R.id.terrain_hillshade_menu_item: + mapFeaturesExample.enableTerrainHillShade(); + return true; + case R.id.terrain_3D_menu_item: + mapFeaturesExample.enableTerrain3D(); + return true; + case R.id.traffic_flow_with_freeflow_menu_item: + mapFeaturesExample.enableTrafficFlowWithFreeFlow(); + return true; + case R.id.traffic_flow_without_freeflow_menu_item: + mapFeaturesExample.enableTrafficFlowWithoutFreeFlow(); + return true; + case R.id.traffic_incidents_menu_item: + mapFeaturesExample.enableTrafficIncidents(); + return true; + case R.id.vehicle_restrictions_active_menu_item: + mapFeaturesExample.enableVehicleRestrictionsActive(); + return true; + case R.id.vehicle_restrictions_active_inactive_menu_item: + mapFeaturesExample.enableVehicleRestrictionsActiveAndInactive(); + return true; + case R.id.vehicle_restrictions_active_inactive_diff_menu_item: + mapFeaturesExample.enableVehicleRestrictionsActiveAndInactiveDiff(); + return true; + case R.id.road_exit_labels_menu_item: + mapFeaturesExample.enableRoadExitLabels(); + return true; + case R.id.road_exit_labels_numbers_menu_item: + mapFeaturesExample.enableRoadExitLabelsNumbersOnly(); + return true; + case R.id.ambient_occlusion_menu_item: + mapFeaturesExample.enableAmbientOcclusion(); + return true; + case R.id.contours_menu_item: + mapFeaturesExample.enableContours(); + return true; + case R.id.low_speed_zones_menu_item: + mapFeaturesExample.enableLowSpeedZones(); + return true; + case R.id.web_mercator: + changeMapProjection(); + return true; + default: + return super.onOptionsItemSelected(item); + } + } +} diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MapFeaturesExample.java b/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MapFeaturesExample.java new file mode 100644 index 00000000..2deacaa5 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MapFeaturesExample.java @@ -0,0 +1,162 @@ +/* + * 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.mapfeatures; + +import com.here.sdk.mapview.MapFeatureModes; +import com.here.sdk.mapview.MapFeatures; +import com.here.sdk.mapview.MapScene; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +public class MapFeaturesExample { + + private final MapScene mapScene; + private Map mapFeatures = new HashMap<>(); + + public MapFeaturesExample(MapScene mapScene) { + this.mapScene = mapScene; + } + + public void disableFeatures() { + mapScene.disableFeatures(new ArrayList<>(mapFeatures.keySet())); + } + + + public void enableBuildingFootprints() { + mapFeatures.put(MapFeatures.BUILDING_FOOTPRINTS, MapFeatureModes.BUILDING_FOOTPRINTS_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableAmbientOcclusion() { + mapFeatures.put(MapFeatures.AMBIENT_OCCLUSION, MapFeatureModes.AMBIENT_OCCLUSION_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableContours() { + mapFeatures.put(MapFeatures.CONTOURS, MapFeatureModes.CONTOURS_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableLowSpeedZones() { + mapFeatures.put(MapFeatures.LOW_SPEED_ZONES, MapFeatureModes.LOW_SPEED_ZONES_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableCongestionZones() { + mapFeatures.put(MapFeatures.CONGESTION_ZONES, MapFeatureModes.CONGESTION_ZONES_ALL); + mapScene.enableFeatures( mapFeatures); + } + + public void enableEnvironmentalZones() { + mapFeatures.put(MapFeatures.ENVIRONMENTAL_ZONES, MapFeatureModes.ENVIRONMENTAL_ZONES_ALL); + mapScene.enableFeatures( mapFeatures); + } + + public void enableExtrudedBuildings() { + mapFeatures.put(MapFeatures.EXTRUDED_BUILDINGS, MapFeatureModes.EXTRUDED_BUILDINGS_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableLandmarksTextured() { + mapFeatures.put(MapFeatures.LANDMARKS, MapFeatureModes.LANDMARKS_TEXTURED); + mapScene.enableFeatures(mapFeatures); + } + + public void enableLandmarksTextureless() { + mapFeatures.put(MapFeatures.LANDMARKS, MapFeatureModes.LANDMARKS_TEXTURELESS); + mapScene.enableFeatures(mapFeatures); + } + + public void enableSafetyCameras() { + mapFeatures.put(MapFeatures.SAFETY_CAMERAS, MapFeatureModes.SAFETY_CAMERAS_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableShadows() { + mapFeatures.put(MapFeatures.SHADOWS, MapFeatureModes.SHADOWS_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableTerrainHillShade() { + mapFeatures.put(MapFeatures.TERRAIN, MapFeatureModes.TERRAIN_HILLSHADE); + mapScene.enableFeatures(mapFeatures); + } + + public void enableTerrain3D() { + mapFeatures.put(MapFeatures.TERRAIN, MapFeatureModes.TERRAIN_3D); + mapScene.enableFeatures(mapFeatures); + } + + public void enableTrafficFlowWithFreeFlow() { + mapFeatures.put(MapFeatures.TRAFFIC_FLOW, MapFeatureModes.TRAFFIC_FLOW_WITH_FREE_FLOW); + mapScene.enableFeatures(mapFeatures); + } + + public void enableTrafficFlowWithoutFreeFlow() { + mapFeatures.put(MapFeatures.TRAFFIC_FLOW, MapFeatureModes.TRAFFIC_FLOW_WITHOUT_FREE_FLOW); + mapScene.enableFeatures(mapFeatures); + } + + public void enableTrafficIncidents() { + mapFeatures.put(MapFeatures.TRAFFIC_INCIDENTS, MapFeatureModes.TRAFFIC_INCIDENTS_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableVehicleRestrictionsActive() { + mapFeatures.put(MapFeatures.VEHICLE_RESTRICTIONS, MapFeatureModes.VEHICLE_RESTRICTIONS_ACTIVE); + mapScene.enableFeatures(mapFeatures); + } + + public void enableVehicleRestrictionsActiveAndInactive() { + mapFeatures.put(MapFeatures.VEHICLE_RESTRICTIONS, MapFeatureModes.VEHICLE_RESTRICTIONS_ACTIVE_AND_INACTIVE); + mapScene.enableFeatures(mapFeatures); + } + + public void enableVehicleRestrictionsActiveAndInactiveDiff() { + mapFeatures.put(MapFeatures.VEHICLE_RESTRICTIONS, MapFeatureModes.VEHICLE_RESTRICTIONS_ACTIVE_AND_INACTIVE_DIFFERENTIATED); + mapScene.enableFeatures(mapFeatures); + } + + public void enableRoadExitLabels() { + mapFeatures.put(MapFeatures.ROAD_EXIT_LABELS, MapFeatureModes.ROAD_EXIT_LABELS_ALL); + mapScene.enableFeatures(mapFeatures); + } + + public void enableRoadExitLabelsNumbersOnly() { + mapFeatures.put(MapFeatures.ROAD_EXIT_LABELS, MapFeatureModes.ROAD_EXIT_LABELS_NUMBERS_ONLY); + mapScene.enableFeatures(mapFeatures); + } + + public Map getEnabledFeatures() { + return new HashMap<>(mapFeatures); + } + + public void applyEnabledFeaturesForMapScene(MapScene targetMapScene) { + targetMapScene.enableFeatures(mapFeatures); + } + + public void enableFeature(String featureKey, String featureMode) { + Map featureMap = new HashMap<>(); + featureMap.put(featureKey, featureMode); + mapScene.enableFeatures(featureMap); + } +} diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MapSchemesExample.java b/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MapSchemesExample.java new file mode 100644 index 00000000..e76e19df --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/MapSchemesExample.java @@ -0,0 +1,55 @@ +/* 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.mapfeatures; + +import android.util.Log; + +import androidx.annotation.Nullable; + +import com.here.sdk.mapview.MapError; +import com.here.sdk.mapview.MapScene; +import com.here.sdk.mapview.MapScheme; +import com.here.sdk.mapview.MapView; + +public class MapSchemesExample { + + private MapScheme currentMapScheme; + + public MapSchemesExample() { + } + + private void loadMapScene(MapView mapView, MapScheme mode) { + currentMapScheme = mode; + mapView.getMapScene().loadScene(mode, new MapScene.LoadSceneCallback() { + @Override + public void onLoadScene(@Nullable MapError mapError) { + if (mapError == null) { + // Map scene loaded successfully + } else { + Log.d("loadMapScene()", "Loading map failed: mapError: " + mapError.name()); + } + } + }); + } + + public MapScheme getCurrentMapScheme() { + return currentMapScheme; + } + + public void loadSchemeForCurrentView(MapView currentMapView, MapScheme mapScheme) { + loadMapScene(currentMapView, mapScheme); + } +} diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/PermissionsRequestor.java b/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/PermissionsRequestor.java new file mode 100644 index 00000000..761219a4 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/java/com/here/mapfeatures/PermissionsRequestor.java @@ -0,0 +1,126 @@ +/* + * 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.mapfeatures; + +import android.Manifest; +import android.app.Activity; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager; +import android.os.Build; + +import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; + +import java.util.ArrayList; + +/** + * Convenience class to request the Android permissions as defined by manifest. + */ +public class PermissionsRequestor { + + private static final int PERMISSIONS_REQUEST_CODE = 42; + private ResultListener resultListener; + private final Activity activity; + + public PermissionsRequestor(Activity activity) { + this.activity = activity; + } + + public interface ResultListener { + void permissionsGranted(); + void permissionsDenied(); + } + + public void request(ResultListener resultListener) { + this.resultListener = resultListener; + + String[] missingPermissions = getPermissionsToRequest(); + if (missingPermissions.length == 0) { + resultListener.permissionsGranted(); + } else { + ActivityCompat.requestPermissions(activity, missingPermissions, PERMISSIONS_REQUEST_CODE); + } + } + + @SuppressWarnings("deprecation") + private String[] getPermissionsToRequest() { + ArrayList permissionList = new ArrayList<>(); + try { + String packageName = activity.getPackageName(); + PackageInfo packageInfo; + if (Build.VERSION.SDK_INT >= 33) { + packageInfo = activity.getPackageManager().getPackageInfo( + packageName, + PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS)); + } else { + packageInfo = activity.getPackageManager().getPackageInfo( + packageName, + PackageManager.GET_PERMISSIONS); + } + if (packageInfo.requestedPermissions != null) { + for (String permission : packageInfo.requestedPermissions) { + if (ContextCompat.checkSelfPermission( + activity, permission) != PackageManager.PERMISSION_GRANTED) { + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.M && + permission.equals(Manifest.permission.CHANGE_NETWORK_STATE)) { + // Exclude CHANGE_NETWORK_STATE as it does not require explicit user approval. + // This workaround is needed for devices running Android 6.0.0, + // see https://issuetracker.google.com/issues/37067994 + continue; + } + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && + permission.equals(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) { + continue; + } + permissionList.add(permission); + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + return permissionList.toArray(new String[0]); + } + + public void onRequestPermissionsResult(int requestCode, @NonNull int[] grantResults) { + if (resultListener == null) { + return; + } + + if (grantResults.length == 0) { + // Request was cancelled. + return; + } + + if (requestCode == PERMISSIONS_REQUEST_CODE) { + boolean allGranted = true; + for (int result : grantResults) { + allGranted &= result == PackageManager.PERMISSION_GRANTED; + } + + if (allGranted) { + resultListener.permissionsGranted(); + } else { + resultListener.permissionsDenied(); + } + } + } +} diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/drawable/ic_launcher_background.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 00000000..d5fccc53 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/drawable/ic_launcher_foreground.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 00000000..701988f4 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/layout/activity_main.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000..8dbce3d7 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,22 @@ + + + + + + + + + diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/menu/map_option_menu.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/menu/map_option_menu.xml new file mode 100644 index 00000000..0bcd0241 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/menu/map_option_menu.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 00000000..eca70cfe --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 00000000..720b89ef --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-hdpi/ic_launcher.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 00000000..a2f59082 Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 00000000..1b523998 Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-mdpi/ic_launcher.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 00000000..ff10afd6 Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 00000000..115a4c76 Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 00000000..dcd3cd80 Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 00000000..459ca609 Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 00000000..8ca12fe0 Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..8e19b410 Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 00000000..b824ebdd Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 00000000..4c19a13c Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/colors.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/colors.xml new file mode 100644 index 00000000..3ab3e9cb --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #3F51B5 + #303F9F + #FF4081 + diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/strings.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/strings.xml new file mode 100644 index 00000000..ff2c20bc --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Map Items Example - HERE SDK for Android + diff --git a/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/styles.xml b/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/styles.xml new file mode 100644 index 00000000..5885930d --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + diff --git a/examples/latest/navigate/android/MapFeatures/build.gradle b/examples/latest/navigate/android/MapFeatures/build.gradle new file mode 100644 index 00000000..39c2ed54 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/build.gradle @@ -0,0 +1,33 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + + repositories { + google() + mavenCentral() + } + dependencies { + classpath 'com.android.tools.build:gradle:8.7.3' + + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + google() + mavenCentral() + } + + gradle.projectsEvaluated { + tasks.withType(JavaCompile) { + options.deprecation = true + } + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/examples/latest/navigate/android/MapFeatures/gradle.properties b/examples/latest/navigate/android/MapFeatures/gradle.properties new file mode 100644 index 00000000..87cac57e --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/gradle.properties @@ -0,0 +1,23 @@ +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html + +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +android.defaults.buildfeatures.buildconfig=true +android.enableJetifier=true +android.nonFinalResIds=false +android.nonTransitiveRClass=false +android.useAndroidX=true +org.gradle.jvmargs=-Xmx1536m + +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true + diff --git a/examples/latest/navigate/android/MapFeatures/gradle/wrapper/gradle-wrapper.jar b/examples/latest/navigate/android/MapFeatures/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..7a3265ee Binary files /dev/null and b/examples/latest/navigate/android/MapFeatures/gradle/wrapper/gradle-wrapper.jar differ diff --git a/examples/latest/navigate/android/MapFeatures/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/MapFeatures/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..c3bd7afb --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat May 30 01:02:29 CEST 2020 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/MapFeatures/gradlew b/examples/latest/navigate/android/MapFeatures/gradlew new file mode 100644 index 00000000..cccdd3d5 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/examples/latest/navigate/android/MapFeatures/gradlew.bat b/examples/latest/navigate/android/MapFeatures/gradlew.bat new file mode 100644 index 00000000..f9553162 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/gradlew.bat @@ -0,0 +1,84 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/examples/latest/navigate/android/MapFeatures/settings.gradle b/examples/latest/navigate/android/MapFeatures/settings.gradle new file mode 100644 index 00000000..e7b4def4 --- /dev/null +++ b/examples/latest/navigate/android/MapFeatures/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/examples/latest/navigate/android/MapItems/app/build.gradle b/examples/latest/navigate/android/MapItems/app/build.gradle index 3e33242b..426648e8 100644 --- a/examples/latest/navigate/android/MapItems/app/build.gradle +++ b/examples/latest/navigate/android/MapItems/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.mapitems" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/MapItems/build.gradle b/examples/latest/navigate/android/MapItems/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/navigate/android/MapItems/build.gradle +++ b/examples/latest/navigate/android/MapItems/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/navigate/android/MapItems/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/MapItems/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/MapItems/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/MapItems/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/MultiDisplays/app/build.gradle b/examples/latest/navigate/android/MultiDisplays/app/build.gradle index 9a08c246..48d0e334 100644 --- a/examples/latest/navigate/android/MultiDisplays/app/build.gradle +++ b/examples/latest/navigate/android/MultiDisplays/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.multidisplays" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/MultiDisplays/build.gradle b/examples/latest/navigate/android/MultiDisplays/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/MultiDisplays/build.gradle +++ b/examples/latest/navigate/android/MultiDisplays/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/MultiDisplays/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/MultiDisplays/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/MultiDisplays/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/MultiDisplays/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/Navigation/app/build.gradle b/examples/latest/navigate/android/Navigation/app/build.gradle index 323ebef6..e4b48bd9 100644 --- a/examples/latest/navigate/android/Navigation/app/build.gradle +++ b/examples/latest/navigate/android/Navigation/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.navigation" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/Navigation/app/src/main/java/com/here/navigation/NavigationEventHandler.java b/examples/latest/navigate/android/Navigation/app/src/main/java/com/here/navigation/NavigationEventHandler.java index 156426a2..5b12430e 100644 --- a/examples/latest/navigate/android/Navigation/app/src/main/java/com/here/navigation/NavigationEventHandler.java +++ b/examples/latest/navigate/android/Navigation/app/src/main/java/com/here/navigation/NavigationEventHandler.java @@ -23,11 +23,11 @@ import android.media.Ringtone; import android.media.RingtoneManager; import android.net.Uri; -import android.os.Handler; import android.util.Log; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.here.sdk.core.GeoCoordinates; import com.here.sdk.core.LanguageCode; @@ -110,6 +110,8 @@ import com.here.sdk.routing.RoadType; import com.here.sdk.routing.Route; import com.here.sdk.routing.RoutingEngine; +import com.here.sdk.routing.RoutingError; +import com.here.sdk.routing.TrafficOnRoute; import com.here.sdk.trafficawarenavigation.DynamicRoutingEngine; import com.here.sdk.transport.GeneralVehicleSpeedLimits; @@ -131,11 +133,7 @@ public class NavigationEventHandler { private final TextView messageView; private final TimeUtils timeUtils; private final RoutingEngine routingEngine; - private int traveledDistanceOnLastSectionInMeters; - private int lastTraveledSectionIndex; - private Route currentRoute; - private Handler trafficOnRouteUpdateHandler; - private Runnable trafficUpdateRunnable; + private long lastTrafficUpdateInMilliseconds = 0l; public NavigationEventHandler(Context context, TextView messageView) { this.context = context; @@ -160,17 +158,6 @@ public void setupListeners(VisualNavigator visualNavigator, DynamicRoutingEngine visualNavigator.setRouteProgressListener(new RouteProgressListener() { @Override public void onRouteProgressUpdated(@NonNull RouteProgress routeProgress) { - List sectionProgressList = routeProgress.sectionProgress; - // sectionProgressList is guaranteed to be non-empty. - SectionProgress lastSectionProgress = sectionProgressList.get(sectionProgressList.size() - 1); - traveledDistanceOnLastSectionInMeters = visualNavigator.getRoute().getLengthInMeters() - lastSectionProgress.remainingDistanceInMeters; - lastTraveledSectionIndex = routeProgress.sectionIndex; - currentRoute = visualNavigator.getRoute(); - String currentETAString = "ETA: " + timeUtils.getETAinDeviceTimeZone((int) lastSectionProgress.remainingDuration.toSeconds()); - Log.d(TAG, "Distance to destination in meters: " + lastSectionProgress.remainingDistanceInMeters); - Log.d(TAG, "Traffic delay ahead in seconds: " + lastSectionProgress.trafficDelay.getSeconds()); - // Logs current ETA. - Log.d(TAG, currentETAString); // Contains the progress for the next maneuver ahead and the next-next maneuvers, if any. List nextManeuverList = routeProgress.maneuverProgress; @@ -213,6 +200,8 @@ public void onRouteProgressUpdated(@NonNull RouteProgress routeProgress) { roundaboutAngle + " degrees to reach the exit."); } + String currentETAString = getETA(routeProgress); + if (previousManeuverIndex != nextManeuverIndex) { currentETAString = currentETAString + "\nNew maneuver: " + logMessage; } else { @@ -228,6 +217,8 @@ public void onRouteProgressUpdated(@NonNull RouteProgress routeProgress) { // We periodically want to search for better traffic-optimized routes. dynamicRoutingEngine.updateCurrentLocation(lastMapMatchedLocation, routeProgress.sectionIndex); } + + updateTrafficOnRoute(routeProgress, visualNavigator); } }); @@ -765,6 +756,18 @@ public void onTollStopWarning(@NonNull TollStop tollStop) { }); } + private String getETA(RouteProgress routeProgress) { + List sectionProgressList = routeProgress.sectionProgress; + // sectionProgressList is guaranteed to be non-empty. + SectionProgress lastSectionProgress = sectionProgressList.get(sectionProgressList.size() - 1); + String currentETAString = "ETA: " + timeUtils.getETAinDeviceTimeZone((int) lastSectionProgress.remainingDuration.toSeconds()); + Log.d(TAG, "Distance to destination in meters: " + lastSectionProgress.remainingDistanceInMeters); + Log.d(TAG, "Traffic delay ahead in seconds: " + lastSectionProgress.trafficDelay.getSeconds()); + // Logs current ETA. + Log.d(TAG, currentETAString); + return currentETAString; + } + private void setupSpeedWarnings(VisualNavigator visualNavigator) { SpeedLimitOffset speedLimitOffset = new SpeedLimitOffset(); speedLimitOffset.lowSpeedOffsetInMetersPerSecond = 2; @@ -944,24 +947,42 @@ private void logLaneAccess(int laneNumber, LaneAccess laneAccess) { Log.d(TAG, "Motorcycles are allowed on this lane: " + laneAccess.motorcycles); } - // Starts periodic updates of the traffic on the route. - public void startPeriodicTrafficUpdateOnRoute(CalculateTrafficOnRouteCallback calculateTrafficOnRouteCallback, long updateIntervalInSeconds){ - trafficOnRouteUpdateHandler = new Handler(); - trafficUpdateRunnable = new Runnable() { - @Override - public void run() { - routingEngine.calculateTrafficOnRoute(currentRoute, lastTraveledSectionIndex, traveledDistanceOnLastSectionInMeters, calculateTrafficOnRouteCallback); - trafficOnRouteUpdateHandler.postDelayed(this,updateIntervalInSeconds); - } - }; - // Refresh traffic after the specified interval. - trafficOnRouteUpdateHandler.post(trafficUpdateRunnable); - } + // Periodically updates the traffic information for the current route. + // This method checks whether the last traffic update occurred within the specified interval and skips the update if not. + // Then it calculates the current traffic conditions along the route using the `RoutingEngine`. + // Lastly, it updates the `VisualNavigator` with the newly calculated `TrafficOnRoute` object, + // which affects the `RouteProgress` duration without altering the route geometry or distance. + public void updateTrafficOnRoute(RouteProgress routeProgress, VisualNavigator visualNavigator) { + Route currentRoute = visualNavigator.getRoute(); + if (currentRoute == null) { + // Should never happen. + return; + } - // Stops periodic updates of the traffic on the route. - public void stopPeriodicTrafficUpdateOnRoute() { - if (trafficOnRouteUpdateHandler != null) { - trafficOnRouteUpdateHandler.removeCallbacks(trafficUpdateRunnable); + long trafficUpdateIntervalInMilliseconds = 3 * 60000; // 3 minutes. + long now = System.currentTimeMillis(); + if ((now - lastTrafficUpdateInMilliseconds) < trafficUpdateIntervalInMilliseconds) { + return; } + // Store the current time when we update trafficOnRoute. + lastTrafficUpdateInMilliseconds = now; + + List sectionProgressList = routeProgress.sectionProgress; + SectionProgress lastSectionProgress = sectionProgressList.get(sectionProgressList.size() - 1); + int traveledDistanceOnLastSectionInMeters = currentRoute.getLengthInMeters() - lastSectionProgress.remainingDistanceInMeters; + int lastTraveledSectionIndex = routeProgress.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; + } + Log.d(TAG, "Updated traffic on route"); + // Sets traffic data for the current route, affecting RouteProgress duration in SectionProgress, while preserving route distance and geometry. + visualNavigator.setTrafficOnRoute(trafficOnRoute); + } + }); } } diff --git a/examples/latest/navigate/android/Navigation/app/src/main/java/com/here/navigation/NavigationExample.java b/examples/latest/navigate/android/Navigation/app/src/main/java/com/here/navigation/NavigationExample.java index 3b835314..977e342f 100644 --- a/examples/latest/navigate/android/Navigation/app/src/main/java/com/here/navigation/NavigationExample.java +++ b/examples/latest/navigate/android/Navigation/app/src/main/java/com/here/navigation/NavigationExample.java @@ -36,10 +36,8 @@ import com.here.sdk.navigation.SpeedBasedCameraBehavior; import com.here.sdk.navigation.VisualNavigator; import com.here.sdk.prefetcher.RoutePrefetcher; -import com.here.sdk.routing.CalculateTrafficOnRouteCallback; import com.here.sdk.routing.Route; import com.here.sdk.routing.RoutingError; -import com.here.sdk.routing.TrafficOnRoute; import com.here.sdk.trafficawarenavigation.DynamicRoutingEngine; import com.here.sdk.trafficawarenavigation.DynamicRoutingEngineOptions; import com.here.sdk.trafficawarenavigation.DynamicRoutingListener; @@ -60,7 +58,6 @@ public class NavigationExample { private RoutePrefetcher routePrefetcher; private final NavigationEventHandler navigationEventHandler; private final TextView messageView; - private CalculateTrafficOnRouteCallback calculateTrafficOnRouteCallback; public NavigationExample(Context context, MapView mapView, TextView messageView) { this.messageView = messageView; @@ -153,16 +150,6 @@ public void startNavigation(Route route, boolean isSimulated, boolean isCameraTr // Synchronize with the toggle button state. updateCameraTracking(isCameraTrackingEnabled); - - navigationEventHandler.startPeriodicTrafficUpdateOnRoute((routingError, trafficOnRoute) -> { - if (routingError != null) { - Log.d(TAG, "CalculateTrafficOnRoute error: " + routingError.name()); - return; - } - Log.d(TAG, "Updated traffic on route"); - // Sets traffic data for the current route, affecting RouteProgress duration in SectionProgress, while preserving route distance and geometry. - visualNavigator.setTrafficOnRoute(trafficOnRoute); - }, 1000); } private void startDynamicSearchForBetterRoutes(Route route) { @@ -209,8 +196,6 @@ public void stopNavigation(boolean isCameraTrackingEnabled) { dynamicRoutingEngine.stop(); routePrefetcher.stopPrefetchAroundRoute(); - navigationEventHandler.stopPeriodicTrafficUpdateOnRoute(); - // Synchronize with the toggle button state. updateCameraTracking(isCameraTrackingEnabled); } diff --git a/examples/latest/navigate/android/Navigation/build.gradle b/examples/latest/navigate/android/Navigation/build.gradle index 60c8e226..39c2ed54 100644 --- a/examples/latest/navigate/android/Navigation/build.gradle +++ b/examples/latest/navigate/android/Navigation/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong diff --git a/examples/latest/navigate/android/Navigation/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/Navigation/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/Navigation/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/Navigation/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/NavigationCustom/app/build.gradle b/examples/latest/navigate/android/NavigationCustom/app/build.gradle index 50fe9ad3..986b175f 100644 --- a/examples/latest/navigate/android/NavigationCustom/app/build.gradle +++ b/examples/latest/navigate/android/NavigationCustom/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.navigationcustom" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/NavigationCustom/build.gradle b/examples/latest/navigate/android/NavigationCustom/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/NavigationCustom/build.gradle +++ b/examples/latest/navigate/android/NavigationCustom/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/NavigationCustom/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/NavigationCustom/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/NavigationCustom/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/NavigationCustom/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/NavigationQuickStart/app/build.gradle b/examples/latest/navigate/android/NavigationQuickStart/app/build.gradle index 740e5c5e..59ca5de8 100644 --- a/examples/latest/navigate/android/NavigationQuickStart/app/build.gradle +++ b/examples/latest/navigate/android/NavigationQuickStart/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.navigationquickstart" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/NavigationQuickStart/build.gradle b/examples/latest/navigate/android/NavigationQuickStart/build.gradle index 1aaa3cdf..527046ea 100644 --- a/examples/latest/navigate/android/NavigationQuickStart/build.gradle +++ b/examples/latest/navigate/android/NavigationQuickStart/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.5.2' + classpath 'com.android.tools.build:gradle:8.7.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/examples/latest/navigate/android/NavigationQuickStart/gradle/wrapper/gradle-wrapper.properties b/examples/latest/navigate/android/NavigationQuickStart/gradle/wrapper/gradle-wrapper.properties index 0709a8f7..c3bd7afb 100644 --- a/examples/latest/navigate/android/NavigationQuickStart/gradle/wrapper/gradle-wrapper.properties +++ b/examples/latest/navigate/android/NavigationQuickStart/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/examples/latest/navigate/android/OfflineMaps/app/build.gradle b/examples/latest/navigate/android/OfflineMaps/app/build.gradle index acb8d495..d15709df 100644 --- a/examples/latest/navigate/android/OfflineMaps/app/build.gradle +++ b/examples/latest/navigate/android/OfflineMaps/app/build.gradle @@ -1,11 +1,11 @@ apply plugin: 'com.android.application' android { - compileSdk 34 + compileSdk 35 defaultConfig { applicationId "com.here.offlinemaps" minSdkVersion 24 - targetSdkVersion 34 + targetSdkVersion 35 versionCode 1 versionName "1.0" } diff --git a/examples/latest/navigate/android/OfflineMaps/app/src/main/java/com/here/offlinemaps/MainActivity.java b/examples/latest/navigate/android/OfflineMaps/app/src/main/java/com/here/offlinemaps/MainActivity.java index 0fe7dbe5..12989247 100644 --- a/examples/latest/navigate/android/OfflineMaps/app/src/main/java/com/here/offlinemaps/MainActivity.java +++ b/examples/latest/navigate/android/OfflineMaps/app/src/main/java/com/here/offlinemaps/MainActivity.java @@ -106,7 +106,7 @@ private void loadMapScene() { @Override public void onLoadScene(@Nullable MapError mapError) { if (mapError == null) { - offlineMapsExample = new OfflineMapsExample(mapView); + offlineMapsExample = new OfflineMapsExample(mapView, MainActivity.this); } else { Log.d(TAG, "onLoadScene failed: " + mapError.toString()); } @@ -169,6 +169,10 @@ public void onSearchPlaceClicked(View view) { offlineMapsExample.onSearchPlaceClicked(); } + public void onAreaClicked(View view) { + offlineMapsExample.onDownloadAreaClicked(); + } + public void clearCache(View view){ offlineMapsExample.clearCache(); } diff --git a/examples/latest/navigate/android/OfflineMaps/app/src/main/java/com/here/offlinemaps/OfflineMapsExample.java b/examples/latest/navigate/android/OfflineMaps/app/src/main/java/com/here/offlinemaps/OfflineMapsExample.java index ced81933..d30b7790 100644 --- a/examples/latest/navigate/android/OfflineMaps/app/src/main/java/com/here/offlinemaps/OfflineMapsExample.java +++ b/examples/latest/navigate/android/OfflineMaps/app/src/main/java/com/here/offlinemaps/OfflineMapsExample.java @@ -19,6 +19,7 @@ package com.here.offlinemaps; +import android.app.AlertDialog; import android.content.Context; import android.os.Bundle; import android.util.Log; @@ -29,7 +30,9 @@ import com.google.android.material.snackbar.Snackbar; import com.here.sdk.core.GeoBox; import com.here.sdk.core.GeoCoordinates; +import com.here.sdk.core.GeoPolygon; import com.here.sdk.core.LanguageCode; +import com.here.sdk.core.Point2D; import com.here.sdk.core.engine.LayerConfiguration; import com.here.sdk.core.engine.SDKBuildInformation; import com.here.sdk.core.engine.SDKNativeEngine; @@ -76,6 +79,7 @@ public class OfflineMapsExample { + private final Context context; private final MapView mapView; @Nullable private MapDownloader mapDownloader; @@ -89,7 +93,8 @@ public class OfflineMapsExample { private boolean offlineSearchLayerEnabled = true; private boolean switchOffline = false; - public OfflineMapsExample(MapView mapView) { + public OfflineMapsExample(MapView mapView, Context context) { + this.context = context; // Configure the map. this.mapView = mapView; @@ -497,7 +502,7 @@ public void onCompleted(@Nullable PersistentMapRepairError persistentMapRepairEr // healing option listed in the API Reference. For example, if the status // is PENDING_UPDATE, it cannot be repaired, but instead an update // should be executed. It is recommended to inform your users to - // perform the recommended action. + // perform the recommended action. Log.d("RepairPersistentMap", "Repair operation failed: " + persistentMapRepairError.name()); } }); @@ -509,8 +514,8 @@ public void toggleLayerConfiguration(String accessKeyID, String accessKeySecret, // After modifying the "FeatureConfiguration" calling performFeatureUpdate() // will also clear the cache if at least one region has been installed. // This app allows the user to install one region for testing purposes. - // In order to simplify testing when no region has been installed, we - // explicitly clear the cache. + // In order to simplify testing when no region has been installed, we + // explicitly clear the cache. // If the cache is not cleared, the HERE SDK will look for cached data, for example, // when using the OfflineSearchEngine. try { @@ -656,6 +661,76 @@ private void logCurrentMapVersion() { } } + // Download the rectangular area that is currently visible in the viewport. + // It is possible to call this method in parallel to download multiple areas in parallel. + public void onDownloadAreaClicked() { + showDialog("Note", "Downloading the area that is currently visible in the viewport."); + GeoPolygon polygonArea = new GeoPolygon(getMapViewGeoBox()); + + mapDownloader.downloadArea(polygonArea, new DownloadRegionsStatusListener() { + @Override + public void onDownloadRegionsComplete(@Nullable MapLoaderError mapLoaderError, @Nullable List list) { + if (mapLoaderError != null) { + String message = "Download area completion error: " + mapLoaderError; + snackbar.setText(message).show(); + return; + } + + // If error is null, it is guaranteed that the regions will not be null. + // When downloading an area, only a single unique ID will be provided. + // Note: It is recommended to store this ID with a human readable name, + // as this will make it easier to delete the downloaded area in the future by calling + // mapDownloader.deleteRegions(...). The ID itself is accessible from InstalledRegions. + // For simplicity, this is not shown here. + String message = "Completed 100% for area! ID: " + list.get(0).id; + snackbar.setText(message).show(); + Log.d(TAG, message); + } + + @Override + public void onProgress(@NonNull RegionId regionId, int percentage) { + // Note that this ID is uniquely created and can be to delete the area in the future. + String message = "Download for area ID: " + regionId.id + + ". Progress: " + percentage + "%."; + snackbar.setText(message).show(); + } + + @Override + public void onPause(@Nullable MapLoaderError mapLoaderError) { + if (mapLoaderError == null) { + String message = "The download area was paused by the user calling mapDownloaderTask.pause()."; + snackbar.setText(message).show(); + } else { + String message = "Download area onPause error. The task tried to often to retry the download: " + mapLoaderError; + snackbar.setText(message).show(); + } + } + + @Override + public void onResume() { + String message = "A previously paused area download has been resumed."; + snackbar.setText(message).show(); + } + }); + } + + private GeoBox getMapViewGeoBox() { + int mapViewWidthInPixels = mapView.getWidth(); + int mapViewHeightInPixels = mapView.getHeight(); + Point2D bottomLeftPoint2D = new Point2D(0, mapViewHeightInPixels); + Point2D topRightPoint2D = new Point2D(mapViewWidthInPixels, 0); + + GeoCoordinates southWestCorner = mapView.viewToGeoCoordinates(bottomLeftPoint2D); + GeoCoordinates northEastCorner = mapView.viewToGeoCoordinates(topRightPoint2D); + + if (southWestCorner == null || northEastCorner == null) { + throw new RuntimeException("GeoBox creation failed, corners are null."); + } + + // Note: This algorithm assumes an unrotated map view. + return new GeoBox(southWestCorner, northEastCorner); + } + // Cached map data will not be removed until the least recently used (LRU) strategy is applied. // Therefore, we can manually clear the cache to remove any outdated entries. public void clearCache() { @@ -677,4 +752,12 @@ private void repositionCamera(){ MapMeasure mapMeasureZoom = new MapMeasure(MapMeasure.Kind.DISTANCE, distanceInMeters); camera.lookAt(new GeoCoordinates(46.94843, 7.44046), mapMeasureZoom); } + + private void showDialog(String title, String message) { + AlertDialog.Builder builder = + new AlertDialog.Builder(context); + builder.setTitle(title); + builder.setMessage(message); + builder.show(); + } } diff --git a/examples/latest/navigate/android/OfflineMaps/app/src/main/res/layout/activity_main.xml b/examples/latest/navigate/android/OfflineMaps/app/src/main/res/layout/activity_main.xml index 741f510a..74428a8b 100644 --- a/examples/latest/navigate/android/OfflineMaps/app/src/main/res/layout/activity_main.xml +++ b/examples/latest/navigate/android/OfflineMaps/app/src/main/res/layout/activity_main.xml @@ -68,6 +68,16 @@ android:textColor="@android:color/white" android:textSize="8sp" /> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/ContentView.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/ContentView.swift new file mode 100644 index 00000000..1c826e16 --- /dev/null +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/ContentView.swift @@ -0,0 +1,112 @@ +/* + * Copyright (C) 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 + */ + +import heresdk +import SwiftUI + +struct ContentView: View, TextViewUpdateDelegate { + + /// State variable to control the visibility of the menu. + @State private var showMenu = false + @State private var mapView = MapView() + @State private var hikingDiaryExample: HikingDiaryExample? + @State private var message: String = "Initializing..." + @State private var switchState: Bool = false + + var body: some View { + // Show the views on top of each other. + ZStack(alignment: .top) { + + // The map view should fill the entire screen. + WrappedMapView(mapView: $mapView) + .edgesIgnoringSafeArea(.all) + + VStack { + HStack { + CustomMenuButton(showMenu: $showMenu) + Spacer() + CustomSliderSwitch( + isOn: $switchState, + onAction: { + hikingDiaryExample?.enableOutdoorRasterLayer() + }, + offAction: { + hikingDiaryExample?.disableOutdoorRasterLayer() + } + ) + .frame(width: 120, height: 50) + } + + HStack { + CustomButton(title: "Start") { + hikingDiaryExample?.onStartHikingButtonClicked() + }.padding(.trailing, 20) + CustomButton(title: "Stop") { + hikingDiaryExample?.onStopHikingButtonClicked() + }.padding(.leading, 20) + } + HStack { + // A permanent view to show log content such as hiking information. + CustomTextView(message: message) + } + } + } + .sheet(isPresented: $showMenu) { + // Presents the menu view as a sheet when showMenu is true. + if let hikingDiary = hikingDiaryExample { + if hikingDiary.pastHikingDiaryEntries.isEmpty { + Text("No hiking diary entries saved yet.") + } else { + MenuView(hikingDiary: hikingDiary) + } + } + } + .onAppear { + // ContentView appeared, now we init the example. + hikingDiaryExample = HikingDiaryExample(mapView) + hikingDiaryExample?.textViewUpdateDelegate = self + updateTextViewMessage("** Hiking Diary **") + } + } + + // Updates the message displayed on CustomTextView. + func updateTextViewMessage(_ message: String) { + self.message = message + } +} + +// The MapView provided by the HERE SDK conforms to a UIKit view, so it needs to be wrapped to conform +// to a SwiftUI view. The map view is created in the ContentView and bound here. +private struct WrappedMapView: UIViewRepresentable { + @Binding var mapView: MapView + func makeUIView(context: Context) -> MapView { return mapView } + func updateUIView(_ mapView: MapView, context: Context) { } +} + +// Protocol to delegate text message updates to display in ContentView. +protocol TextViewUpdateDelegate { + func updateTextViewMessage(_ message: String) +} + +struct ContentView_Previews: PreviewProvider { + static var previews: some View { + ContentView() + } +} + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/CustomMenuView.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/CustomMenuView.swift new file mode 100644 index 00000000..233d1de9 --- /dev/null +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/CustomMenuView.swift @@ -0,0 +1,102 @@ +/* + * Copyright (C) 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 + */ + +import heresdk +import SwiftUI + +// Represents a single hiking diary entry with a title and description. +struct HikingDiaryEntry { + let title: String + let description: String +} + +// Displays a single menu item in the list with swipe-to-delete functionality. +struct MenuItemView: View { + var entry: HikingDiaryEntry + var onDelete: () -> Void + var onTap: () -> Void + + var body: some View { + HStack { + VStack(alignment: .leading) { + Text(entry.title) + .font(.headline) + Text(entry.description) + .font(.subheadline) + .foregroundColor(.gray) + } + Spacer() + } + .padding() + .background(Color.white) + .cornerRadius(8) + .shadow(radius: 5) + .contextMenu { + Button(action: onTap) { + Text("View Entry") + } + Button(role: .destructive, action: onDelete) { + Text("Delete Entry") + } + } + .swipeActions(edge: .trailing) { + Button(role: .destructive, action: onDelete) { + Label("Delete", systemImage: "trash") + } + } + .onLongPressGesture { + onTap() + } + .onTapGesture { + onTap() + } + } +} + +/// View for displaying the menu. Each menu item triggers its respective action and supports swipeable delete. +struct MenuView: View { + @ObservedObject var hikingDiary: HikingDiaryExample + @State private var showMenu = false + @Environment(\.dismiss) var dismiss + + var body: some View { + NavigationView { + List { + ForEach(hikingDiary.pastHikingDiaryEntries.indices, id: \.self) { index in + MenuItemView( + entry: hikingDiary.pastHikingDiaryEntries[index], + onDelete: { + hikingDiary.deletetHikeEntry(at: index) + }, + onTap: { + hikingDiary.loadHikeEntry(index: index) + dismiss() + } + ) + } + } + .navigationBarItems(trailing: Button("Hiking Diary") { + showMenu.toggle() + + }) + .navigationTitle("Past Hikes") + } + } +} + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/CustomViews.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/CustomViews.swift new file mode 100644 index 00000000..0327be26 --- /dev/null +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/CustomViews.swift @@ -0,0 +1,159 @@ +/* + * Copyright (C) 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 + */ + +import SwiftUI + +/* + * A collection of resuable views with custom styling and layout. + */ + +// CustomMenuButton is a reusable SwiftUI view that displays a button with a menu icon. +struct CustomMenuButton: View { + // Use @Binding to connect to the state from the parent view. + @Binding var showMenu: Bool + + var body: some View { + Button(action: { + showMenu.toggle() + }) { + Image(systemName: "line.horizontal.3") + .resizable() + .frame(width: 25, height: 25) + } + .padding() + } +} + +// A reusable button to keep the layout clean. +struct CustomButton: View { + let title: String + let action: () -> Void + + var body: some View { + Button(action: action) { + Text(title) + .padding() + .background(Color(red: 0, green: 182/255, blue: 178/255)) + .foregroundColor(.white) + .cornerRadius(5) + } + } +} + +// A reusable toggle button to keep the layout clean. +struct CustomToggleButton: View { + @State private var isOn: Bool = false + var onLabel: String + var offLabel: String + var onAction: () -> Void + var offAction: () -> Void + + var body: some View { + Button(action: { + isOn.toggle() + if isOn { + onAction() + } else { + offAction() + } + }) { + Text(isOn ? onLabel : offLabel) + .padding() + .background(Color(red: 0, green: 182/255, blue: 178/255)) + .foregroundColor(.white) + .cornerRadius(5) + } + } +} + +/// A customizable slider switch with drag and tap gestures for toggling states. +struct CustomSliderSwitch: View { + @Binding var isOn: Bool + @State private var offset: CGFloat = 0.0 + + private let switchWidth: CGFloat = 80 + private let switchHeight: CGFloat = 40 + private let thumbDiameter: CGFloat = 36 + + private let onColor = Color(red: 0, green: 144 / 255, blue: 138 / 255) + private let offColor = Color.gray + private let thumbOnColor = Color.white + private let thumbOffColor = Color.white + + // Action closures + var onAction: () -> Void + var offAction: () -> Void + + var body: some View { + ZStack { + // Background + Capsule() + .fill(isOn ? onColor : offColor) + .frame(width: switchWidth, height: switchHeight) + + // Thumb + Circle() + .fill(isOn ? thumbOnColor : thumbOffColor) + .frame(width: thumbDiameter, height: thumbDiameter) + .offset(x: offset) + .shadow(radius: 2) + .gesture( + DragGesture() + .onChanged { gesture in + let newOffset = gesture.translation.width + let minOffset = -(switchWidth / 2 - thumbDiameter / 2) + let maxOffset = (switchWidth / 2 - thumbDiameter / 2) + offset = min(max(newOffset + (isOn ? maxOffset : minOffset), minOffset), maxOffset) + } + .onEnded { _ in + let midPoint = CGFloat(0) + let wasOn = isOn + isOn = offset > midPoint + withAnimation { + offset = isOn ? (switchWidth / 2 - thumbDiameter / 2) : -(switchWidth / 2 - thumbDiameter / 2) + } + if wasOn != isOn { + if isOn { onAction() } else { offAction() } + } + } + ) + } + .onAppear { + offset = isOn ? (switchWidth / 2 - thumbDiameter / 2) : -(switchWidth / 2 - thumbDiameter / 2) + } + .frame(height: switchHeight) + } +} + +// A custom text view for displaying and updating text in the UI. +struct CustomTextView: View { + var message: String + var textViewBackgroundColor = Color(red: 0, green: 144 / 255, blue: 138 / 255).opacity(0.8) + + var body: some View { + Text(message) + .font(.system(size: 14)) + .foregroundColor(.white) + .padding() + .background(textViewBackgroundColor) + .cornerRadius(8) + .multilineTextAlignment(.center) + } +} + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/HEREPositioningSimulator.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/HEREPositioningSimulator.swift index b2c873bd..94cfbcda 100644 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/HEREPositioningSimulator.swift +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/HEREPositioningSimulator.swift @@ -64,3 +64,4 @@ class HEREPositioningSimulator { return locationSimulator } } + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/HEREPositioningVisualizer.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/HEREPositioningVisualizer.swift index 467b598b..732be318 100644 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/HEREPositioningVisualizer.swift +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/HEREPositioningVisualizer.swift @@ -92,3 +92,4 @@ class HEREPositioningVisualizer { } } } + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/AppDelegate.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingDiaryApp.swift similarity index 62% rename from examples/latest/navigate/ios/HikingDiary/HikingDiary/AppDelegate.swift rename to examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingDiaryApp.swift index 2d76fb93..8883b412 100644 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/AppDelegate.swift +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingDiaryApp.swift @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022-2024 HERE Europe B.V. + * Copyright (C) 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. @@ -18,19 +18,36 @@ */ import heresdk -import UIKit +import SwiftUI -@UIApplicationMain -class AppDelegate: UIResponder, UIApplicationDelegate { - - var window: UIWindow? - - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { +// This class is the entry point to an application. +// HERE SDK initialization is done at start of app. When app is terminated, the HERE SDK is disposed. +@main +struct HikingDiaryApp: App { + + var body: some Scene { + WindowGroup { + ContentView() + } + } + + init() { + observeAppLifecycle() + // Usually, you need to initialize the HERE SDK only once during the lifetime of an application. initializeHERESDK() - return true } - + + private func observeAppLifecycle() { + NotificationCenter.default.addObserver(forName: UIApplication.willTerminateNotification, + object: nil, + queue: nil) { _ in + // Perform cleanup or final tasks here. + print("App is about to terminate.") + disposeHERESDK() + } + } + private func initializeHERESDK() { // Set your credentials for the HERE SDK. let accessKeyID = "YOUR_ACCESS_KEY_ID" @@ -42,15 +59,13 @@ class AppDelegate: UIResponder, UIApplicationDelegate { fatalError("Failed to initialize the HERE SDK. Cause: \(engineInstantiationError)") } } - + private func disposeHERESDK() { // Free HERE SDK resources before the application shuts down. // Usually, this should be called only on application termination. - // Afterwards, the HERE SDK is no longer usable unless it is initialized again. + + // After this call, the HERE SDK is no longer usable unless it is initialized again. SDKNativeEngine.sharedInstance = nil } - - func applicationWillTerminate(_ application: UIApplication) { - disposeHERESDK() - } } + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingApp.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingDiaryExample.swift similarity index 68% rename from examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingApp.swift rename to examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingDiaryExample.swift index d3d7f354..11caf9af 100644 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingApp.swift +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/HikingDiaryExample.swift @@ -18,10 +18,16 @@ */ import heresdk -import UIKit +import SwiftUI + +enum ConstantsEnum { + static let DEFAULT_MAP_CENTER = GeoCoordinates(latitude: 52.520798, longitude: 13.409408) + static let DEFAULT_DISTANCE_IN_METERS: Double = 1000 * 2 +} // An app that tracks the user's location and allows to record the travelled path with a GPXTrackWriter. -class HikingApp: LocationDelegate { +class HikingDiaryExample: LocationDelegate, + ObservableObject { // A class to receive location events from the device. private let herePositioningProvider = HEREPositioningProvider() @@ -34,12 +40,13 @@ class HikingApp: LocationDelegate { private let gpxManager: GPXManager private let positioningVisualizer: HEREPositioningVisualizer private let outdoorRasterLayer: OutdoorRasterLayer - private let messageTextView = UITextView() private var locationFilter: LocationFilterStrategy + var textViewUpdateDelegate: TextViewUpdateDelegate? + @Published var pastHikingDiaryEntries: [HikingDiaryEntry] = [] - init(mapView: MapView) { + init(_ mapView: MapView) { self.mapView = mapView - + // A class to filter out undesired location signals. locationFilter = DistanceAccuracyLocationFilter() @@ -55,10 +62,35 @@ class HikingApp: LocationDelegate { // Sets delegate to receive locations from HERE Positioning. herePositioningProvider.startLocating(locationDelegate: self, accuracy: .navigation) + // Load the map scene using a map scheme to render the map with. + mapView.mapScene.loadScene(mapScheme: MapScheme.normalDay, completion: onLoadScene) + animateCameraToCurrentLocation() - - setupMessageView() - setMessage("** Hiking Diary **") + + // Load the past hike trips to this published variable used for displaying and deleting those entries. + pastHikingDiaryEntries = getPastHikingDiaryEntries() + + let message = "For this example app, an outdoor layer from thunderforest.com is used. Without setting a valid API key, these raster tiles will show a watermark (terms of usage: https://www.thunderforest.com/terms/).\n Attribution for the outdoor layer: \n Maps © www.thunderforest.com, \n Data © www.osm.org/copyright." + showDialog(title: "Note", message: message) + + updateMessage("** Hiking Diary **") + } + + // Completion handler for loadScene(). + private func onLoadScene(mapError: MapError?) { + guard mapError == nil else { + print("Error: Map scene not loaded, \(String(describing: mapError))") + return + } + + // Enhance the scene with map features suitable for hiking trips. + mapView.mapScene.enableFeatures([MapFeatures.terrain : MapFeatureModes.terrain3d]) + mapView.mapScene.enableFeatures([MapFeatures.ambientOcclusion : MapFeatureModes.ambientOcclusionAll]) + mapView.mapScene.enableFeatures([MapFeatures.buildingFootprints : MapFeatureModes.buildingFootprintsAll]) + mapView.mapScene.enableFeatures([MapFeatures.contours : MapFeatureModes.contoursAll]) + mapView.mapScene.enableFeatures([MapFeatures.extrudedBuildings : MapFeatureModes.extrudedBuildingsAll]) + mapView.mapScene.enableFeatures([MapFeatures.landmarks : MapFeatureModes.landmarksTextured]) + } func onStartHikingButtonClicked() { @@ -66,7 +98,7 @@ class HikingApp: LocationDelegate { isHiking = true isGPXTrackLoaded = false animateCameraToCurrentLocation() - setMessage("Start Hike.") + updateMessage("Starting Hike.") // Create a new GPXTrackWriter to record this trip. gpxTrackWriter = GPXTrackWriter() @@ -78,7 +110,7 @@ class HikingApp: LocationDelegate { if isHiking && isGPXTrackLoaded == false { saveDiaryEntry() } else { - setMessage("Stopped.") + updateMessage("Stopped.") } isHiking = false @@ -111,11 +143,11 @@ class HikingApp: LocationDelegate { // Calculate the currently travelled distance. if let mapPolyline = mapPolyline { let distanceTravelled = getLengthOfGeoPolylineInMeters(mapPolyline.geometry) - setMessage("Hike Distance: \(distanceTravelled) m") + updateMessage("Hike Distance: \(distanceTravelled) m") } } } - + private func updateTravelledPath() -> MapPolyline? { let geoCoordinatesList = gpxManager.getGeoCoordinatesList(track: gpxTrackWriter.track) @@ -158,7 +190,7 @@ class HikingApp: LocationDelegate { size: widthInPixels), color: polylineColor, capShape: LineCap.round)) - + mapView.mapScene.addMapPolyline(myPathMapPolyline!) } catch let error { fatalError("Failed to render MapPolyline. Cause: \(error)") @@ -176,11 +208,12 @@ class HikingApp: LocationDelegate { private func saveDiaryEntry() { // Permanently store the trip on the device. let result = gpxManager.saveGPXTrack(gpxTrackWriter.track) - setMessage("Saved Hike: \(result).") + pastHikingDiaryEntries.append(HikingDiaryEntry(title: gpxTrackWriter.track.name, description: gpxTrackWriter.track.description)) + updateMessage("Saved Hike: \(result).") } // Load the selected diary entry and show the polyline related to that hike. - public func loadDiaryEntry(index: Int) { + private func loadDiaryEntry(index: Int) { if isHiking { print("Stop hiking first.") return @@ -200,16 +233,16 @@ class HikingApp: LocationDelegate { addMapPolyline(diaryGeoPolyline) animateCameraTo(diaryGeoCoordinatesList) - setMessage("Diary Entry from: " + gpxTrack.description + "\n" + + updateMessage("Diary Entry from: " + gpxTrack.description + "\n" + "Hike Distance: \(distanceTravelled) m") } - public func deleteDiaryEntry(index: Int) { + private func deleteDiaryEntry(index: Int) { let isSuccess = gpxManager.deleteGPXTrack(index: index) print("Deleted entry: \(isSuccess)") } - public func getMenuEntryKeys() -> [String] { + private func getMenuEntryKeys() -> [String] { var entryKeys: [String] = [] for track in gpxManager.gpxDocument.tracks { entryKeys.append(track.name) @@ -217,7 +250,7 @@ class HikingApp: LocationDelegate { return entryKeys } - public func getMenuEntryDescriptions() -> [String] { + private func getMenuEntryDescriptions() -> [String] { var entryDescriptions: [String] = [] for track in gpxManager.gpxDocument.tracks { entryDescriptions.append("Hike done on: " + track.description) @@ -265,23 +298,51 @@ class HikingApp: LocationDelegate { mapView.camera.startAnimation(mapCameraAnimation) } - // A permanent view to show scrollable text content. - private func setupMessageView() { - messageTextView.textColor = .white - messageTextView.backgroundColor = UIColor(red: 0, green: 144 / 255, blue: 138 / 255, alpha: 1) - messageTextView.layer.cornerRadius = 8 - messageTextView.isEditable = false - messageTextView.textAlignment = NSTextAlignment.center - messageTextView.font = .systemFont(ofSize: 14) - messageTextView.frame = CGRect(x: 0, y: 0, width: mapView.frame.width * 0.6, height: mapView.frame.height * 0.085) - messageTextView.center = CGPoint(x: mapView.frame.width * 0.5, y: mapView.frame.height * 0.9) - - UIView.transition(with: mapView, duration: 0.2, options: [.transitionCrossDissolve], animations: { - self.mapView.addSubview(self.messageTextView) - }) + private func updateMessage(_ message: String) { + textViewUpdateDelegate?.updateTextViewMessage(message) } + + // Method to convert and fetch saved hiking data into list of HikingDiaryEntry objects. + func getPastHikingDiaryEntries() -> [HikingDiaryEntry] { + var hikingDiaryEntries: [HikingDiaryEntry] = [] + hikingDiaryEntries = zip(getMenuEntryKeys(), getMenuEntryDescriptions()).map { (title, description) in + return HikingDiaryEntry(title: title, description: description) + } + return hikingDiaryEntries + } + + func deletetHikeEntry(at index: Int) { + pastHikingDiaryEntries.remove(at: index) + deleteDiaryEntry(index: index) + } + + func loadHikeEntry(index: Int) { + loadDiaryEntry(index: index) + } + + private func showDialog(title: String, message: String) { + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let rootViewController = windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController { + + let alert = UIAlertController( + title: title, + message: message, + preferredStyle: .alert + ) + + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in + // Handle OK button action. + alert.dismiss(animated: true, completion: nil) + })) + + rootViewController.present(alert, animated: true, completion: nil) + } + } +} - public func setMessage(_ message: String) { - messageTextView.text = message +extension HikingDiaryExample: TextViewUpdateDelegate { + func updateTextViewMessage(_ message: String) { + textViewUpdateDelegate?.updateTextViewMessage(message) } } + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/Info.plist b/examples/latest/navigate/ios/HikingDiary/HikingDiary/Info.plist index f5b3dde8..738e967a 100644 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/Info.plist +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/Info.plist @@ -20,12 +20,6 @@ 1 LSRequiresIPhoneOS - NSLocationWhenInUseUsageDescription - This app needs to access your current location to display it on the map. - NSLocationAlwaysAndWhenInUseUsageDescription - This app needs to access your current location to display it on the map while the app is being used or when running in background. - NSMotionUsageDescription - Motion detection is needed to determine more accurate locations, when no GPS signal is found or used. UIBackgroundModes location @@ -34,24 +28,26 @@ UIRequiredDeviceCapabilities location-services + gps - BGTaskSchedulerPermittedIdentifiers - - $(PRODUCT_BUNDLE_IDENTIFIER) - - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main + NSLocationAlwaysAndWhenInUseUsageDescription + This app needs to access your current location to display it on the map. + NSLocationWhenInUseUsageDescription + This app needs to access your current location to display it on the map. + NSMotionUsageDescription + Motion detection is needed to determine more accurate locations, when no GPS signal is found or used. UISupportedInterfaceOrientations UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/LocationFilterStrategy.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/LocationFilterStrategy.swift index fd524da8..408f6b95 100644 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/LocationFilterStrategy.swift +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/LocationFilterStrategy.swift @@ -87,3 +87,4 @@ class DefaultLocationFilter: LocationFilterStrategy { return true } } + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/Menu/Menu.storyboard b/examples/latest/navigate/ios/HikingDiary/HikingDiary/Menu/Menu.storyboard deleted file mode 100644 index d18ce507..00000000 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/Menu/Menu.storyboard +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/Menu/MenuViewController.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/Menu/MenuViewController.swift deleted file mode 100644 index 9cc45510..00000000 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/Menu/MenuViewController.swift +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2022-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 - */ - -import UIKit - -// A helper class to show selectable entries. -// Entries can be deleted by swiping an entry to the left. -class MenuViewController: UIViewController { - - // A menu entry consists of a key and the text to show. - public var entryKeys: [String] = [] - public var entryText: [String] = [] - - @IBOutlet var table: UITableView! - - // A listener to notify when an entry of the list is selected. - private var escapedSelectedIndexListener: (_ index: Int) -> Void = { _ in } - - // A listener to notify when an entry of the list is deleted. - private var escapedDeletedIndexListener: (_ index: Int) -> Void = { _ in } - - public func setSelectedIndexListener(listener: @escaping (_ index: Int) -> Void) { - escapedSelectedIndexListener = listener - } - - public func setDeletedIndexListener(listener: @escaping (_ index: Int) -> Void) { - escapedDeletedIndexListener = listener - } - - private func setSelectedIndex(_ index: Int) { - escapedSelectedIndexListener(index) - } - - private func setDeletedIndex(_ index: Int) { - escapedDeletedIndexListener(index) - } - - override func viewDidLoad() { - super.viewDidLoad() - - table.delegate = self - table.dataSource = self - } -} - -extension MenuViewController: UITableViewDelegate, UITableViewDataSource { - - func numberOfSections(in tableView: UITableView) -> Int { - return 1 - } - - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return entryKeys.count - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "MenuEntry", for: indexPath) - cell.textLabel?.text = entryText[indexPath.row] - return cell - } - - func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle { - UserDefaults.standard.removeObject(forKey: entryKeys[indexPath.row]) - return .delete - } - - func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) { - if editingStyle == .delete { - tableView.beginUpdates() - - // Notfies listener on deleted index of entry. - setDeletedIndex(indexPath.row) - - // Update content. - entryKeys.remove(at: indexPath.row) - entryText.remove(at: indexPath.row) - - // Update menu UI. - tableView.deleteRows(at: [indexPath], with: .fade) - tableView.endUpdates() - } - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - tableView.deselectRow(at: indexPath, animated: true) - - // Notfies listener on selected index of entry. - setSelectedIndex(indexPath.row) - } -} diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/OutdoorRasterLayer.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/OutdoorRasterLayer.swift index 15a011ca..c34d14ae 100644 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/OutdoorRasterLayer.swift +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/OutdoorRasterLayer.swift @@ -18,7 +18,7 @@ */ import heresdk -import UIKit +import SwiftUI // A class to show a custom raster layer on top of the default map style. // This class has been taken and adapted for this app from the CustomerRasterLayers example app, you can find here: @@ -86,6 +86,7 @@ class OutdoorRasterLayer { private func createMapLayer(dataSourceName: String) -> MapLayer { // The layer should be rendered on top of other layers except the layers showing the location indicator and polylines/polygons. let priority = MapLayerPriorityBuilder() + .renderedAfterLayer(named: "labels") .renderedBeforeLayer(named: "&location_indicator_layer") .renderedBeforeLayer(named: "&polyline_layer") .build() @@ -110,3 +111,4 @@ class OutdoorRasterLayer { } } } + diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/Preview Content/Preview Assets.xcassets/Contents.json b/examples/latest/navigate/ios/HikingDiary/HikingDiary/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/examples/latest/navigate/ios/HikingDiary/HikingDiary/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/examples/latest/navigate/ios/HikingDiary/HikingDiary/ViewController.swift b/examples/latest/navigate/ios/HikingDiary/HikingDiary/ViewController.swift deleted file mode 100644 index 5727e693..00000000 --- a/examples/latest/navigate/ios/HikingDiary/HikingDiary/ViewController.swift +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2022-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 - */ - -import heresdk -import UIKit - -class ViewController: UIViewController { - - @IBOutlet private var mapView: MapView! - private var hikingApp: HikingApp? - - override func viewDidLoad() { - super.viewDidLoad() - - // Load the map scene using a map scheme to render the map with. - mapView.mapScene.loadScene(mapScheme: MapScheme.topoDay, completion: onLoadScene) - } - - override func viewDidAppear(_ animated: Bool) { - super.viewDidAppear(animated) - - let message = "For this example app, an outdoor layer from thunderforest.com is used. Without setting a valid API key, these raster tiles will show a watermark (terms of usage: https://www.thunderforest.com/terms/).\n Attribution for the outdoor layer: \n Maps © www.thunderforest.com, \n Data © www.osm.org/copyright." - showDialog(title: "Note", message: message) - } - - // Completion handler when loading a map scene. - private func onLoadScene(mapError: MapError?) { - if let error = mapError { - print("Error: Map scene not loaded, \(error)") - } else { - hikingApp = HikingApp(mapView: mapView) - enableMapFeatures() - } - } - - // Enhance the scene with map features suitable for hiking trips. - private func enableMapFeatures() { - mapView.mapScene.enableFeatures([MapFeatures.terrain: MapFeatureModes.terrain3d, - MapFeatures.contours: MapFeatureModes.contoursAll, - MapFeatures.buildingFootprints : MapFeatureModes.buildingFootprintsAll, - MapFeatures.extrudedBuildings : MapFeatureModes.extrudedBuildingsAll, - MapFeatures.landmarks : MapFeatureModes.landmarksTextured, - MapFeatures.ambientOcclusion : MapFeatureModes.ambientOcclusionAll]) - } - - // When a custom raster outdoor layer is shown, we do not need to load hidden map features to save bandwidth. - private func disableMapFeatures() { - mapView.mapScene.disableFeatures([MapFeatures.terrain, - MapFeatures.contours, - MapFeatures.buildingFootprints, - MapFeatures.extrudedBuildings, - MapFeatures.landmarks, - MapFeatures.ambientOcclusion]) - } - - @IBAction func schemaSwitch(_ sender: UISwitch) { - if sender.isOn { - disableMapFeatures() - hikingApp?.enableOutdoorRasterLayer() - } else if !sender.isOn { - enableMapFeatures() - hikingApp?.disableOutdoorRasterLayer() - } - } - - @IBAction func onEnableButtonClicked(_ sender: Any) { - hikingApp?.onStartHikingButtonClicked() - } - - @IBAction func onDisableButtonClicked(_ sender: Any) { - hikingApp?.onStopHikingButtonClicked() - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - mapView.handleLowMemory() - } - - @IBAction func onMenuButtonClicked(_ sender: UIBarButtonItem) { - let entries = hikingApp?.getMenuEntryKeys() ?? [] - if entries.isEmpty { - hikingApp?.setMessage("No hiking diary entries yet.") - } else { - performSegue(withIdentifier: "showMenu", sender: mapView) - } - } - - // Open the menu. - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { - if segue.identifier == "showMenu" { - let menuViewController = segue.destination as? MenuViewController - - menuViewController?.entryKeys = hikingApp?.getMenuEntryKeys() ?? [] - menuViewController?.entryText = hikingApp?.getMenuEntryDescriptions() ?? [] - - menuViewController?.setSelectedIndexListener { index in - self.hikingApp?.loadDiaryEntry(index: index) - } - - menuViewController?.setDeletedIndexListener { index in - self.hikingApp?.deleteDiaryEntry(index: index) - } - } - } - - func showDialog(title: String, message: String) { - let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) - - alertController.addAction(UIAlertAction(title: "Ok", style: .cancel, handler: nil)) - - present(alertController, animated: true, completion: nil) - } - - // Close the menu. - @IBAction func unwindToViewController(_ unwindSegue: UIStoryboardSegue) {} -} diff --git a/examples/latest/navigate/ios/HikingDiary/README.md b/examples/latest/navigate/ios/HikingDiary/README.md index 1232196d..49bafa41 100644 --- a/examples/latest/navigate/ios/HikingDiary/README.md +++ b/examples/latest/navigate/ios/HikingDiary/README.md @@ -1,4 +1,5 @@ -This app shows how to use positioning to calculate the distance travelled by a user. You can find how this is done in [HikingExample.swift](HikingDiary/HikingApp.swift). +This app shows how to use positioning to calculate the distance travelled by a user. You can find how this is done in [HikingDiaryExample.swift](HikingDiary/HikingDiaryExample.swift). +You can find a complete [tutorial](https://www.here.com/docs/bundle/sdk-for-ios-navigate-developer-guide/page/topics/hiking-app-tutorial.html) on building this hiking diary app from scratch, featuring detailed explanations of the algorithms and concepts behind location accuracy and location filters used in building this application. Build instructions: ------------------- diff --git a/examples/latest/navigate/ios/MapItems/README.md b/examples/latest/navigate/ios/MapItems/README.md index 27b8eafc..307f8f50 100644 --- a/examples/latest/navigate/ios/MapItems/README.md +++ b/examples/latest/navigate/ios/MapItems/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `MapItemsApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/Navigation/Navigation/ContentView.swift b/examples/latest/navigate/ios/Navigation/Navigation/ContentView.swift index 96ae51bc..c81efc0e 100644 --- a/examples/latest/navigate/ios/Navigation/Navigation/ContentView.swift +++ b/examples/latest/navigate/ios/Navigation/Navigation/ContentView.swift @@ -20,11 +20,10 @@ import heresdk import SwiftUI -struct ContentView: View, TextViewUpdateDelegate { +struct ContentView: View { @State private var mapView = MapView() - @State private var navigationAppLogic: NavigationAppLogic? - @State private var message: String = "Initializing..." + @StateObject private var navigationAppLogic = NavigationAppLogic() var body: some View { // Show the views on top of each other. @@ -37,10 +36,10 @@ struct ContentView: View, TextViewUpdateDelegate { VStack { HStack { CustomButton(title: "Add Route (Simulated Location)") { - navigationAppLogic?.addRouteSimulatedLocationButtonClicked() + navigationAppLogic.addRouteSimulatedLocationButtonClicked() } CustomButton(title: "Add Route (Device Location)") { - navigationAppLogic?.addRouteDeviceLocationButtonClicked() + navigationAppLogic.addRouteDeviceLocationButtonClicked() } } HStack { @@ -48,33 +47,27 @@ struct ContentView: View, TextViewUpdateDelegate { onLabel: "Camera Tracking: Off", offLabel: "Camera Tracking: On", onAction: { - navigationAppLogic?.disableCameraTracking() + navigationAppLogic.disableCameraTracking() }, offAction: { - navigationAppLogic?.enableCameraTracking() + navigationAppLogic.enableCameraTracking() } ) CustomButton(title: "Clear map") { - navigationAppLogic?.clearMapButtonClicked() + navigationAppLogic.clearMapButtonClicked() } } HStack { // A permanent view to show log content such as maneuver information. - CustomTextView(message: message) + CustomTextView(message: navigationAppLogic.messageText) } } } .onAppear { - // ContentView appeared, now we init the example. - navigationAppLogic = NavigationAppLogic(mapView) - navigationAppLogic?.textViewUpdateDelegate = self + // ContentView appeared, now we start the example. + navigationAppLogic.startExample(mapView) } } - - // Updates the message displayed on CustomTextView. - func updateTextViewMessage(_ message: String) { - self.message = message - } } // The MapView provided by the HERE SDK conforms to a UIKit view, so it needs to be wrapped to conform @@ -85,11 +78,6 @@ private struct WrappedMapView: UIViewRepresentable { func updateUIView(_ mapView: MapView, context: Context) { } } -// Protocol to delegate text message updates to display in ContentView. -protocol TextViewUpdateDelegate { - func updateTextViewMessage(_ message: String) -} - struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() diff --git a/examples/latest/navigate/ios/Navigation/Navigation/NavigationAppLogic.swift b/examples/latest/navigate/ios/Navigation/Navigation/NavigationAppLogic.swift index 5edf6361..25800a5e 100644 --- a/examples/latest/navigate/ios/Navigation/Navigation/NavigationAppLogic.swift +++ b/examples/latest/navigate/ios/Navigation/Navigation/NavigationAppLogic.swift @@ -25,22 +25,28 @@ enum ConstantsEnum { static let DEFAULT_DISTANCE_IN_METERS: Double = 1000 * 2 } +// A protocol to send text messages from other classes to this class. +protocol MessageDelegate { + func updateMessage(_ message: String) +} + // An app that allows to calculate a route and start navigation, using either platform positioning or // simulated locations. -class NavigationAppLogic: LongPressDelegate { +class NavigationAppLogic: ObservableObject, MessageDelegate, LongPressDelegate { - private let mapView: MapView - private let routeCalculator: RouteCalculator - private let navigationExample: NavigationExample + private var mapView: MapView? + private var routeCalculator: RouteCalculator? + private var navigationExample: NavigationExample? private var mapMarkers = [MapMarker]() private var mapPolylineList = [MapPolyline]() private var startingWaypoint: Waypoint? private var destinationWaypoint: Waypoint? private var isLongpressDestination = false private var timeUtils = TimeUtils() - var textViewUpdateDelegate: TextViewUpdateDelegate? - init(_ mapView: MapView) { + @Published var messageText: String = "Initializing ..." + + func startExample(_ mapView: MapView) { self.mapView = mapView let distanceInMeters = MapMeasure(kind: .distance, value: ConstantsEnum.DEFAULT_DISTANCE_IN_METERS) @@ -48,10 +54,11 @@ class NavigationAppLogic: LongPressDelegate { zoom: distanceInMeters) routeCalculator = RouteCalculator() - - navigationExample = NavigationExample(mapView: mapView) - navigationExample.textViewUpdateDelegate = self - navigationExample.startLocationProvider() + if let routeCalculator = routeCalculator { + navigationExample = NavigationExample(mapView: mapView, routeCalculator: routeCalculator) + navigationExample?.startLocationProvider() + navigationExample?.messageDelegate = self + } // Load the map scene using a map scheme to render the map with. mapView.mapScene.loadScene(mapScheme: MapScheme.normalDay, completion: onLoadScene) @@ -68,9 +75,9 @@ class NavigationAppLogic: LongPressDelegate { } // Enable traffic flows, low speed zones and 3d landmarks, by default. - mapView.mapScene.enableFeatures([MapFeatures.trafficFlow : MapFeatureModes.trafficFlowWithFreeFlow]) - mapView.mapScene.enableFeatures([MapFeatures.lowSpeedZones : MapFeatureModes.lowSpeedZonesAll]) - mapView.mapScene.enableFeatures([MapFeatures.landmarks : MapFeatureModes.landmarksTextured]) + mapView?.mapScene.enableFeatures([MapFeatures.trafficFlow : MapFeatureModes.trafficFlowWithFreeFlow]) + mapView?.mapScene.enableFeatures([MapFeatures.lowSpeedZones : MapFeatureModes.lowSpeedZonesAll]) + mapView?.mapScene.enableFeatures([MapFeatures.landmarks : MapFeatureModes.landmarksTextured]) } // Calculate a route and start navigation using a location simulator. @@ -93,11 +100,11 @@ class NavigationAppLogic: LongPressDelegate { } func enableCameraTracking() { - navigationExample.startCameraTracking() + navigationExample?.startCameraTracking() } func disableCameraTracking() { - navigationExample.stopCameraTracking() + navigationExample?.stopCameraTracking() } private func calculateRoute(isSimulated: Bool) { @@ -108,8 +115,8 @@ class NavigationAppLogic: LongPressDelegate { } // Calculates a car route. - routeCalculator.calculateRoute(start: startingWaypoint!, - destination: destinationWaypoint!) { (routingError, routes) in + routeCalculator?.calculateRoute(start: startingWaypoint!, + destination: destinationWaypoint!) { (routingError, routes) in if let error = routingError { self.showDialog(title: "Error while calculating a route:", message: "\(error)") return @@ -125,7 +132,7 @@ class NavigationAppLogic: LongPressDelegate { private func determineRouteWaypoints(isSimulated: Bool) -> Bool { // When using real GPS locations, we always start from the current location of user. if !isSimulated { - guard let location = navigationExample.getLastKnownLocation() else { + guard let location = navigationExample?.getLastKnownLocation() else { showDialog(title: "Error", message: "No location found.") return false } @@ -135,7 +142,7 @@ class NavigationAppLogic: LongPressDelegate { // If a driver is moving, the bearing value can help to improve the route calculation. startingWaypoint?.headingInDegrees = location.bearingInDegrees - mapView.camera.lookAt(point: location.coordinates) + mapView?.camera.lookAt(point: location.coordinates) } if (startingWaypoint == nil) { @@ -175,7 +182,7 @@ class NavigationAppLogic: LongPressDelegate { size: widthInPixels), color: polylineColor, capShape: LineCap.round)) - mapView.mapScene.addMapPolyline(routeMapPolyline) + mapView?.mapScene.addMapPolyline(routeMapPolyline) mapPolylineList.append(routeMapPolyline) } catch let error { fatalError("Failed to render MapPolyline. Cause: \(error)") @@ -186,30 +193,30 @@ class NavigationAppLogic: LongPressDelegate { clearWaypointMapMarker() clearRoute() - navigationExample.stopNavigation() + navigationExample?.stopNavigation() } private func clearWaypointMapMarker() { for mapMarker in mapMarkers { - mapView.mapScene.removeMapMarker(mapMarker) + mapView?.mapScene.removeMapMarker(mapMarker) } mapMarkers.removeAll() } private func clearRoute() { for mapPolyline in mapPolylineList { - mapView.mapScene.removeMapPolyline(mapPolyline) + mapView?.mapScene.removeMapPolyline(mapPolyline) } mapPolylineList.removeAll() } private func setLongPressGestureHandler() { - mapView.gestures.longPressDelegate = self + mapView?.gestures.longPressDelegate = self } // Conform to LongPressDelegate protocol. func onLongPress(state: heresdk.GestureState, origin: Point2D) { - guard let geoCoordinates = mapView.viewToGeoCoordinates(viewCoordinates: origin) else { + guard let geoCoordinates = mapView?.viewToGeoCoordinates(viewCoordinates: origin) else { print("Warning: Long press coordinate is not on map view.") return } @@ -243,7 +250,7 @@ class NavigationAppLogic: LongPressDelegate { } private func getMapViewCenter() -> GeoCoordinates { - return mapView.camera.state.targetCoordinates + return mapView?.camera.state.targetCoordinates ?? GeoCoordinates(latitude: 52, longitude: 13) } private func addCircleMapMarker(geoCoordinates: GeoCoordinates, imageName: String) { @@ -257,7 +264,7 @@ class NavigationAppLogic: LongPressDelegate { imageFormat: ImageFormat.png) let mapMarker = MapMarker(at: geoCoordinates, image: mapImage) - mapView.mapScene.addMapMarker(mapMarker) + mapView?.mapScene.addMapMarker(mapMarker) mapMarkers.append(mapMarker) } @@ -279,7 +286,7 @@ class NavigationAppLogic: LongPressDelegate { alert.addAction(UIAlertAction(title: buttonText, style: .default, handler: { (alertAction) -> Void in // Handle OK button action. - self.navigationExample.startNavigation(route: route, isSimulated: isSimulated) + self.navigationExample?.startNavigation(route: route, isSimulated: isSimulated) })) alert.addAction(UIAlertAction(title: "Cancel", style: .default)) @@ -306,13 +313,9 @@ class NavigationAppLogic: LongPressDelegate { } } - private func updateMessage(_ message: String) { - textViewUpdateDelegate?.updateTextViewMessage(message) - } -} - -extension NavigationAppLogic: TextViewUpdateDelegate { - func updateTextViewMessage(_ message: String) { - textViewUpdateDelegate?.updateTextViewMessage(message) + // Conform to MessageDelegate protocol. + func updateMessage(_ message: String) { + // Publish the text in our ContentView. + messageText = message } } diff --git a/examples/latest/navigate/ios/Navigation/Navigation/NavigationEventHandler.swift b/examples/latest/navigate/ios/Navigation/Navigation/NavigationEventHandler.swift index ace59875..c8dec8c2 100644 --- a/examples/latest/navigate/ios/Navigation/Navigation/NavigationEventHandler.swift +++ b/examples/latest/navigate/ios/Navigation/Navigation/NavigationEventHandler.swift @@ -50,12 +50,16 @@ class NavigationEventHandler : NavigableLocationDelegate, private let voiceAssistant: VoiceAssistant private var lastMapMatchedLocation: MapMatchedLocation? private var previousManeuverIndex: Int32 = -1 - var textViewUpdateDelegate: TextViewUpdateDelegate? + private let routeCalculator: RouteCalculator + private var lastTrafficUpdateInMilliseconds: Int = 0; + var messageDelegate: MessageDelegate? init(_ visualNavigator: VisualNavigator, - _ dynamicRoutingEngine: DynamicRoutingEngine) { + _ dynamicRoutingEngine: DynamicRoutingEngine, + _ routeCalculator: RouteCalculator) { self.visualNavigator = visualNavigator self.dynamicRoutingEngine = dynamicRoutingEngine + self.routeCalculator = routeCalculator // A helper class for TTS. voiceAssistant = VoiceAssistant() @@ -133,7 +137,53 @@ class NavigationEventHandler : NavigableLocationDelegate, mapMatchedLocation: lastMapMatchedLocation, sectionIndex: routeProgress.sectionIndex) } + + updateTrafficOnRoute(routeProgress: routeProgress) + } + + // Periodically updates the traffic information for the current route. + // This method checks whether the last traffic update occurred within the specified interval and skips the update if not. + // Then it calculates the current traffic conditions along the route using the `RoutingEngine`. + // Lastly, it updates the `VisualNavigator` with the newly calculated `TrafficOnRoute` object, + // which affects the `RouteProgress` duration without altering the route geometry or distance. + func updateTrafficOnRoute(routeProgress: RouteProgress) { + guard let currentRoute = visualNavigator.route else { + // Should never happen. + return + } + + let trafficUpdateIntervalInMilliseconds = 3 * 60000 // 3 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.sectionIndex + + routeCalculator.calculateTrafficOnRoute( + currentRoute: currentRoute, + lastTraveledSectionIndex: Int(lastTraveledSectionIndex), + traveledDistanceOnLastSectionInMeters: Int(traveledDistanceOnLastSectionInMeters) + ) { routingError, trafficOnRoute in + if let routingError = routingError { + print("CalculateTrafficOnRoute error: \(routingError)") + return + } + print("Updated traffic on route") + // Sets traffic data for the current route, affecting RouteProgress duration in SectionProgress, while preserving route distance and geometry. + self.visualNavigator.trafficOnRoute = trafficOnRoute + } } + func getRoadName(maneuver: Maneuver) -> String { let currentRoadTexts = maneuver.roadTexts @@ -811,6 +861,6 @@ class NavigationEventHandler : NavigableLocationDelegate, } private func updateMessage(_ message: String) { - textViewUpdateDelegate?.updateTextViewMessage(message) + messageDelegate?.updateMessage(message) } } diff --git a/examples/latest/navigate/ios/Navigation/Navigation/NavigationExample.swift b/examples/latest/navigate/ios/Navigation/Navigation/NavigationExample.swift index 95eca97c..0b26a7c4 100644 --- a/examples/latest/navigate/ios/Navigation/Navigation/NavigationExample.swift +++ b/examples/latest/navigate/ios/Navigation/Navigation/NavigationExample.swift @@ -25,7 +25,7 @@ import SwiftUI // By default, tracking mode is enabled. When navigation is stopped, tracking mode is enabled again. // The preferred device language determines the language for voice notifications used for TTS. // (Make sure to set language + region in device settings.) -class NavigationExample : DynamicRoutingDelegate { +class NavigationExample : DynamicRoutingDelegate, MessageDelegate { private let visualNavigator: VisualNavigator private let dynamicRoutingEngine: DynamicRoutingEngine @@ -33,9 +33,10 @@ class NavigationExample : DynamicRoutingDelegate { private let herePositioningSimulator: HEREPositioningSimulator private let routePrefetcher: RoutePrefetcher private let navigationEventHandler: NavigationEventHandler - var textViewUpdateDelegate: TextViewUpdateDelegate? + private let routeCalculator: RouteCalculator + var messageDelegate: MessageDelegate? - init(mapView: MapView) { + init(mapView: MapView, routeCalculator:RouteCalculator) { do { // Without a route set, this starts tracking mode. try visualNavigator = VisualNavigator() @@ -43,6 +44,8 @@ class NavigationExample : DynamicRoutingDelegate { fatalError("Failed to initialize VisualNavigator. Cause: \(engineInstantiationError)") } + self.routeCalculator = routeCalculator + // By default, enable auto-zoom during guidance. visualNavigator.cameraBehavior = DynamicCameraBehavior() @@ -61,9 +64,10 @@ class NavigationExample : DynamicRoutingDelegate { dynamicRoutingEngine = NavigationExample.createDynamicRoutingEngine() // A class to handle various kinds of guidance events. + navigationEventHandler = NavigationEventHandler( - visualNavigator, dynamicRoutingEngine) - navigationEventHandler.textViewUpdateDelegate = self + visualNavigator, dynamicRoutingEngine, routeCalculator) + navigationEventHandler.messageDelegate = self } func startLocationProvider() { @@ -192,13 +196,8 @@ class NavigationExample : DynamicRoutingDelegate { return herePositioningProvider.getLastKnownLocation() } - private func updateMessage(_ message: String) { - textViewUpdateDelegate?.updateTextViewMessage(message) - } -} - -extension NavigationExample: TextViewUpdateDelegate { - func updateTextViewMessage(_ message: String) { - textViewUpdateDelegate?.updateTextViewMessage(message) + // Conform to MessageDelegate protocol. + func updateMessage(_ message: String) { + messageDelegate?.updateMessage(message) } } diff --git a/examples/latest/navigate/ios/Navigation/Navigation/RouteCalculator.swift b/examples/latest/navigate/ios/Navigation/Navigation/RouteCalculator.swift index 3d61e57d..2aaa42ce 100644 --- a/examples/latest/navigate/ios/Navigation/Navigation/RouteCalculator.swift +++ b/examples/latest/navigate/ios/Navigation/Navigation/RouteCalculator.swift @@ -21,9 +21,9 @@ import heresdk // A class that creates car Routes with the HERE SDK. class RouteCalculator { - + private let routingEngine: RoutingEngine - + init() { do { try routingEngine = RoutingEngine() @@ -31,11 +31,11 @@ class RouteCalculator { fatalError("Failed to initialize routing engine. Cause: \(engineInstantiationError)") } } - + func calculateRoute(start: Waypoint, destination: Waypoint, calculateRouteCompletionHandler: @escaping CalculateRouteCompletionHandler) { - + // A route handle is required for the DynamicRoutingEngine to get updates on traffic-optimized routes. var carOptions = CarOptions() carOptions.routeOptions.enableRouteHandle = true @@ -44,4 +44,12 @@ class RouteCalculator { carOptions: carOptions, completion: calculateRouteCompletionHandler) } + + func calculateTrafficOnRoute( + currentRoute: Route, + lastTraveledSectionIndex: Int, + traveledDistanceOnLastSectionInMeters: Int, + calculatetrafficOnRouteCompletionHandler: @escaping CalculateTrafficOnRouteCompletionHandler) { + routingEngine.calculateTrafficOnRoute(route: currentRoute, lastTraveledSectionIndex: Int32(lastTraveledSectionIndex), traveledDistanceOnLastSectionInMeters: Int32(traveledDistanceOnLastSectionInMeters), completion: calculatetrafficOnRouteCompletionHandler) + } } diff --git a/examples/latest/navigate/ios/Navigation/README.md b/examples/latest/navigate/ios/Navigation/README.md index 530bcf67..ea6e2af1 100644 --- a/examples/latest/navigate/ios/Navigation/README.md +++ b/examples/latest/navigate/ios/Navigation/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `NavigationApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/NavigationCustom/README.md b/examples/latest/navigate/ios/NavigationCustom/README.md index b20d3379..82b121ef 100644 --- a/examples/latest/navigate/ios/NavigationCustom/README.md +++ b/examples/latest/navigate/ios/NavigationCustom/README.md @@ -12,4 +12,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `NavigationCustomApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps.xcodeproj/project.pbxproj b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps.xcodeproj/project.pbxproj index 603be4da..49185ff4 100644 --- a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps.xcodeproj/project.pbxproj +++ b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 83C837CB2C20AAE50004F54E /* heresdk.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83C837CA2C20AAE50004F54E /* heresdk.xcframework */; }; 83C837CC2C20AAE50004F54E /* heresdk.xcframework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 83C837CA2C20AAE50004F54E /* heresdk.xcframework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 83C837D12C20EFA70004F54E /* OfflineMapsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C837D02C20EFA70004F54E /* OfflineMapsExample.swift */; }; + DC2DCDEA2CE353B7004FADCC /* MapViewObservable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC2DCDE92CE353B7004FADCC /* MapViewObservable.swift */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -23,7 +24,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - 83C837CC2C20AAE50004F54E /* heresdk.xcframework in Embed Frameworks */ + 83C837CC2C20AAE50004F54E /* heresdk.xcframework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -38,6 +39,7 @@ 83C837C22C207F360004F54E /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 83C837CA2C20AAE50004F54E /* heresdk.xcframework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcframework; path = heresdk.xcframework; sourceTree = ""; }; 83C837D02C20EFA70004F54E /* OfflineMapsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OfflineMapsExample.swift; sourceTree = ""; }; + DC2DCDE92CE353B7004FADCC /* MapViewObservable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewObservable.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -77,6 +79,7 @@ 83C837D02C20EFA70004F54E /* OfflineMapsExample.swift */, 83C837BF2C207F360004F54E /* Assets.xcassets */, 83C837C12C207F360004F54E /* Preview Content */, + DC2DCDE92CE353B7004FADCC /* MapViewObservable.swift */, ); path = OfflineMaps; sourceTree = ""; @@ -171,6 +174,7 @@ 83C837BE2C207F340004F54E /* ContentView.swift in Sources */, 83C837BC2C207F340004F54E /* OfflineMapsApp.swift in Sources */, 83C837D12C20EFA70004F54E /* OfflineMapsExample.swift in Sources */, + DC2DCDEA2CE353B7004FADCC /* MapViewObservable.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/ContentView.swift b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/ContentView.swift index a9e37724..f81d0300 100644 --- a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/ContentView.swift +++ b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/ContentView.swift @@ -21,18 +21,22 @@ import heresdk import SwiftUI struct ContentView: View { - - @State private var mapView = MapView() + @State private var offlineMapsExample: OfflineMapsExample? @State private var messageText = "" + @StateObject private var mapViewObservable = MapViewObservable() + @State private var isMapViewVisible = true // Toggle visibility + var body: some View { // Show the views on top of each other. ZStack(alignment: .top) { - // The map view should fill the entire screen. - WrappedMapView(mapView: $mapView) - .edgesIgnoringSafeArea(.all) + // Conditionally render the map view + if isMapViewVisible { + WrappedMapView(mapViewObservable: mapViewObservable) + .edgesIgnoringSafeArea(.all) + } VStack { HStack { @@ -42,29 +46,50 @@ struct ContentView: View { CustomButton(title: "Download") { offlineMapsExample!.onDownloadMapClicked() } + CustomButton(title: "Clear Cache"){ + offlineMapsExample!.clearCache() + } + } + HStack{ + CustomToggleButton(onLabel: "offlineSearch layer: OFF", offLabel: "offlineSearch layer: ON") { + offlineMapsExample!.toggleConfiguration() + + // In SwiftUI, UIViewRepresentable views may not always be recreated when their state changes, + // especially when SwiftUI performs optimizations like view recycling. + // To ensure that a UIViewRepresentable is fully recreated (i.e., makeUIView is called again), + // we can toggle the visibility of the view, effectively removing it from the view hierarchy + // and then re-adding it. + isMapViewVisible = false + DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { + isMapViewVisible = true + } + + } + CustomButton(title: "Area") { + offlineMapsExample!.onDownloadAreaClicked() + } CustomButton(title: "Cancel") { offlineMapsExample!.onCancelMapDownloadClicked() } - CustomButton(title: "Test") { - offlineMapsExample!.onSearchPlaceClicked() - } } HStack { - CustomButton(title: "Switch Online") { - offlineMapsExample!.onSwitchOnlineClicked() + CustomButton(title: "Test offline Search") { + offlineMapsExample!.onSearchPlaceClicked() } - CustomButton(title: "Switch Offline") { - offlineMapsExample!.onSwitchOfflineClicked() + CustomToggleButton(onLabel: "Offline Mode: On", offLabel: "Offline Mode: Off") { + offlineMapsExample!.toggleOfflineMode() } + } HStack(){ - MessageView(message: messageText) - } + MessageView(message: messageText) } } + .font(.subheadline) + } .onAppear { // ContentView appeared, now we init the example. - offlineMapsExample = OfflineMapsExample(mapView: mapView, showMessageClosure: showMessage) + offlineMapsExample = OfflineMapsExample(mapViewObservable: mapViewObservable, showMessageClosure: showMessage) } } @@ -75,12 +100,23 @@ struct ContentView: View { } } + // The MapView provided by the HERE SDK conforms to a UIKit view, so it needs to be wrapped to conform // to a SwiftUI view. The map view is created in the ContentView and bound here. -private struct WrappedMapView: UIViewRepresentable { - @Binding var mapView: MapView - func makeUIView(context: Context) -> MapView { return mapView } - func updateUIView(_ mapView: MapView, context: Context) { } +private struct WrappedMapView: UIViewRepresentable{ + @ObservedObject var mapViewObservable: MapViewObservable + + func makeUIView(context: Context) -> MapView { + if mapViewObservable.mapView == nil{ + mapViewObservable.configureMapView() + } + + return mapViewObservable.mapView! + } + + func updateUIView(_ uiView: MapView, context: Context) { + // Updates will automatically apply due to observable properties + } } // A reusable button to keep the layout clean. @@ -99,6 +135,28 @@ struct CustomButton: View { } } +// A reusable toggle button to keep the layout clean. +struct CustomToggleButton: View { + @State private var isOn: Bool = false + var onLabel: String + var offLabel: String + var action: () -> Void + + var body: some View { + Button(action: { + isOn.toggle() + action() + }) { + Text(isOn ? onLabel : offLabel) + .padding() + .background(Color(red: 0, green: 182/255, blue: 178/255)) + .foregroundColor(.white) + .cornerRadius(5) + } + } +} + + // A reusable text view to keep the layout clean. struct MessageView: View { let message: String diff --git a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/MapViewObservable.swift b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/MapViewObservable.swift new file mode 100644 index 00000000..f1b788ed --- /dev/null +++ b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/MapViewObservable.swift @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2022-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 + */ + +import Foundation +import heresdk + +class MapViewObservable : ObservableObject { + @Published var mapView: MapView? + + init() { + self.mapView = MapView() + } + + func configureMapView() { + self.mapView = self.mapView ?? MapView() + let camera = self.mapView!.camera + let distanceInMeters = MapMeasure(kind: .distance, value: 1000 * 7) + camera.lookAt(point: GeoCoordinates(latitude: 52.530932, longitude: 13.384915), + zoom: distanceInMeters) + // Load the map scene using a map scheme to render the map with. + self.mapView!.mapScene.loadScene(mapScheme: MapScheme.normalDay, completion: onLoadScene) + + } + + // Completion handler for loadScene(). + private func onLoadScene(mapError: MapError?) { + if let mapError = mapError { + print("Error: Map scene not loaded, \(String(describing: mapError))") + } + } + + func resetMapView() { + self.mapView = nil + } +} + diff --git a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/OfflineMapsApp.swift b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/OfflineMapsApp.swift index 1d6495f8..a2f6f243 100644 --- a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/OfflineMapsApp.swift +++ b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/OfflineMapsApp.swift @@ -24,6 +24,10 @@ import SwiftUI // HERE SDK initialization is done at start of app. When app is terminated, the HERE SDK is disposed. @main struct OfflineMapsApp: App { + + // Set your credentials for the HERE SDK. + static let accessKeyID = "YOUR_ACCESS_KEY_ID" + static let accessKeySecret = "YOUR_ACCESS_KEY_SECRET" var body: some Scene { WindowGroup { @@ -49,11 +53,13 @@ struct OfflineMapsApp: App { } private func initializeHERESDK() { - // Set your credentials for the HERE SDK. - let accessKeyID = "YOUR_ACCESS_KEY_ID" - let accessKeySecret = "YOUR_ACCESS_KEY_SECRET" - let options = SDKOptions(accessKeyId: accessKeyID, accessKeySecret: accessKeySecret) + var options = SDKOptions(accessKeyId: OfflineMapsApp.accessKeyID, accessKeySecret: OfflineMapsApp.accessKeySecret) do { + var features: [LayerConfiguration.Feature] = [] + features = [.detailRendering, .rendering, .offlineSearch] + // With this layer configuration we enable only the listed layers. + // All the other layers including the default layers will be disabled. + options.layerConfiguration = LayerConfiguration(enabledFeatures: features) try SDKNativeEngine.makeSharedInstance(options: options) } catch let engineInstantiationError { fatalError("Failed to initialize the HERE SDK. Cause: \(engineInstantiationError)") diff --git a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/OfflineMapsExample.swift b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/OfflineMapsExample.swift index bab781ca..804e3aa6 100644 --- a/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/OfflineMapsExample.swift +++ b/examples/latest/navigate/ios/OfflineMaps/OfflineMaps/OfflineMapsExample.swift @@ -22,24 +22,26 @@ import SwiftUI class OfflineMapsExample : DownloadRegionsStatusListener { - private let mapView: MapView private var mapDownloader: MapDownloader? private var mapUpdater: MapUpdater? - private let offlineSearchEngine: OfflineSearchEngine + private var offlineSearchEngine: OfflineSearchEngine private var downloadableRegions = [Region]() private var mapDownloaderTasks = [MapDownloaderTask]() private var showMessage: (String) -> Void + private var offlineMode = false + private var offlineSearchEnabled = true; + private var mapViewObservable : MapViewObservable - init(mapView: MapView, showMessageClosure: @escaping (String) -> Void) { - self.mapView = mapView + init(mapViewObservable : MapViewObservable, showMessageClosure: @escaping (String) -> Void) { self.showMessage = showMessageClosure - + self.mapViewObservable = mapViewObservable + // Configure the map. - let camera = mapView.camera + let camera = self.mapViewObservable.mapView!.camera let distanceInMeters = MapMeasure(kind: .distance, value: 1000 * 7) camera.lookAt(point: GeoCoordinates(latitude: 52.530932, longitude: 13.384915), zoom: distanceInMeters) - + do { // Adding offline search engine to show that we can search on downloaded regions. // Note that the engine cannot be used while a map update is in progress and an error will be indicated. @@ -56,15 +58,6 @@ class OfflineMapsExample : DownloadRegionsStatusListener { let storagePath = sdkNativeEngine.options.cachePath showMessage("This example allows to download the region Switzerland. StoragePath: \(storagePath).") - // Create MapDownloader in background to not block the UI thread. - MapDownloader.fromEngineAsync(sdkNativeEngine, { mapDownloader in - self.mapDownloader = mapDownloader - - // Checks the status of already downloaded map data and eventually repairs it. - // Important: For production-ready apps, it is recommended to not do such operations silently in - // the background and instead inform the user. - self.checkInstallationStatus() - }) // Create MapUpdater in background to not block the UI thread. MapUpdater.fromEngineAsync(sdkNativeEngine, { mapUpdater in @@ -72,11 +65,13 @@ class OfflineMapsExample : DownloadRegionsStatusListener { self.performUpdateChecks() }) - + + initMapDownloader(sdkNativeEngine: sdkNativeEngine) + // Load the map scene using a map scheme to render the map with. - mapView.mapScene.loadScene(mapScheme: MapScheme.normalDay, completion: onLoadScene) + self.mapViewObservable.configureMapView() } - + // Completion handler for loadScene(). private func onLoadScene(mapError: MapError?) { if let mapError = mapError { @@ -214,6 +209,92 @@ class OfflineMapsExample : DownloadRegionsStatusListener { return downloadableRegion } + // Download the rectangular area that is currently visible in the viewport. + // It is possible to call downloadArea() in parallel to download multiple areas in parallel. + func onDownloadAreaClicked() { + let downloadAreaStatusListenerImpl = DownloadRegionsStatusListenerImpl() + downloadAreaStatusListenerImpl.showDialog(title: "Note", + message: "Downloading the area that is currently visible in the viewport.") + + let polygonArea = GeoPolygon(geoBox: getMapViewGeoBox()) + _ = mapDownloader?.downloadArea(area: polygonArea, + statusListener: downloadAreaStatusListenerImpl) + } + + private class DownloadRegionsStatusListenerImpl: DownloadRegionsStatusListener { + func onDownloadRegionsComplete(error: MapLoaderError?, regions: [RegionId]?) { + if let mapLoaderError = error { + showDialog(title: "Error", + message: "Download area completion error: \(mapLoaderError.localizedDescription)") + return + } + + // If error is null, it is guaranteed that the regions will not be null. + // When downloading an area, only a single unique ID will be provided. + // Note: It is recommended to store this ID with a human readable name, + // as this will make it easier to delete the downloaded area in the future by calling + // mapDownloader.deleteRegions(...). The ID itself is accessible from InstalledRegions. + // For simplicity, this is not shown here. + if let regionId = regions?.first { + let message = "Download area status. Completed 100%! ID: \(regionId.id)" + print(message) + } + } + + func onProgress(region: RegionId, percentage: Int32) { + // Note that this ID is uniquely created and can be used to delete the area in the future. + let message = "Download of area. ID: \(region.id). Progress: \(percentage)%." + print(message) + } + + func onPause(error: MapLoaderError?) { + if let mapLoaderError = error { + showDialog(title: "Error", + message: "Download area onPause error. The task tried too often to retry the download: \(mapLoaderError.localizedDescription)") + } else { + showDialog(title: "Info", + message: "The area download was paused by the user calling mapDownloaderTask.pause().") + } + } + + func onResume() { + showDialog(title: "Info", message: "A previously paused area download has been resumed.") + } + + func showDialog(title: String, message: String) { + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let rootViewController = windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController { + + let alert = UIAlertController( + title: title, + message: message, + preferredStyle: .alert + ) + + alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in + // Handle OK button action. + alert.dismiss(animated: true, completion: nil) + })) + + rootViewController.present(alert, animated: true, completion: nil) + } + } + } + + private func getMapViewGeoBox() -> GeoBox { + let scaleFactor = UIScreen.main.scale + let mapViewWidthInPixels = Double(mapViewObservable.mapView!.bounds.width * scaleFactor) + let mapViewHeightInPixels = Double(mapViewObservable.mapView!.bounds.height * scaleFactor) + let bottomLeftPoint2D = Point2D(x: 0, y: mapViewHeightInPixels) + let topRightPoint2D = Point2D(x: mapViewWidthInPixels, y: 0) + + let southWestCorner = mapViewObservable.mapView!.viewToGeoCoordinates(viewCoordinates: bottomLeftPoint2D)! + let northEastCorner = mapViewObservable.mapView!.viewToGeoCoordinates(viewCoordinates: topRightPoint2D)! + + // Note: This algorithm assumes an unrotated map view. + return GeoBox(southWestCorner: southWestCorner, northEastCorner: northEastCorner) + } + func onCancelMapDownloadClicked() { for mapDownloaderTask in mapDownloaderTasks { mapDownloaderTask.cancel() @@ -334,7 +415,7 @@ class OfflineMapsExample : DownloadRegionsStatusListener { // the SearchEngine will only search online using HERE backend services. // Keep in mind that the OfflineSearchEngine can also search on cached map data. func onSearchPlaceClicked() { - guard let bbox = mapView.camera.boundingBox else { + guard let bbox = self.mapViewObservable.mapView!.camera.boundingBox else { showMessage("Invalid bounding box.") return } @@ -360,14 +441,113 @@ class OfflineMapsExample : DownloadRegionsStatusListener { } } - func onSwitchOnlineClicked() { - SDKNativeEngine.sharedInstance?.isOfflineMode = false - showMessage("The app is allowed to go online.") + func toggleOfflineMode(){ + offlineMode = !offlineMode; + if offlineMode { + SDKNativeEngine.sharedInstance?.isOfflineMode = true + showMessage("The app is radio-silence.") + } else{ + SDKNativeEngine.sharedInstance?.isOfflineMode = false + showMessage("The app is allowed to go online.") + } } - func onSwitchOfflineClicked() { - SDKNativeEngine.sharedInstance?.isOfflineMode = true - showMessage("The app is radio-silence.") + func toggleConfiguration() { + var options = SDKOptions(accessKeyId: OfflineMapsApp.accessKeyID, accessKeySecret: OfflineMapsApp.accessKeySecret) + + // Toggle the layer configuration + offlineSearchEnabled = !offlineSearchEnabled + var features: [LayerConfiguration.Feature] + + if offlineSearchEnabled { + features = [.detailRendering, .rendering, .offlineSearch] + showMessage("Enabled minimal layer configuration with offlineSearch layer.") + } else { + features = [.detailRendering, .rendering] + showMessage("Enabled minimal layer configuration without offlineSearch layer.") + } + options.layerConfiguration = LayerConfiguration(enabledFeatures: features) + + do { + // Initialize the SDKNativeEngine + try SDKNativeEngine.makeSharedInstance(options: options) + } catch let engineInstantiationError { + showMessage("Failed to initialize the HERE SDK. Cause: \(engineInstantiationError.localizedDescription)") + return + } + + // Reset the map view + self.mapViewObservable.resetMapView() + + do { + // Adding offline search engine to show that we can search on downloaded regions. + // Note that the engine cannot be used while a map update is in progress and an error will be indicated. + try self.offlineSearchEngine = OfflineSearchEngine() + } catch let engineInstantiationError { + fatalError("Failed to initialize OfflineSearchEngine. Cause: \(engineInstantiationError)") + } + + // ReCreate MapUpdater in background to not block the UI thread. + MapUpdater.fromEngineAsync(SDKNativeEngine.sharedInstance!) { mapUpdater in + self.mapUpdater = mapUpdater + _ = mapUpdater.performFeatureUpdate(completion: MapUpdateprogressListenerImpl()) + } + + // Initialize MapDownloader + initMapDownloader(sdkNativeEngine: SDKNativeEngine.sharedInstance!) + } + + private class MapUpdateprogressListenerImpl : MapUpdateProgressListener { + func onProgress(region: heresdk.RegionId, percentage: Int32) { + print("FeatureUpdate: Downloading and installing a map feature update. Progress for \(region.id): \(percentage)%.") + } + + func onPause(error: heresdk.MapLoaderError?) { + if let mapLoaderError = error { + print("Feature update onPause error. The task tried to often to retry the update: \(mapLoaderError).") + } else { + print("FeatureUpdate: The map feature update was paused by the user.") + } + } + + func onComplete(error: heresdk.MapLoaderError?) { + if let mapLoaderError = error { + print("FeatureUpdate completion error: \(mapLoaderError)") + return + } + print("FeatureUpdate: One or more map update has been successfully installed.") + + } + + func onResume() { + print("MapUpdate: A previously paused map feature update has been resumed.") + } + + } + + func initMapDownloader(sdkNativeEngine:SDKNativeEngine){ + // Create MapDownloader in background to not block the UI thread. + MapDownloader.fromEngineAsync(sdkNativeEngine, { mapDownloader in + self.mapDownloader = mapDownloader + + // Checks the status of already downloaded map data and eventually repairs it. + // Important: For production-ready apps, it is recommended to not do such operations silently in + // the background and instead inform the user. + self.checkInstallationStatus() + }) + } + + + // Cached map data will not be removed until the least recently used (LRU) strategy is applied. + // Therefore, we can manually clear the cache to remove any outdated entries. + func clearCache(){ + SDKCache.fromEngine(SDKNativeEngine.sharedInstance!).clearCache { (error) in + if error == nil { + self.showMessage("Cache clear succeeded.") + } else{ + self.showMessage("Cache clear error \(error.debugDescription)") + } + } } private func checkInstallationStatus() { diff --git a/examples/latest/navigate/ios/OfflineMaps/README.md b/examples/latest/navigate/ios/OfflineMaps/README.md index 158bd46e..9b25314f 100644 --- a/examples/latest/navigate/ios/OfflineMaps/README.md +++ b/examples/latest/navigate/ios/OfflineMaps/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `OfflineMapsApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/OffscreenMap/README.md b/examples/latest/navigate/ios/OffscreenMap/README.md index 7f044936..bcd6c473 100644 --- a/examples/latest/navigate/ios/OffscreenMap/README.md +++ b/examples/latest/navigate/ios/OffscreenMap/README.md @@ -20,4 +20,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `exampleApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `OffscreenMapApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/Positioning/README.md b/examples/latest/navigate/ios/Positioning/README.md index d4ff27b1..7d27d7d7 100644 --- a/examples/latest/navigate/ios/Positioning/README.md +++ b/examples/latest/navigate/ios/Positioning/README.md @@ -7,4 +7,4 @@ Build instructions: 2) In Xcode, open the General settings of the App target and make sure that the HERE SDK framework appears under Embedded Binaries. If it does not appear, add the heresdk.framework to the Embedded Binaries section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `PositioningApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/PublicTransit/README.md b/examples/latest/navigate/ios/PublicTransit/README.md index 966d2d2d..c53c0e0d 100644 --- a/examples/latest/navigate/ios/PublicTransit/README.md +++ b/examples/latest/navigate/ios/PublicTransit/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `PublicTransitApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/Rerouting/README.md b/examples/latest/navigate/ios/Rerouting/README.md index 8d3e8393..1a33f5a1 100644 --- a/examples/latest/navigate/ios/Rerouting/README.md +++ b/examples/latest/navigate/ios/Rerouting/README.md @@ -20,4 +20,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `ReroutingApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/Rerouting/Rerouting/ReroutingExample.swift b/examples/latest/navigate/ios/Rerouting/Rerouting/ReroutingExample.swift index 14fb0c88..fa6f893f 100644 --- a/examples/latest/navigate/ios/Rerouting/Rerouting/ReroutingExample.swift +++ b/examples/latest/navigate/ios/Rerouting/Rerouting/ReroutingExample.swift @@ -673,6 +673,7 @@ class ReroutingExample: LongPressDelegate, // will not change very quickly, so that a previous icon will not be overwritten by a parallel call. iconProvider.createRoadShieldIcon(properties: roadShieldIconProperties, mapScheme: MapScheme.normalDay, + assetType: IconProviderAssetType.ui, widthConstraintInPixels: widthConstraintInPixels, heightConstraintInPixels: heightConstraintInPixels, callback: handleIconProviderCallback) diff --git a/examples/latest/navigate/ios/Routing/README.md b/examples/latest/navigate/ios/Routing/README.md index c7847fd8..fc3cd09d 100644 --- a/examples/latest/navigate/ios/Routing/README.md +++ b/examples/latest/navigate/ios/Routing/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `RoutingApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/RoutingHybrid/README.md b/examples/latest/navigate/ios/RoutingHybrid/README.md index ed656a99..7ed1b98d 100644 --- a/examples/latest/navigate/ios/RoutingHybrid/README.md +++ b/examples/latest/navigate/ios/RoutingHybrid/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `RoutingHybridApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/RoutingHybrid/RoutingHybrid/RoutingHybridExample.swift b/examples/latest/navigate/ios/RoutingHybrid/RoutingHybrid/RoutingHybridExample.swift index a15e3453..de0eee1a 100644 --- a/examples/latest/navigate/ios/RoutingHybrid/RoutingHybrid/RoutingHybridExample.swift +++ b/examples/latest/navigate/ios/RoutingHybrid/RoutingHybrid/RoutingHybridExample.swift @@ -146,6 +146,7 @@ class RoutingHybridExample { let outlineColor = UIColor(red: 0.043, green: 0.325, blue: 0.749, alpha: 1) do { // Below, we're creating an instance of MapMeasureDependentRenderSize. This instance will use the scaled width values to render the route polyline. + // We can also apply the same values to MapArrow.setMeasureDependentTailWidth(). // The parameters for the constructor are: the kind of MapMeasure (in this case, ZOOM_LEVEL), the unit of measurement for the render size (PIXELS), and the scaled width values. let mapMeasureDependentLineWidth = try MapMeasureDependentRenderSize(measureKind: MapMeasure.Kind.zoomLevel, sizeUnit: RenderSize.Unit.pixels, sizes: getDefaultLineWidthValues()) @@ -180,7 +181,8 @@ class RoutingHybridExample { } } - // We are retrieving the default route line widths from VisualNavigator and scale them according to the screen's pixel density. + // Retrieves the default widths of a route polyline and maneuver arrows from VisualNavigator, + // scaling them based on the screen's pixel density. // Note that the VisualNavigator stores the width values per zoom level MapMeasure.Kind. private func getDefaultLineWidthValues() -> [Double:Double] { var widthsPerZoomLevel: [Double: Double] = [:]; diff --git a/examples/latest/navigate/ios/Search/README.md b/examples/latest/navigate/ios/Search/README.md index b82e342d..c7ce39e0 100644 --- a/examples/latest/navigate/ios/Search/README.md +++ b/examples/latest/navigate/ios/Search/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `SearchApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/Search/Search.xcodeproj/project.pbxproj b/examples/latest/navigate/ios/Search/Search.xcodeproj/project.pbxproj index 3a298d75..3a9e9501 100644 --- a/examples/latest/navigate/ios/Search/Search.xcodeproj/project.pbxproj +++ b/examples/latest/navigate/ios/Search/Search.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ diff --git a/examples/latest/navigate/ios/Search/Search/ContentView.swift b/examples/latest/navigate/ios/Search/Search/ContentView.swift index c61f2b63..b1305420 100644 --- a/examples/latest/navigate/ios/Search/Search/ContentView.swift +++ b/examples/latest/navigate/ios/Search/Search/ContentView.swift @@ -26,27 +26,29 @@ struct ContentView: View { @State private var searchExample: SearchExample? var body: some View { - // Show the views on top of each other. ZStack(alignment: .top) { - // The map view should fill the entire screen. WrappedMapView(mapView: $mapView) .edgesIgnoringSafeArea(.all) - HStack { - CustomButton(title: "Search example") { - searchExample?.onSearchButtonClicked() - } - CustomButton(title: "GeoCode example") { - searchExample?.onGeoCodeButtonClicked() + VStack(spacing: 10) { + HStack { + CustomButton(title: "Search ") { + searchExample?.onSearchButtonClicked() + } + + CustomButton(title: "GeoCode ") { + searchExample?.onGeoCodeButtonClicked() + } } } - } - .onAppear { - // ContentView appeared, now we init the example. - searchExample = SearchExample(mapView) - } - } + .padding() + } + .onAppear { + // ContentView appeared, now we init the example. + searchExample = SearchExample(mapView) + } + } } // The MapView provided by the HERE SDK conforms to a UIKit view, so it needs to be wrapped to conform diff --git a/examples/latest/navigate/ios/SearchHybrid/README.md b/examples/latest/navigate/ios/SearchHybrid/README.md index 28ec3ed9..a5a9da5c 100644 --- a/examples/latest/navigate/ios/SearchHybrid/README.md +++ b/examples/latest/navigate/ios/SearchHybrid/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `SearchHybridApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/SearchHybrid/SearchHybrid.xcodeproj/project.pbxproj b/examples/latest/navigate/ios/SearchHybrid/SearchHybrid.xcodeproj/project.pbxproj index ff2f0cdb..e99b39d5 100644 --- a/examples/latest/navigate/ios/SearchHybrid/SearchHybrid.xcodeproj/project.pbxproj +++ b/examples/latest/navigate/ios/SearchHybrid/SearchHybrid.xcodeproj/project.pbxproj @@ -3,10 +3,11 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ + 83C4975C2D0C9B9600D67F5E /* W3WSearchExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C4975B2D0C9B9600D67F5E /* W3WSearchExample.swift */; }; 83C837BC2C207F340004F54E /* SearchHybridApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C837BB2C207F340004F54E /* SearchHybridApp.swift */; }; 83C837BE2C207F340004F54E /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83C837BD2C207F340004F54E /* ContentView.swift */; }; 83C837C02C207F360004F54E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 83C837BF2C207F360004F54E /* Assets.xcassets */; }; @@ -31,6 +32,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 83C4975B2D0C9B9600D67F5E /* W3WSearchExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = W3WSearchExample.swift; sourceTree = ""; }; 83C837B82C207F340004F54E /* SearchHybrid.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SearchHybrid.app; sourceTree = BUILT_PRODUCTS_DIR; }; 83C837BB2C207F340004F54E /* SearchHybridApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHybridApp.swift; sourceTree = ""; }; 83C837BD2C207F340004F54E /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; @@ -75,6 +77,7 @@ 83C837BB2C207F340004F54E /* SearchHybridApp.swift */, 83C837BD2C207F340004F54E /* ContentView.swift */, 83C837D02C20EFA70004F54E /* SearchHybridExample.swift */, + 83C4975B2D0C9B9600D67F5E /* W3WSearchExample.swift */, 83C837BF2C207F360004F54E /* Assets.xcassets */, 83C837C12C207F360004F54E /* Preview Content */, ); @@ -168,6 +171,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 83C4975C2D0C9B9600D67F5E /* W3WSearchExample.swift in Sources */, 83C837BE2C207F340004F54E /* ContentView.swift in Sources */, 83C837BC2C207F340004F54E /* SearchHybridApp.swift in Sources */, 83C837D12C20EFA70004F54E /* SearchHybridExample.swift in Sources */, diff --git a/examples/latest/navigate/ios/SearchHybrid/SearchHybrid/ContentView.swift b/examples/latest/navigate/ios/SearchHybrid/SearchHybrid/ContentView.swift index 3969ba77..05633a76 100644 --- a/examples/latest/navigate/ios/SearchHybrid/SearchHybrid/ContentView.swift +++ b/examples/latest/navigate/ios/SearchHybrid/SearchHybrid/ContentView.swift @@ -24,6 +24,7 @@ struct ContentView: View { @State private var mapView = MapView() @State private var searchHybridExample: SearchHybridExample? + @State private var w3wSearchExample: W3WSearchExample? var body: some View { // Show the views on top of each other. @@ -42,6 +43,14 @@ struct ContentView: View { searchHybridExample?.onGeoCodeButtonClicked() } } + HStack { + CustomButton(title: "W3W Search") { + w3wSearchExample?.onW3WSearchButtonClicked() + } + CustomButton(title: "W3W GeoCode") { + w3wSearchExample?.onW3WGeoCodeButtonClicked() + } + } HStack { CustomToggleButton(onLabel: "Online: On", offLabel: "Online: Off") { searchHybridExample?.onToggleOnlineButton() @@ -50,8 +59,9 @@ struct ContentView: View { } } .onAppear { - // ContentView appeared, now we init the example. + // ContentView appeared, now we init the examples. searchHybridExample = SearchHybridExample(mapView) + w3wSearchExample = W3WSearchExample(mapView) } } } diff --git a/examples/latest/navigate/ios/SearchHybrid/SearchHybrid/W3WSearchExample.swift b/examples/latest/navigate/ios/SearchHybrid/SearchHybrid/W3WSearchExample.swift new file mode 100644 index 00000000..cd0e2a91 --- /dev/null +++ b/examples/latest/navigate/ios/SearchHybrid/SearchHybrid/W3WSearchExample.swift @@ -0,0 +1,133 @@ +/* + * 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 + */ + +import heresdk +import SwiftUI + +/** + * The W3WSearchExample class demonstrates the use of the W3WSearchEngine + * to perform operations with what3words terms. + * + * With the W3WSearchEngine, you can: + * - Resolve a what3words term to an address and geographic coordinates. + * - Find a what3words term for given geographic coordinates. + * + * Both approaches are demonstrated in the examples below. + * The W3WSearchEngine interacts with the https://what3words.com/ backend + * to perform these operations. + */ +class W3WSearchExample{ + + private var w3wSearchEngine : W3WSearchEngine + + init(_ mapView: MapView) { + + // Configure the map. + let camera = mapView.camera + let distanceInMeters = MapMeasure(kind: .distance, value: 1000 * 10) + camera.lookAt(point: GeoCoordinates(latitude: 52.520798, longitude: 13.409408), + zoom: distanceInMeters) + + do { + try w3wSearchEngine = W3WSearchEngine() + } catch let engineInstantiationError { + fatalError("Failed to initialize W3WSearchEngine. Cause: \(engineInstantiationError)") + } + + // Load the map scene using a map scheme to render the map with. + mapView.mapScene.loadScene(mapScheme: MapScheme.normalDay, completion: onLoadScene) + } + + // Completion handler for loadScene(). + private func onLoadScene(mapError: MapError?) { + if let mapError = mapError { + print("Error: Map scene not loaded, \(String(describing: mapError))") + } + } + + func onW3WSearchButtonClicked() { + // W3W sample "dizzy.vanilla.singer" used for demonstration purposes. Replace with user input as needed. + let searchWords = "dizzy.vanilla.singer" + + /* Finds the location of a known What3Words term. + * This method searches for the geographic location corresponding to a given three-word address + * (e.g., "dizzy.vanilla.singer"). It uses the What3Words API to resolve the three-word address into + * a square on the map, retrieving additional details such as the square's coordinates and language. + */ + w3wSearchEngine.search(words: searchWords) { [weak self] error, W3WSquare in + guard let self = self else { return } + if let error = error { + self.showDialog(title: "W3W Search Error", message: "\(error)") + return + } else if let w3wSquare = W3WSquare { + let message = """ + 3-word address: \(w3wSquare.words) + Language: \(w3wSquare.languageCode) + Coordinates: \(w3wSquare.coordinates.latitude), \(w3wSquare.coordinates.longitude) + """ + self.showDialog(title: "What3Words Details", message: message) + } + } + } + + func onW3WGeoCodeButtonClicked() { + let coordinates = GeoCoordinates(latitude: 53.520798, longitude: 13.409408) + + // The language code for the desired three-word address. + // ISO 639-1 code "en" specifies that the three-word address will be in English. + let w3wLanguageCode = "en"; + + /* Resolves geographic coordinates to a What3Words address (three-word format). + * This method uses the What3Words search engine to find a three-word address based + * on the provided coordinates (latitude and longitude). The result includes + * additional details such as the square's coordinates and language. + */ + w3wSearchEngine.search(coordinates: coordinates, language: w3wLanguageCode) { [weak self] error, W3WSquare in + guard let self = self else { return } + + if let error = error { + self.showDialog(title: "W3W reverse geocoding failed with error:", message: "\(error)") + return + } else if let w3wSquare = W3WSquare { + let message = """ + 3-word address: \(w3wSquare.words) + Language: \(w3wSquare.languageCode) + Coordinates: \(w3wSquare.coordinates.latitude), \(w3wSquare.coordinates.longitude) + """ + self.showDialog(title: "Geocoding Details", message: message) + } else { + print("W3W reverse geocoding returned no results.") + self.showDialog(title: "No Result", message: "W3W reverse geocoding returned no results.") + } + } + } + + private func showDialog(title: String, message: String) { + let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert) + let okAction = UIAlertAction(title: "OK", style: .default, handler: nil) + alertController.addAction(okAction) + if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, + let keyWindow = windowScene.windows.first(where: { $0.isKeyWindow }), + let topViewController = keyWindow.rootViewController { + topViewController.present(alertController, animated: true, completion: nil) + } else { + print("Error: Unable to find key window or root view controller.") + } + } +} diff --git a/examples/latest/navigate/ios/Traffic/README.md b/examples/latest/navigate/ios/Traffic/README.md index 16c2ff36..c126adc6 100644 --- a/examples/latest/navigate/ios/Traffic/README.md +++ b/examples/latest/navigate/ios/Traffic/README.md @@ -11,4 +11,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `TrafficApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. diff --git a/examples/latest/navigate/ios/TruckGuidance/README.md b/examples/latest/navigate/ios/TruckGuidance/README.md index cc8d265b..743228a9 100644 --- a/examples/latest/navigate/ios/TruckGuidance/README.md +++ b/examples/latest/navigate/ios/TruckGuidance/README.md @@ -24,4 +24,4 @@ Note: If your framework version is different than the version shown in the _Deve Note: In Xcode, open the _General_ settings of the _App target_ and make sure that the HERE SDK framework appears under _Embedded Binaries_. If it does not appear, add the `heresdk.framework` to the _Embedded Binaries_ section ("Add other..." -> "Create folder references"). -Please do not forget: To run the app, you need to add your HERE SDK credentials to the `AppDelegate.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_. +Please do not forget: To run the app, you need to add your HERE SDK credentials to the `TruckGuidanceApp.swift` file of your project. More information can be found in the _Get Started_ section of the _Developer Guide_.