diff --git a/README.md b/README.md index d191a0f0c..9dfa8d8dd 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,21 @@ -# ArcGIS Maps SDK Kotlin Samples +# ArcGIS Maps SDK Kotlin Samples + +[![Link: ArcGIS Developers home](https://img.shields.io/badge/ArcGIS%20Developers%20Home-633b9b?style=flat-square)](https://developers.arcgis.com) +[![Link: Documentation](https://img.shields.io/badge/Documentation-633b9b?style=flat-square)](https://developers.arcgis.com/kotlin/) +[![Link: Tutorials](https://img.shields.io/badge/Tutorials-633b9b?style=flat-square)](https://developers.arcgis.com/documentation/mapping-apis-and-services/tutorials/) +[![Badge: Samples](https://img.shields.io/badge/Samples-633b9b?style=flat-square)](https://developers.arcgis.com/kotlin/sample-code/) +[![Link: Toolkit](https://img.shields.io/badge/Toolkit-633b9b?style=flat-square)](https://developers.arcgis.com/kotlin/toolkit/) +[![Link: Esri Community](https://img.shields.io/badge/🙋-Get%20help%20in%20Esri%20Community-633b9b?style=flat-square)](https://community.esri.com/t5/kotlin-maps-sdk-questions/bd-p/kotlin-maps-sdk-questions) + + Get it on Google Play ## Overview -ArcGIS Maps SDK for Kotlin v200.5.0 samples. The `main` branch of this repository contains sample app modules for the latest available version of the [ArcGIS Maps SDK Android Kotlin](https://developers.arcgis.com/kotlin/). Samples released under older versions can be found through the [git tags](https://github.com/Esri/arcgis-maps-sdk-kotlin-samples/tags). Please read our [wiki](https://github.com/Esri/arcgis-maps-sdk-kotlin-samples/wiki) for help with working with this repository. +ArcGIS Maps SDK for Kotlin v200.6.0 samples. The `main` branch of this repository contains sample app modules for the latest available version of the [ArcGIS Maps Kotlin SDK](https://developers.arcgis.com/kotlin/). Samples released under older versions can be found through the [git tags](https://github.com/Esri/arcgis-maps-sdk-kotlin-samples/tags). Please read our [wiki](https://github.com/Esri/arcgis-maps-sdk-kotlin-samples/wiki) for help with working with this repository. ## Prerequisites -* The samples are building with `compileSdkVersion 33` +* The samples are building with `compileSdkVersion 35` * [Android Studio](http://developer.android.com/sdk/index.html) * [An ArcGIS Developers API key](https://developers.arcgis.com/kotlin/get-started/#3-get-an-api-key) @@ -31,11 +40,11 @@ A long-lived access token that gives your application access to ArcGIS location * **Location services** > **Geocoding** * **Location services** > **Routing** -The Android samples in this repository have been structured to use an API key, set once, which will run in all samples. -Set your API key in the `gradle.properties` file located in the `/.gradle` folder within your home directory. -The API_KEY property should contain quotes around the key itself: +The Kotlin samples in this repository have been structured to use an access token, set once, which will run in all samples. +Set your access token in the `local.properties` in the same folder as the `secrets.defaults.properties`. +The ACCESS_TOKEN property should contain quotes around the key itself: ```gradle -API_KEY = "YOUR_API_KEY" // path: /Users//.gradle/gradle.properties +ACCESS_TOKEN=YOUR_ACCESS_TOKEN ``` ### ArcGIS identity @@ -62,7 +71,7 @@ $ ./gradlew assembleDebug adb -d install path/to/sample.apk ``` -Built APK's are saved to **arcgis-maps-sdk-kotlin-samples/[module-name]/build/outputs/apk/**. More information about running apps on devices can be found [here](https://developer.android.com/studio/run/device.html). +Built APK's are saved to **arcgis-maps-sdk-kotlin-samples/app/build/outputs/**. More information about running apps on devices can be found [here](https://developer.android.com/studio/run/device.html). ## Issues @@ -83,6 +92,18 @@ Anyone and everyone is welcome to [contribute](.github/CONTRIBUTING.md). We do a Please see our [guidelines for contributing doc](https://github.com/Esri/contributing/blob/master/README.md) +## Third-Party Libraries + +This project uses the following third-party libraries: + +- **[Showdown](https://github.com/showdownjs/showdown/blob/master/LICENSE)** + - License: MIT License + - Copyright: 2018, 2021 + +- **[Highlight.js](https://github.com/highlightjs/highlight.js/blob/main/LICENSE)** + - License: BSD 3-Clause License + - Copyright: 2006, Ivan Sagalaev + ## Licensing Copyright 2022 Esri diff --git a/add-3d-tiles-layer/build.gradle.kts b/add-3d-tiles-layer/build.gradle.kts deleted file mode 100644 index a62055933..000000000 --- a/add-3d-tiles-layer/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.add3dtileslayer" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.add3dtileslayer" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/add-3d-tiles-layer/proguard-rules.pro b/add-3d-tiles-layer/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/add-3d-tiles-layer/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/add-3d-tiles-layer/src/main/AndroidManifest.xml b/add-3d-tiles-layer/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/add-3d-tiles-layer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/add-3d-tiles-layer/src/main/java/com/esri/arcgismaps/sample/add3dtileslayer/MainActivity.kt b/add-3d-tiles-layer/src/main/java/com/esri/arcgismaps/sample/add3dtileslayer/MainActivity.kt deleted file mode 100644 index c4332ff6a..000000000 --- a/add-3d-tiles-layer/src/main/java/com/esri/arcgismaps/sample/add3dtileslayer/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.add3dtileslayer - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.add3dtileslayer.screens.MainScreen -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - Add3DTilesLayerApp() - } - } - } - - @Composable - private fun Add3DTilesLayerApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/add-3d-tiles-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml b/add-3d-tiles-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/add-3d-tiles-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/add-3d-tiles-layer/src/main/res/drawable/ic_launcher_background.xml b/add-3d-tiles-layer/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/add-3d-tiles-layer/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/add-3d-tiles-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/add-3d-tiles-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-3d-tiles-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-3d-tiles-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/add-3d-tiles-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-3d-tiles-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-3d-tiles-layer/src/main/res/mipmap-hdpi/ic_launcher.png b/add-3d-tiles-layer/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png b/add-3d-tiles-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-mdpi/ic_launcher.png b/add-3d-tiles-layer/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png b/add-3d-tiles-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-xhdpi/ic_launcher.png b/add-3d-tiles-layer/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/add-3d-tiles-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png b/add-3d-tiles-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/add-3d-tiles-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/add-3d-tiles-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/add-3d-tiles-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/add-3d-tiles-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-3d-tiles-layer/src/main/res/values/strings.xml b/add-3d-tiles-layer/src/main/res/values/strings.xml deleted file mode 100644 index 53e685ff8..000000000 --- a/add-3d-tiles-layer/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Add 3D tiles layer - diff --git a/add-custom-dynamic-entity-data-source/.gitignore b/add-custom-dynamic-entity-data-source/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/add-custom-dynamic-entity-data-source/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/add-custom-dynamic-entity-data-source/README.metadata.json b/add-custom-dynamic-entity-data-source/README.metadata.json deleted file mode 100644 index 8d4914aca..000000000 --- a/add-custom-dynamic-entity-data-source/README.metadata.json +++ /dev/null @@ -1,46 +0,0 @@ -{ - "category": "Layers", - "description": "Create a custom dynamic entity data source and display it using a dynamic entity layer.", - "formal_name": "AddCustomDynamicEntityDataSource", - "ignore": false, - "images": [ - "add-custom-dynamic-entity-data-source.png" - ], - "keywords": [ - "callout", - "data", - "dynamic", - "entity", - "flow", - "label", - "labeling", - "live", - "real-time", - "stream", - "track", - "CustomDynamicEntityDataSource.EntityFeedProvider", - "DynamicEntity", - "DynamicEntityDataSource", - "DynamicEntityLayer", - "LabelDefinition", - "TrackDisplayProperties" - ], - "language": "kotlin", - "redirect_from": "", - "relevant_apis": [ - "CustomDynamicEntityDataSource.EntityFeedProvider", - "DynamicEntity", - "DynamicEntityDataSource", - "DynamicEntityLayer", - "LabelDefinition", - "TrackDisplayProperties" - ], - "snippets": [ - "src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/MainActivity.kt", - "src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/DownloadActivity.kt", - "src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/components/CustomEntityFeedProvider.kt", - "src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/components/MapViewModel.kt", - "src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/screens/MainScreen.kt" - ], - "title": "Add custom dynamic entity data source" -} diff --git a/add-custom-dynamic-entity-data-source/build.gradle.kts b/add-custom-dynamic-entity-data-source/build.gradle.kts deleted file mode 100644 index 2be6d5561..000000000 --- a/add-custom-dynamic-entity-data-source/build.gradle.kts +++ /dev/null @@ -1,56 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.addcustomdynamicentitydatasource" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.addcustomdynamicentitydatasource" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) - - implementation(libs.serialization) -} diff --git a/add-custom-dynamic-entity-data-source/proguard-rules.pro b/add-custom-dynamic-entity-data-source/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/add-custom-dynamic-entity-data-source/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/add-custom-dynamic-entity-data-source/src/main/AndroidManifest.xml b/add-custom-dynamic-entity-data-source/src/main/AndroidManifest.xml deleted file mode 100644 index 8eaea2ef4..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/DownloadActivity.kt b/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/DownloadActivity.kt deleted file mode 100644 index 62b5a83f6..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/DownloadActivity.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.addcustomdynamicentitydatasource - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - // ArcGIS Portal item containing the json file of observations of marine vessels in - // the Pacific North West - listOf( - "https://www.arcgis.com/home/item.html?id=a8a942c228af4fac96baa78ad60f511f" - ) - ) - } -} diff --git a/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/MainActivity.kt b/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/MainActivity.kt deleted file mode 100644 index fa1d4c1f4..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.addcustomdynamicentitydatasource - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.addcustomdynamicentitydatasource.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - SampleApp() - } - } - } - - @Composable - private fun SampleApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/components/MapViewModel.kt b/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/components/MapViewModel.kt deleted file mode 100644 index 043b3292c..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/java/com/esri/arcgismaps/sample/addcustomdynamicentitydatasource/components/MapViewModel.kt +++ /dev/null @@ -1,198 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.addcustomdynamicentitydatasource.components - -import android.app.Application -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.compose.ui.unit.dp -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.viewModelScope -import com.arcgismaps.arcgisservices.LabelingPlacement -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.GeoElement -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.labeling.LabelDefinition -import com.arcgismaps.mapping.labeling.SimpleLabelExpression -import com.arcgismaps.mapping.layers.DynamicEntityLayer -import com.arcgismaps.mapping.layers.Layer -import com.arcgismaps.mapping.symbology.TextSymbol -import com.arcgismaps.mapping.view.SingleTapConfirmedEvent -import com.arcgismaps.realtime.ConnectionStatus -import com.arcgismaps.realtime.CustomDynamicEntityDataSource -import com.arcgismaps.realtime.DynamicEntityObservation -import com.arcgismaps.toolkit.geoviewcompose.MapViewProxy -import com.esri.arcgismaps.sample.addcustomdynamicentitydatasource.R -import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.Job -import kotlinx.coroutines.cancelAndJoin -import kotlinx.coroutines.launch -import java.io.File -import kotlin.time.Duration.Companion.milliseconds - -class MapViewModel(application: Application) : AndroidViewModel(application) { - - // Keep track of connected status string state. - var connectionStatusString by mutableStateOf("") - private set - - // Set connection status string in he UI. - private fun updateConnectionStatusString(connectionStatus: String) { - connectionStatusString = connectionStatus - } - - private val provisionPath: String by lazy { - application.getExternalFilesDir(null)?.path.toString() + File.separator + application.getString( - R.string.app_name - ) - } - - // Create a new custom feed provider that processes observations from a JSON file. - // This takes the path to the simulation file, field name that will be used as the entity id, - // and the delay between each observation that is processed. - // In this example we are using a json file as our custom data source. - // This field value should be a unique identifier for each entity. - // Adjusting the value for the delay will change the speed at which the entities and their - // observations are displayed. - private val feedProvider = CustomEntityFeedProvider( - fileName = "$provisionPath/AIS_MarineCadastre_SelectedVessels_CustomDataSource.jsonl", - entityIdField = "MMSI", - delayDuration = 10.milliseconds - ) - - private val dynamicEntityDataSource = CustomDynamicEntityDataSource(feedProvider).apply { - // Observe the connection status of the custom data source. - viewModelScope.launch { - connectionStatus.collect { connectionStatus -> - updateConnectionStatusString( - when (connectionStatus) { - is ConnectionStatus.Connected -> "Connected" - is ConnectionStatus.Disconnected -> "Disconnected" - is ConnectionStatus.Connecting -> "Connecting" - is ConnectionStatus.Failed -> "Failed" - } - ) - } - } - } - - // Create the dynamic entity layer using the custom data source. - private val dynamicEntityLayer = DynamicEntityLayer(dynamicEntityDataSource).apply { - trackDisplayProperties.apply { - // Set up the track display properties, these properties will be used to configure the appearance of the track line and previous observations. - showPreviousObservations = true - showTrackLine = true - maximumObservations = 20 - } - - // Define the label expression to be used, in this case we will use the "VesselName" for each of the dynamic entities. - val simpleLabelExpression = SimpleLabelExpression("[VesselName]") - - // Set the text symbol color and size for the labels. - val labelSymbol = TextSymbol().apply { - color = com.arcgismaps.Color.red - size = 12.0F - } - - // Add the label definition to the dynamic entity layer and enable labels. - labelDefinitions.add(LabelDefinition(simpleLabelExpression, labelSymbol).apply { - // Set the label position. - placement = LabelingPlacement.PointAboveCenter - }) - labelsEnabled = true - } - - val arcGISMap = ArcGISMap(BasemapStyle.ArcGISOceans).apply { - initialViewpoint = Viewpoint(47.984, -123.657, 3e6) - // Add the dynamic entity layer to the map. - operationalLayers.add(dynamicEntityLayer) - } - - // Create a mapViewProxy that will be used to identify features in the MapView. - // This should also be passed to the composable MapView this mapViewProxy is associated with. - val mapViewProxy = MapViewProxy() - - // create a ViewModel to handle dialog interactions - val messageDialogVM: MessageDialogViewModel = MessageDialogViewModel() - - fun dynamicEntityDataSourceConnect() = - viewModelScope.launch { dynamicEntityDataSource.connect() } - - fun dynamicEntityDataSourceDisconnect() = - viewModelScope.launch { dynamicEntityDataSource.disconnect() } - - // Keep track of the currently selected GeoElement. - var selectedGeoElement by mutableStateOf(null) - private set - - // Keep track of the most recent observation string. - var observationString by mutableStateOf("") - private set - - // Keep track of the Coroutine Scope where observations on being collected on, so that it can - // be cancelled on subsequent identifies. - private var observationsJob: Job? = null - - /** - * Identifies the tapped screen coordinate in the provided [singleTapConfirmedEvent] - */ - fun identify(singleTapConfirmedEvent: SingleTapConfirmedEvent) { - viewModelScope.launch { - // If collecting observations on a previous identify, now cancel and stop collecting. - observationsJob?.cancelAndJoin() - // identify the cluster in the feature layer on the tapped coordinate - mapViewProxy.identify( - dynamicEntityLayer as Layer, - screenCoordinate = singleTapConfirmedEvent.screenCoordinate, - tolerance = 12.dp, - maximumResults = 1 - ).onSuccess { result -> - (result.geoElements.firstOrNull() as? DynamicEntityObservation)?.let { observation -> - // Set the identified dynamic entity, used to display the callout. - selectedGeoElement = observation.dynamicEntity - // Define a new CoroutineScope to collect observation events on. - observationsJob = launch(Dispatchers.IO) { - // Collect observation events and update the observation string accordingly. - observation.dynamicEntity?.dynamicEntityChangedEvent?.collect { dynamicEntityChangedInfo -> - // Parse the observation attributes, filter out empty values, and remove - // starting and ending {}s. - observationString = dynamicEntityChangedInfo - .receivedObservation?.attributes?.filter { - it.value.toString().isNotEmpty() && !it.key.contains("globalid") - }.toString() - .replaceFirst("{", " ") - .removeSuffix("}") - .replace(",", "\n") - } - } - // If no observation is found, set the selectedGeoElement to null. - } ?: run { - selectedGeoElement = null - observationString = "Waiting for a new observation ..." - } - }.onFailure { error -> - messageDialogVM.showMessageDialog( - title = "Error identifying results: ${error.message.toString()}", - description = error.cause.toString() - ) - } - } - } -} diff --git a/add-custom-dynamic-entity-data-source/src/main/res/drawable-v24/ic_launcher_foreground.xml b/add-custom-dynamic-entity-data-source/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/add-custom-dynamic-entity-data-source/src/main/res/drawable/ic_launcher_background.xml b/add-custom-dynamic-entity-data-source/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-hdpi/ic_launcher.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-hdpi/ic_launcher_round.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-mdpi/ic_launcher.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-mdpi/ic_launcher_round.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xhdpi/ic_launcher.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxhdpi/ic_launcher.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/add-custom-dynamic-entity-data-source/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-custom-dynamic-entity-data-source/src/main/res/values/strings.xml b/add-custom-dynamic-entity-data-source/src/main/res/values/strings.xml deleted file mode 100644 index de8acea66..000000000 --- a/add-custom-dynamic-entity-data-source/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Add custom dynamic entity data source - Connect - Disconnect - diff --git a/add-dynamic-entity-layer/build.gradle.kts b/add-dynamic-entity-layer/build.gradle.kts deleted file mode 100644 index edcdafaf3..000000000 --- a/add-dynamic-entity-layer/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.adddynamicentitylayer" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.adddynamicentitylayer" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/add-dynamic-entity-layer/proguard-rules.pro b/add-dynamic-entity-layer/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/add-dynamic-entity-layer/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/add-dynamic-entity-layer/src/main/AndroidManifest.xml b/add-dynamic-entity-layer/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/add-dynamic-entity-layer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/add-dynamic-entity-layer/src/main/java/com/esri/arcgismaps/sample/adddynamicentitylayer/MainActivity.kt b/add-dynamic-entity-layer/src/main/java/com/esri/arcgismaps/sample/adddynamicentitylayer/MainActivity.kt deleted file mode 100644 index 602ca410f..000000000 --- a/add-dynamic-entity-layer/src/main/java/com/esri/arcgismaps/sample/adddynamicentitylayer/MainActivity.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.adddynamicentitylayer - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.adddynamicentitylayer.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - setContent { - SampleAppTheme { - AddDynamicEntityLayerApp() - } - } - } - - @Composable - private fun AddDynamicEntityLayerApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/add-dynamic-entity-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml b/add-dynamic-entity-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/add-dynamic-entity-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/add-dynamic-entity-layer/src/main/res/drawable/ic_launcher_background.xml b/add-dynamic-entity-layer/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/add-dynamic-entity-layer/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/add-dynamic-entity-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-dynamic-entity-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/add-dynamic-entity-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-dynamic-entity-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-hdpi/ic_launcher.png b/add-dynamic-entity-layer/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png b/add-dynamic-entity-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-mdpi/ic_launcher.png b/add-dynamic-entity-layer/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png b/add-dynamic-entity-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-xhdpi/ic_launcher.png b/add-dynamic-entity-layer/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/add-dynamic-entity-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png b/add-dynamic-entity-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/add-dynamic-entity-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/add-dynamic-entity-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/add-dynamic-entity-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/add-dynamic-entity-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-dynamic-entity-layer/src/main/res/values/strings.xml b/add-dynamic-entity-layer/src/main/res/values/strings.xml deleted file mode 100644 index d5d718e78..000000000 --- a/add-dynamic-entity-layer/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Add dynamic entity layer - https://realtimegis2016.esri.com:6443/arcgis/rest/services/SandyVehicles/StreamServer - diff --git a/add-feature-layers/.gitignore b/add-feature-layers/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/add-feature-layers/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/add-feature-layers/build.gradle.kts b/add-feature-layers/build.gradle.kts deleted file mode 100644 index c2b5c393c..000000000 --- a/add-feature-layers/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.addfeaturelayers" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.addfeaturelayers" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(libs.androidx.appcompat) - implementation(project(":samples-lib")) -} diff --git a/add-feature-layers/proguard-rules.pro b/add-feature-layers/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/add-feature-layers/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/add-feature-layers/src/main/AndroidManifest.xml b/add-feature-layers/src/main/AndroidManifest.xml deleted file mode 100644 index d2957b0d5..000000000 --- a/add-feature-layers/src/main/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/add-feature-layers/src/main/java/com/esri/arcgismaps/sample/addfeaturelayers/DownloadActivity.kt b/add-feature-layers/src/main/java/com/esri/arcgismaps/sample/addfeaturelayers/DownloadActivity.kt deleted file mode 100644 index 6a148ab74..000000000 --- a/add-feature-layers/src/main/java/com/esri/arcgismaps/sample/addfeaturelayers/DownloadActivity.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.esri.arcgismaps.sample.addfeaturelayers - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // ArcGIS Portal item containing the .mmpk mobile map package - "https://www.arcgis.com/home/item.html?id=cb1b20748a9f4d128dad8a87244e3e37", - // ArcGIS Portal item containing shapefiles of Scottish Wildlife Trust reserve boundaries - "https://www.arcgis.com/home/item.html?id=15a7cbd3af1e47cfa5d2c6b93dc44fc2", - // GeoPackage AuroraCO.gpkg with datasets that cover Aurora Colorado - "https://www.arcgis.com/home/item.html?id=68ec42517cdd439e81b036210483e8e7" - ) - ) - } -} diff --git a/add-feature-layers/src/main/java/com/esri/arcgismaps/sample/addfeaturelayers/MainActivity.kt b/add-feature-layers/src/main/java/com/esri/arcgismaps/sample/addfeaturelayers/MainActivity.kt deleted file mode 100644 index 40595117e..000000000 --- a/add-feature-layers/src/main/java/com/esri/arcgismaps/sample/addfeaturelayers/MainActivity.kt +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.addfeaturelayers - -import android.os.Bundle -import android.util.Log -import android.widget.ArrayAdapter -import android.widget.Toast -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.data.GeoPackage -import com.arcgismaps.data.Geodatabase -import com.arcgismaps.data.ServiceFeatureTable -import com.arcgismaps.data.ShapefileFeatureTable -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.layers.FeatureLayer -import com.arcgismaps.portal.Portal -import com.arcgismaps.mapping.PortalItem -import com.esri.arcgismaps.sample.addfeaturelayers.databinding.ActivityMainBinding -import kotlinx.coroutines.launch -import java.io.File - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - // enum to keep track of the selected source to display the feature layer - enum class FeatureLayerSource(val menuPosition: Int) { - SERVICE_FEATURE_TABLE(0), - PORTAL_ITEM(1), - GEODATABASE(2), - GEOPACKAGE(3), - SHAPEFILE(4) - } - - // keeps track of the previously selected feature layer source - private var previousSource: FeatureLayerSource? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - // set the map to be displayed in as the BasemapStyle topographic - activityMainBinding.mapView.map = ArcGISMap(BasemapStyle.ArcGISTopographic) - setUpBottomUI() - } - - /** - * Sets the map using the [layer] at the given [viewpoint] - */ - private fun setFeatureLayer(layer: FeatureLayer, viewpoint: Viewpoint) { - activityMainBinding.mapView.apply { - // clears the existing layer on the map - map?.operationalLayers?.clear() - // adds the new layer to the map - map?.operationalLayers?.add(layer) - // updates the viewpoint to the given viewpoint - setViewpoint(viewpoint) - } - } - - /** - * Load a feature layer with a URL - */ - private fun loadFeatureServiceURL() { - // initialize the service feature table using a URL - val serviceFeatureTable = - ServiceFeatureTable(resources.getString(R.string.sample_service_url)) - // create a feature layer with the feature table - val featureLayer = FeatureLayer.createWithFeatureTable(serviceFeatureTable) - val viewpoint = Viewpoint(41.70, -88.20, 120000.0) - // set the feature layer on the map - setFeatureLayer(featureLayer, viewpoint) - } - - - /** - * Load a feature layer with a portal item - */ - private suspend fun loadPortalItem() { - // set the portal - val portal = Portal("https://www.arcgis.com") - // create the portal item with the item ID for the Portland tree service data - val portalItem = PortalItem(portal, "1759fd3e8a324358a0c58d9a687a8578") - portalItem.load().onSuccess { - // create the feature layer with the item - val featureLayer = FeatureLayer.createWithItem(portalItem) - // set the viewpoint to Portland, Oregon - val viewpoint = Viewpoint(45.5266, -122.6219, 2500.0) - // set the feature layer on the map - setFeatureLayer(featureLayer, viewpoint) - }.onFailure { - showError("Error loading portal item: ${it.message}") - } - } - - /** - * Load a feature layer with a local geodatabase file - */ - private suspend fun loadGeodatabase() { - // locate the .geodatabase file in the device - val geodatabaseFile = File(provisionPath, getString(R.string.geodatabase_la_trails)) - // instantiate the geodatabase with the file path - val geodatabase = Geodatabase(geodatabaseFile.path) - // load the geodatabase - geodatabase.load().onSuccess { - // get the feature table with the name - val geodatabaseFeatureTable = - geodatabase.getFeatureTable("Trailheads") - if (geodatabaseFeatureTable == null) { - showError("Feature table name not found in geodatabase") - return - } - // create a feature layer with the feature table - val featureLayer = FeatureLayer.createWithFeatureTable(geodatabaseFeatureTable) - // set the viewpoint to Malibu, California - val viewpoint = Viewpoint(34.0772, -118.7989, 600000.0) - // set the feature layer on the map - setFeatureLayer(featureLayer, viewpoint) - }.onFailure { - showError("Error loading geodatabase: ${it.message}") - } - } - - /** - * Load a feature layer with a local geopackage file - */ - private suspend fun loadGeopackage() { - // locate the .gpkg file in the device - val geopackageFile = File(provisionPath, "/AuroraCO.gpkg") - // instantiate the geopackage with the file path - val geoPackage = GeoPackage(geopackageFile.path) - // load the geopackage - geoPackage.load().onSuccess { - // get the first feature table in the geopackage - val geoPackageFeatureTable = geoPackage.geoPackageFeatureTables.first() - // create a feature layer with the feature table - val featureLayer = FeatureLayer.createWithFeatureTable(geoPackageFeatureTable) - // set the viewpoint to Denver, CO - val viewpoint = Viewpoint(39.7294, -104.8319, 500000.0) - // set the feature layer on the map - setFeatureLayer(featureLayer, viewpoint) - }.onFailure { - showError("Error loading geopackage: ${it.message}") - } - } - - /** - * Load a feature layer with a local shapefile file - */ - private suspend fun loadShapefile() { - // locate the shape file in device - val file = File( - provisionPath, - "/ScottishWildlifeTrust_ReserveBoundaries_20201102.shp" - ) - // create a shapefile feature table from a named bundle resource - val shapeFileTable = ShapefileFeatureTable(file.path) - shapeFileTable.load().onSuccess { - // create a feature layer for the shapefile feature table - val featureLayer = FeatureLayer.createWithFeatureTable(shapeFileTable) - // set the viewpoint to Scotland - val viewpoint = Viewpoint(56.641344, -3.889066, 6000000.0) - // set the feature layer on the map - setFeatureLayer(featureLayer, viewpoint) - }.onFailure { - showError("Error loading shapefile: ${it.message}") - } - } - - private fun showError(message: String) { - Toast.makeText(this@MainActivity, message, Toast.LENGTH_SHORT).show() - Log.e(localClassName, message) - } - - /** - * Sets up the bottom UI selector to switch between - * different ways to load a feature layers - */ - private fun setUpBottomUI() { - // create an adapter with the types of feature layer - // sources to be displayed in menu - val adapter = ArrayAdapter( - this, - android.R.layout.simple_list_item_1, - resources.getStringArray(R.array.feature_layer_sources) - ) - activityMainBinding.bottomListItems.apply { - // populate the bottom list with the feature layer sources - setAdapter(adapter) - // click listener when feature layer source is selected - setOnItemClickListener { _, _, i, _ -> - // get the selected feature layer source - val selectedSource = FeatureLayerSource.entries.find { it.menuPosition == i } - // check if the same feature is selected - if (previousSource != null && (previousSource == selectedSource)) { - // same feature layer selected, return - return@setOnItemClickListener - } - lifecycleScope.launch { - // set the feature layer source using the selected source - when (selectedSource) { - FeatureLayerSource.SERVICE_FEATURE_TABLE -> loadFeatureServiceURL() - FeatureLayerSource.PORTAL_ITEM -> loadPortalItem() - FeatureLayerSource.GEODATABASE -> loadGeodatabase() - FeatureLayerSource.GEOPACKAGE -> loadGeopackage() - FeatureLayerSource.SHAPEFILE -> loadShapefile() - else -> {} - } - } - // update the previous feature layer source - previousSource = selectedSource - } - } - } -} diff --git a/add-feature-layers/src/main/res/drawable-v24/ic_launcher_foreground.xml b/add-feature-layers/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/add-feature-layers/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/add-feature-layers/src/main/res/drawable/ic_launcher_background.xml b/add-feature-layers/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/add-feature-layers/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/add-feature-layers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/add-feature-layers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-feature-layers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-feature-layers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/add-feature-layers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-feature-layers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-feature-layers/src/main/res/mipmap-hdpi/ic_launcher.png b/add-feature-layers/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-hdpi/ic_launcher_round.png b/add-feature-layers/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-mdpi/ic_launcher.png b/add-feature-layers/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-mdpi/ic_launcher_round.png b/add-feature-layers/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-xhdpi/ic_launcher.png b/add-feature-layers/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/add-feature-layers/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-xxhdpi/ic_launcher.png b/add-feature-layers/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/add-feature-layers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/add-feature-layers/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/add-feature-layers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/add-feature-layers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-feature-layers/src/main/res/values/strings.xml b/add-feature-layers/src/main/res/values/strings.xml deleted file mode 100644 index 99c78d215..000000000 --- a/add-feature-layers/src/main/res/values/strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - Add feature layers - Select a feature layer source - https://sampleserver6.arcgisonline.com/arcgis/rest/services/NapervilleShelters/FeatureServer/0 - /LA_Trails.geodatabase - - Service Feature Table - Portal Item - Geodatabase - Geopackage - Shapefile - - diff --git a/add-features-with-contingent-values/.gitignore b/add-features-with-contingent-values/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/add-features-with-contingent-values/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/add-features-with-contingent-values/build.gradle.kts b/add-features-with-contingent-values/build.gradle.kts deleted file mode 100644 index 246aaa3dc..000000000 --- a/add-features-with-contingent-values/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.addfeatureswithcontingentvalues" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.addfeatureswithcontingentvalues" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(libs.androidx.appcompat) - implementation(project(":samples-lib")) -} diff --git a/add-features-with-contingent-values/proguard-rules.pro b/add-features-with-contingent-values/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/add-features-with-contingent-values/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/add-features-with-contingent-values/src/main/AndroidManifest.xml b/add-features-with-contingent-values/src/main/AndroidManifest.xml deleted file mode 100644 index c857c45c5..000000000 --- a/add-features-with-contingent-values/src/main/AndroidManifest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/add-features-with-contingent-values/src/main/java/com/esri/arcgismaps/sample/addfeatureswithcontingentvalues/DownloadActivity.kt b/add-features-with-contingent-values/src/main/java/com/esri/arcgismaps/sample/addfeatureswithcontingentvalues/DownloadActivity.kt deleted file mode 100644 index 30fee2596..000000000 --- a/add-features-with-contingent-values/src/main/java/com/esri/arcgismaps/sample/addfeatureswithcontingentvalues/DownloadActivity.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.esri.arcgismaps.sample.addfeatureswithcontingentvalues - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // Geodatabase containing bird nests defined with contingent values - "https://www.arcgis.com/home/item.html?id=e12b54ea799f4606a2712157cf9f6e41", - // Vector tile package of the Fillmore area - "https://www.arcgis.com/home/item.html?id=b5106355f1634b8996e634c04b6a930a" - ) - ) - } -} diff --git a/add-features-with-contingent-values/src/main/java/com/esri/arcgismaps/sample/addfeatureswithcontingentvalues/MainActivity.kt b/add-features-with-contingent-values/src/main/java/com/esri/arcgismaps/sample/addfeatureswithcontingentvalues/MainActivity.kt deleted file mode 100644 index 1302830a3..000000000 --- a/add-features-with-contingent-values/src/main/java/com/esri/arcgismaps/sample/addfeatureswithcontingentvalues/MainActivity.kt +++ /dev/null @@ -1,465 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.addfeatureswithcontingentvalues - -import android.os.Bundle -import android.util.Log -import android.view.ViewGroup -import android.widget.ArrayAdapter -import android.widget.AutoCompleteTextView -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.data.ArcGISFeature -import com.arcgismaps.data.ArcGISFeatureTable -import com.arcgismaps.data.CodedValue -import com.arcgismaps.data.CodedValueDomain -import com.arcgismaps.data.ContingentCodedValue -import com.arcgismaps.data.ContingentRangeValue -import com.arcgismaps.data.Feature -import com.arcgismaps.data.Geodatabase -import com.arcgismaps.data.QueryParameters -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.Basemap -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.layers.ArcGISVectorTiledLayer -import com.arcgismaps.mapping.layers.FeatureLayer -import com.arcgismaps.mapping.symbology.SimpleFillSymbol -import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol -import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.esri.arcgismaps.sample.addfeatureswithcontingentvalues.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.addfeatureswithcontingentvalues.databinding.AddFeatureLayoutBinding -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val bottomSheetBinding by lazy { - AddFeatureLayoutBinding.inflate(layoutInflater) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - // mobile database containing offline feature data. geodatabase is closed on app exit - private val geodatabase: Geodatabase by lazy { - Geodatabase("${cacheDir.path}/ContingentValuesBirdNests.geodatabase") - } - - // graphic overlay instance to add the feature graphic to the map - private val graphicsOverlay = GraphicsOverlay() - - // instance of the contingent feature to be added to the map - private var feature: ArcGISFeature? = null - - // instance of the feature table retrieved from the geodatabase, updates when new feature is added - private var featureTable: ArcGISFeatureTable? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // use the offline vector tiled layer as a basemap - val fillmoreVectorTiledLayer = ArcGISVectorTiledLayer( - "$provisionPath/FillmoreTopographicMap.vtpk" - ) - - mapView.apply { - // set the basemap layer and the graphic overlay to the MapView - map = ArcGISMap(Basemap(fillmoreVectorTiledLayer)) - graphicsOverlays.add(graphicsOverlay) - } - - // add a listener to the MapView to detect when - // a user has performed a single tap to add a new feature - lifecycleScope.launch { - mapView.onSingleTapConfirmed.collect { - // open a bottom sheet view to add the feature - it.mapPoint?.let { mapPoint -> createBottomSheet(mapPoint) } - } - } - - // create a temporary directory to use the geodatabase file - createGeodatabaseCacheDirectory() - - lifecycleScope.launch { - // retrieve and load the offline mobile geodatabase file from the cache directory - geodatabase.load().getOrElse { - showError("Error loading GeoDatabase: ${it.message}") - } - - // get the first geodatabase feature table - val featureTable = geodatabase.featureTables.firstOrNull() - ?: return@launch showError("No feature table found in geodatabase") - // load the geodatabase feature table - featureTable.load().getOrElse { - return@launch showError(it.message.toString()) - } - - // create and load the feature layer from the feature table - val featureLayer = FeatureLayer.createWithFeatureTable(featureTable) - // add the feature layer to the map - mapView.map?.operationalLayers?.add(featureLayer) - - // set the map's viewpoint to the feature layer's full extent - val extent = featureLayer.fullExtent - ?: return@launch showError("Error retrieving extent of the feature layer") - mapView.setViewpoint(Viewpoint(extent)) - - // keep the instance of the featureTable - this@MainActivity.featureTable = featureTable - - // add buffer graphics for the feature layer - queryFeatures() - } - } - - /** - * Geodatabase creates and uses various temporary files while processing a database, - * which will need to be cleared before looking up the [geodatabase] again. - * A copy of the original geodatabase file is created in the cache folder. - */ - private fun createGeodatabaseCacheDirectory() { - // clear cache directory - File(cacheDir.path).deleteRecursively() - // copy over the original Geodatabase file to be used in the temp cache directory - File("$provisionPath/ContingentValuesBirdNests.geodatabase").copyTo( - File("${cacheDir.path}/ContingentValuesBirdNests.geodatabase") - ) - } - - /** - * Create buffer graphics for the features and adds the graphics to - * the [graphicsOverlay] - */ - private suspend fun queryFeatures() { - // clear the existing graphics - graphicsOverlay.graphics.clear() - - // create buffer graphics for the features - val queryParameters = QueryParameters().apply { - // set the where clause to filter for buffer sizes greater than 0 - whereClause = "BufferSize > 0" - } - - // query the features using the queryParameters on the featureTable - val featureQueryResult = featureTable?.queryFeatures(queryParameters)?.getOrThrow() - // call get on the future to get the result - val featureResultList = featureQueryResult?.toList() - - if (!featureResultList.isNullOrEmpty()) { - // create list of graphics for each query result - val graphics = featureResultList.map { createGraphic(it) } - // add the graphics to the graphics overlay - graphicsOverlay.graphics.addAll(graphics) - } else { - showError("No features found with BufferSize > 0") - } - } - - /** - * Create a graphic for the given [feature] and returns a Graphic with the features attributes - */ - private fun createGraphic(feature: Feature): Graphic { - // get the feature's buffer size - val bufferSize = feature.attributes["BufferSize"] as Int - // get a polygon using the feature's buffer size and geometry - val polygon = feature.geometry?.let { GeometryEngine.bufferOrNull(it, bufferSize.toDouble()) } - // create the outline for the buffers - val lineSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.black, 2f) - // create the buffer symbol - val bufferSymbol = SimpleFillSymbol( - SimpleFillSymbolStyle.ForwardDiagonal, Color.red, lineSymbol - ) - // create an graphic using the geometry and fill symbol - return Graphic(polygon, bufferSymbol) - } - - /** - * Creates a BottomSheetDialog view to handle contingent value interaction. - * Once the contingent values have been set and the apply button is clicked, - * the function will call validateContingency() to add the feature at the [mapPoint]. - */ - private fun createBottomSheet(mapPoint: Point) { - // creates a new BottomSheetDialog - val bottomSheet = BottomSheetDialog(this).apply { - behavior.state = BottomSheetBehavior.STATE_EXPANDED - } - - // set up the first content value attribute - setUpStatusAttributes() - - // clear and set bottom sheet content view to layout, - // to be able to set the content view on each bottom sheet draw - if (bottomSheetBinding.root.parent != null) { - (bottomSheetBinding.root.parent as ViewGroup).removeAllViews() - } - - // reset feature to null since this is a new feature - feature = null - - bottomSheetBinding.apply { - - // reset bottom sheet values, this is needed to showcase contingent values behavior - statusInputLayout.editText?.setText("") - protectionInputLayout.editText?.setText("") - selectedBuffer.text = "" - protectionInputLayout.isEnabled = false - bufferSeekBar.isEnabled = false - bufferSeekBar.value = bufferSeekBar.valueFrom - - // set apply button to validate and apply contingency feature on map - applyTv.setOnClickListener { - // check if the contingent features set is valid and set it to the map if valid - validateContingency(mapPoint) - bottomSheet.dismiss() - } - - // dismiss on cancel clicked - cancelTv.setOnClickListener { bottomSheet.dismiss() } - } - - // set the content view to the root of the binding layout - bottomSheet.setContentView(bottomSheetBinding.root) - // display the bottom sheet view - bottomSheet.show() - } - - /** - * Retrieve the status fields, add the fields to a ContingentValueDomain, and set the values to the spinner - * When status attribute selected, createFeature() is called. - */ - private fun setUpStatusAttributes() { - // get the first field by name - val statusField = featureTable?.fields?.find { field -> field.name == "Status" } - // get the field's domains as coded value domain - val codedValueDomain = statusField?.domain as CodedValueDomain - // get the coded value domain's coded values - val statusCodedValues = codedValueDomain.codedValues - // get the selected index if applicable - val statusNames = statusCodedValues.map { it.name } - // get the items to be added to the spinner adapter - val adapter = ArrayAdapter(bottomSheetBinding.root.context, R.layout.list_item, statusNames) - (bottomSheetBinding.statusInputLayout.editText as AutoCompleteTextView).apply { - setAdapter(adapter) - setOnItemClickListener { _, _, position, _ -> - // get the CodedValue of the item selected, and create a feature needed for feature attributes - createFeature(statusCodedValues[position]) - } - } - } - - /** - * Set up the [feature] using the status attribute's coded value - * by loading the [featureTable]'s Contingent Value Definition. - * This function calls setUpProtectionAttributes() once the [feature] has been set - */ - private fun createFeature(codedValue: CodedValue) { - // get the contingent values definition from the feature table - val contingentValueDefinition = featureTable?.contingentValuesDefinition - if (contingentValueDefinition != null) { - lifecycleScope.launch { - // load the contingent values definition - contingentValueDefinition.load().getOrElse { - showError("Error loading the ContingentValuesDefinition") - } - // create a feature from the feature table and set the initial attribute - feature = featureTable?.createFeature() as ArcGISFeature - feature?.attributes?.set("Status", codedValue.code) - setUpProtectionAttributes() - } - } else { - showError("Error retrieving ContingentValuesDefinition from the FeatureTable") - } - } - - /** - * Retrieve the protection attribute fields, add the fields to a ContingentCodedValue, and set the values to the spinner - * When status attribute selected, showBufferSeekbar() is called. - */ - private fun setUpProtectionAttributes() { - // set the bottom sheet view to enable the Protection attribute, and disable input elsewhere - bottomSheetBinding.apply { - protectionInputLayout.isEnabled = true - bufferSeekBar.isEnabled = false - bufferSeekBar.value = bufferSeekBar.valueFrom - protectionInputLayout.editText?.setText("") - selectedBuffer.text = "" - } - - // get the contingent value results with the feature for the protection field - val contingentValuesResult = feature?.let { - featureTable?.getContingentValuesOrNull(it, "Protection") - } - - // get the list of contingent values by field group - val contingentValues = contingentValuesResult?.byFieldGroup?.get("ProtectionFieldGroup") - - // convert the list of ContingentValues to a list of CodedValue - val protectionCodedValues = - contingentValues?.map { (it as ContingentCodedValue).codedValue } - ?: return showError("Error getting coded values by field group") - - // get the attribute names for each coded value - val protectionNames = protectionCodedValues.map { it.name } - - // set the items to be added to the spinner adapter - val adapter = ArrayAdapter( - bottomSheetBinding.root.context, R.layout.list_item, protectionNames - ) - - // set the choices of protection attribute values - (bottomSheetBinding.protectionInputLayout.editText as AutoCompleteTextView).apply { - setAdapter(adapter) - setOnItemClickListener { _, _, position, _ -> - // set the protection CodedValue of the item selected - feature?.attributes?.set("Protection", protectionCodedValues[position].code) - // enable buffer seekbar - showBufferSeekbar() - } - } - } - - /** - * Retrieve the buffer attribute fields, add the fields - * to a ContingentRangeValue, and set the values to a SeekBar - */ - private fun showBufferSeekbar() { - // set the bottom sheet view to enable the buffer attribute - bottomSheetBinding.apply { - bufferSeekBar.isEnabled = true - selectedBuffer.text = "" - } - - // get the contingent value results using the feature and field - val contingentValueResult = feature?.let { - featureTable?.getContingentValuesOrNull(it, "BufferSize") - } - - // get the contingent rang value of the buffer size field group - val bufferSizeRangeValue = contingentValueResult?.byFieldGroup?.get("BufferSizeFieldGroup") - ?.get(0) as ContingentRangeValue - - // set the minimum and maximum possible buffer sizes - val minValue = bufferSizeRangeValue.minValue as Int - val maxValue = bufferSizeRangeValue.maxValue as Int - - // check if there can be a max value, if not disable SeekBar - // & set value to attribute size to 0 - if (maxValue > 0) { - // get SeekBar instance from the binding layout - bottomSheetBinding.bufferSeekBar.apply { - // set the min, max and current value of the SeekBar - valueFrom = minValue.toFloat() - valueTo = maxValue.toFloat() - value = valueFrom - // set the initial attribute and the text to the min of the ContingentRangeValue - feature?.attributes?.set("BufferSize", value.toInt()) - bottomSheetBinding.selectedBuffer.text = value.toInt().toString() - // set the change listener to update the attribute value and the displayed value to the SeekBar position - addOnChangeListener { _, value, _ -> - feature?.attributes?.set("BufferSize", value.toInt()) - bottomSheetBinding.selectedBuffer.text = value.toInt().toString() - } - } - } else { - // max value is 0, so disable seekbar and update the attribute value accordingly - bottomSheetBinding.apply { - bufferSeekBar.isEnabled = false - selectedBuffer.text = "0" - } - feature?.attributes?.set("BufferSize", 0) - } - } - - /** - * Ensure that the selected values are a valid combination. - * If contingencies are valid, then display [feature] on the [mapPoint] - */ - private fun validateContingency(mapPoint: Point) { - // check if all the features have been set - if (featureTable == null) { - showError("Input all values to add a feature to the map") - return - } - - // validate the feature's contingencies - val contingencyViolations = feature?.let { - featureTable?.validateContingencyConstraints(it) - } ?: return showError("No feature attribute was selected") - - // if there are no contingency violations - if (contingencyViolations.isEmpty()) { - // the feature is valid and ready to add to the feature table - // create a symbol to represent a bird's nest - val symbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.black, 11F) - // add the graphic to the graphics overlay - graphicsOverlay.graphics.add(Graphic(mapPoint, symbol)) - - // set the geometry of the feature to the map point - feature?.geometry = mapPoint - - // create the graphic of the feature - val graphic = feature?.let { createGraphic(it) } - // add the graphic to the graphics overlay - graphic?.let { graphicsOverlay.graphics.add(it) } - - // add the feature to the feature table - lifecycleScope.launch { - feature?.let { featureTable?.addFeature(it) } - feature?.load()?.getOrElse { - return@launch showError(it.message.toString()) - } - } - } else { - showError("Invalid contingent values: " + (contingencyViolations.size) + " violations found.") - } - - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/add-features-with-contingent-values/src/main/res/drawable-v24/ic_launcher_foreground.xml b/add-features-with-contingent-values/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/add-features-with-contingent-values/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/add-features-with-contingent-values/src/main/res/drawable/ic_launcher_background.xml b/add-features-with-contingent-values/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/add-features-with-contingent-values/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/add-features-with-contingent-values/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/add-features-with-contingent-values/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-features-with-contingent-values/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-features-with-contingent-values/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/add-features-with-contingent-values/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-features-with-contingent-values/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-features-with-contingent-values/src/main/res/mipmap-hdpi/ic_launcher.png b/add-features-with-contingent-values/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-hdpi/ic_launcher_round.png b/add-features-with-contingent-values/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-mdpi/ic_launcher.png b/add-features-with-contingent-values/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-mdpi/ic_launcher_round.png b/add-features-with-contingent-values/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-xhdpi/ic_launcher.png b/add-features-with-contingent-values/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/add-features-with-contingent-values/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-xxhdpi/ic_launcher.png b/add-features-with-contingent-values/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/add-features-with-contingent-values/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/add-features-with-contingent-values/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/add-features-with-contingent-values/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/add-features-with-contingent-values/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-features-with-contingent-values/src/main/res/values/strings.xml b/add-features-with-contingent-values/src/main/res/values/strings.xml deleted file mode 100644 index cd7f448cd..000000000 --- a/add-features-with-contingent-values/src/main/res/values/strings.xml +++ /dev/null @@ -1,11 +0,0 @@ - - Add features with contingent values - The options will vary depending on which values are selected - Add Feature - Apply - Cancel - Set the attributes: - Select status attribute - Select protection attribute - Exclusion area buffer size - diff --git a/add-scene-layer-with-elevation/.gitignore b/add-scene-layer-with-elevation/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/add-scene-layer-with-elevation/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/add-scene-layer-with-elevation/build.gradle.kts b/add-scene-layer-with-elevation/build.gradle.kts deleted file mode 100644 index 577274a01..000000000 --- a/add-scene-layer-with-elevation/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.addscenelayerwithelevation" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.addscenelayerwithelevation" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/add-scene-layer-with-elevation/proguard-rules.pro b/add-scene-layer-with-elevation/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/add-scene-layer-with-elevation/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/add-scene-layer-with-elevation/src/main/AndroidManifest.xml b/add-scene-layer-with-elevation/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/add-scene-layer-with-elevation/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/add-scene-layer-with-elevation/src/main/java/com/esri/arcgismaps/sample/addscenelayerwithelevation/MainActivity.kt b/add-scene-layer-with-elevation/src/main/java/com/esri/arcgismaps/sample/addscenelayerwithelevation/MainActivity.kt deleted file mode 100644 index 8b4f559f0..000000000 --- a/add-scene-layer-with-elevation/src/main/java/com/esri/arcgismaps/sample/addscenelayerwithelevation/MainActivity.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.addscenelayerwithelevation - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.addscenelayerwithelevation.screens.MainScreen -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - SceneLayerWithElevationApp() - } - } - } - - @Composable - private fun SceneLayerWithElevationApp() { - Surface(color = MaterialTheme.colorScheme.background) { - MainScreen(sampleName = getString(R.string.app_name)) - } - } -} diff --git a/add-scene-layer-with-elevation/src/main/res/drawable-v24/ic_launcher_foreground.xml b/add-scene-layer-with-elevation/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/add-scene-layer-with-elevation/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/add-scene-layer-with-elevation/src/main/res/drawable/ic_launcher_background.xml b/add-scene-layer-with-elevation/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/add-scene-layer-with-elevation/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/add-scene-layer-with-elevation/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-scene-layer-with-elevation/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/add-scene-layer-with-elevation/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-scene-layer-with-elevation/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-hdpi/ic_launcher.png b/add-scene-layer-with-elevation/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-hdpi/ic_launcher_round.png b/add-scene-layer-with-elevation/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-mdpi/ic_launcher.png b/add-scene-layer-with-elevation/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-mdpi/ic_launcher_round.png b/add-scene-layer-with-elevation/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-xhdpi/ic_launcher.png b/add-scene-layer-with-elevation/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/add-scene-layer-with-elevation/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-xxhdpi/ic_launcher.png b/add-scene-layer-with-elevation/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/add-scene-layer-with-elevation/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/add-scene-layer-with-elevation/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/add-scene-layer-with-elevation/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/add-scene-layer-with-elevation/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-scene-layer-with-elevation/src/main/res/values/strings.xml b/add-scene-layer-with-elevation/src/main/res/values/strings.xml deleted file mode 100644 index 953ca2cbb..000000000 --- a/add-scene-layer-with-elevation/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Add scene layer with elevation - - https://tiles.arcgis.com/tiles/P3ePLMYs2RVChkJx/arcgis/rest/services/Buildings_Brest/SceneServer - diff --git a/add-web-tiled-layer/.gitignore b/add-web-tiled-layer/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/add-web-tiled-layer/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/add-web-tiled-layer/build.gradle.kts b/add-web-tiled-layer/build.gradle.kts deleted file mode 100644 index cf655622b..000000000 --- a/add-web-tiled-layer/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.addwebtiledlayer" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.addwebtiledlayer" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/add-web-tiled-layer/proguard-rules.pro b/add-web-tiled-layer/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/add-web-tiled-layer/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/add-web-tiled-layer/src/main/AndroidManifest.xml b/add-web-tiled-layer/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/add-web-tiled-layer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/add-web-tiled-layer/src/main/java/com/esri/arcgismaps/sample/addwebtiledlayer/MainActivity.kt b/add-web-tiled-layer/src/main/java/com/esri/arcgismaps/sample/addwebtiledlayer/MainActivity.kt deleted file mode 100644 index 4775c3335..000000000 --- a/add-web-tiled-layer/src/main/java/com/esri/arcgismaps/sample/addwebtiledlayer/MainActivity.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.addwebtiledlayer - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.Basemap -import com.arcgismaps.mapping.layers.WebTiledLayer -import com.esri.arcgismaps.sample.addwebtiledlayer.databinding.ActivityMainBinding - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - lifecycle.addObserver(mapView) - - // build the web tiled layer from ArcGIS Living Atlas of the World tile service url - val webTiledLayer = WebTiledLayer.create( - urlTemplate = getString(R.string.template_uri_living_atlas) - ).apply { - // set the attribution on the layer - attribution = getString(R.string.living_atlas_attribution) - } - - // use web tiled layer as Basemap - val map = ArcGISMap(Basemap(webTiledLayer)) - mapView.map = map - } -} diff --git a/add-web-tiled-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml b/add-web-tiled-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/add-web-tiled-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/add-web-tiled-layer/src/main/res/drawable/ic_launcher_background.xml b/add-web-tiled-layer/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/add-web-tiled-layer/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/add-web-tiled-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/add-web-tiled-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-web-tiled-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-web-tiled-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/add-web-tiled-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-web-tiled-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-web-tiled-layer/src/main/res/mipmap-hdpi/ic_launcher.png b/add-web-tiled-layer/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png b/add-web-tiled-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-mdpi/ic_launcher.png b/add-web-tiled-layer/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png b/add-web-tiled-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-xhdpi/ic_launcher.png b/add-web-tiled-layer/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/add-web-tiled-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png b/add-web-tiled-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/add-web-tiled-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/add-web-tiled-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/add-web-tiled-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/add-web-tiled-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-web-tiled-layer/src/main/res/values/strings.xml b/add-web-tiled-layer/src/main/res/values/strings.xml deleted file mode 100644 index 5fa9c7d7e..000000000 --- a/add-web-tiled-layer/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Add web tiled layer - https://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer/tile/{level}/{row}/{col}.jpg - Map tiles by ArcGIS Living Atlas of the World, under Esri Master License Agreement. Data by Esri, Garmin, GEBCO, NOAA NGDC, and other contributors. - diff --git a/add-wms-layer/.gitignore b/add-wms-layer/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/add-wms-layer/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/add-wms-layer/build.gradle.kts b/add-wms-layer/build.gradle.kts deleted file mode 100644 index 313bc605c..000000000 --- a/add-wms-layer/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.addwmslayer" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.addwmslayer" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/add-wms-layer/proguard-rules.pro b/add-wms-layer/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/add-wms-layer/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/add-wms-layer/src/main/AndroidManifest.xml b/add-wms-layer/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/add-wms-layer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/add-wms-layer/src/main/java/com/esri/arcgismaps/sample/addwmslayer/MainActivity.kt b/add-wms-layer/src/main/java/com/esri/arcgismaps/sample/addwmslayer/MainActivity.kt deleted file mode 100644 index cf8d65a5e..000000000 --- a/add-wms-layer/src/main/java/com/esri/arcgismaps/sample/addwmslayer/MainActivity.kt +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.addwmslayer - -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.layers.WmsLayer -import com.esri.arcgismaps.sample.addwmslayer.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // create and add a map with a light gray basemap style - val map = ArcGISMap(BasemapStyle.ArcGISLightGray) - - // apply mapView assignments - mapView.apply { - this.map = map - // set an initial viewpoint to a zoomed out view of North America - setViewpoint(Viewpoint(39.8, -98.6, 10e7)) - } - - lifecycleScope.launch { - // if the map load fails, show an error and return - map.load().onFailure { - return@launch showError("Error loading map") - } - // create a list representing names of layers to load from the WMS service - val wmsLayerNames = listOf("conus_base_reflectivity_mosaic") - // create a new WmsLayer with the WMS service url and the layers name list - val wmsLayer = WmsLayer(getString(R.string.wms_layer_url), wmsLayerNames) - // add the wmsLayer to the map as an operational layer - map.operationalLayers.add(wmsLayer) - // if loading the layer fails show an error - wmsLayer.load().onFailure { - showError("Error loading WmsLayer") - } - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/add-wms-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml b/add-wms-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/add-wms-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/add-wms-layer/src/main/res/drawable/ic_launcher_background.xml b/add-wms-layer/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/add-wms-layer/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/add-wms-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/add-wms-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-wms-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-wms-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/add-wms-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/add-wms-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/add-wms-layer/src/main/res/mipmap-hdpi/ic_launcher.png b/add-wms-layer/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png b/add-wms-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-mdpi/ic_launcher.png b/add-wms-layer/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png b/add-wms-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-xhdpi/ic_launcher.png b/add-wms-layer/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/add-wms-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png b/add-wms-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/add-wms-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/add-wms-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/add-wms-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/add-wms-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/add-wms-layer/src/main/res/values/strings.xml b/add-wms-layer/src/main/res/values/strings.xml deleted file mode 100644 index 7df5865df..000000000 --- a/add-wms-layer/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Add WMS layer - https://nowcoast.noaa.gov/geoserver/observations/weather_radar/wms - diff --git a/analyze-hotspots/.gitignore b/analyze-hotspots/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/analyze-hotspots/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/analyze-hotspots/build.gradle.kts b/analyze-hotspots/build.gradle.kts deleted file mode 100644 index 6d6aa87c8..000000000 --- a/analyze-hotspots/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.analyzehotspots" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.analyzehotspots" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/analyze-hotspots/proguard-rules.pro b/analyze-hotspots/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/analyze-hotspots/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/analyze-hotspots/src/main/AndroidManifest.xml b/analyze-hotspots/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/analyze-hotspots/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/analyze-hotspots/src/main/java/com/esri/arcgismaps/sample/analyzehotspots/MainActivity.kt b/analyze-hotspots/src/main/java/com/esri/arcgismaps/sample/analyzehotspots/MainActivity.kt deleted file mode 100644 index b976e78e6..000000000 --- a/analyze-hotspots/src/main/java/com/esri/arcgismaps/sample/analyzehotspots/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.analyzehotspots - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.analyzehotspots.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - AnalyzeHotspotsApp() - } - } - } - - @Composable - private fun AnalyzeHotspotsApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/analyze-hotspots/src/main/res/drawable-v24/ic_launcher_foreground.xml b/analyze-hotspots/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/analyze-hotspots/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/analyze-hotspots/src/main/res/drawable/ic_launcher_background.xml b/analyze-hotspots/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/analyze-hotspots/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/analyze-hotspots/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/analyze-hotspots/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/analyze-hotspots/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/analyze-hotspots/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/analyze-hotspots/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/analyze-hotspots/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/analyze-hotspots/src/main/res/mipmap-hdpi/ic_launcher.png b/analyze-hotspots/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-hdpi/ic_launcher_round.png b/analyze-hotspots/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-mdpi/ic_launcher.png b/analyze-hotspots/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-mdpi/ic_launcher_round.png b/analyze-hotspots/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-xhdpi/ic_launcher.png b/analyze-hotspots/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/analyze-hotspots/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-xxhdpi/ic_launcher.png b/analyze-hotspots/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/analyze-hotspots/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/analyze-hotspots/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/analyze-hotspots/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/analyze-hotspots/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-hotspots/src/main/res/values/strings.xml b/analyze-hotspots/src/main/res/values/strings.xml deleted file mode 100644 index 533d8bdab..000000000 --- a/analyze-hotspots/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Analyze hotspots - http://sampleserver6.arcgisonline.com/arcgis/rest/services/911CallsHotspot/GPServer/911%20Calls%20Hotspot - diff --git a/analyze-network-with-subnetwork-trace/.gitignore b/analyze-network-with-subnetwork-trace/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/analyze-network-with-subnetwork-trace/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/analyze-network-with-subnetwork-trace/build.gradle.kts b/analyze-network-with-subnetwork-trace/build.gradle.kts deleted file mode 100644 index 0b592241f..000000000 --- a/analyze-network-with-subnetwork-trace/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.analyzenetworkwithsubnetworktrace" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.analyzenetworkwithsubnetworktrace" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/analyze-network-with-subnetwork-trace/proguard-rules.pro b/analyze-network-with-subnetwork-trace/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/analyze-network-with-subnetwork-trace/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/analyze-network-with-subnetwork-trace/src/main/AndroidManifest.xml b/analyze-network-with-subnetwork-trace/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/analyze-network-with-subnetwork-trace/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/analyze-network-with-subnetwork-trace/src/main/java/com/esri/arcgismaps/sample/analyzenetworkwithsubnetworktrace/MainActivity.kt b/analyze-network-with-subnetwork-trace/src/main/java/com/esri/arcgismaps/sample/analyzenetworkwithsubnetworktrace/MainActivity.kt deleted file mode 100644 index f3e11443e..000000000 --- a/analyze-network-with-subnetwork-trace/src/main/java/com/esri/arcgismaps/sample/analyzenetworkwithsubnetworktrace/MainActivity.kt +++ /dev/null @@ -1,519 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.analyzenetworkwithsubnetworktrace - -import android.os.Bundle -import android.text.InputType -import android.util.Log -import android.view.View -import android.widget.AdapterView -import android.widget.ArrayAdapter -import android.widget.AutoCompleteTextView -import android.widget.CheckBox -import android.widget.RelativeLayout -import android.widget.TextView -import android.widget.ToggleButton -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Guid -import com.arcgismaps.LoadStatus -import com.arcgismaps.data.CodedValue -import com.arcgismaps.data.CodedValueDomain -import com.arcgismaps.httpcore.authentication.ArcGISAuthenticationChallengeHandler -import com.arcgismaps.httpcore.authentication.ArcGISAuthenticationChallengeResponse -import com.arcgismaps.httpcore.authentication.TokenCredential -import com.arcgismaps.utilitynetworks.UtilityAttributeComparisonOperator -import com.arcgismaps.utilitynetworks.UtilityCategoryComparison -import com.arcgismaps.utilitynetworks.UtilityElement -import com.arcgismaps.utilitynetworks.UtilityElementTraceResult -import com.arcgismaps.utilitynetworks.UtilityNetwork -import com.arcgismaps.utilitynetworks.UtilityNetworkAttribute -import com.arcgismaps.utilitynetworks.UtilityNetworkAttributeComparison -import com.arcgismaps.utilitynetworks.UtilityNetworkAttributeDataType -import com.arcgismaps.utilitynetworks.UtilityTier -import com.arcgismaps.utilitynetworks.UtilityTraceAndCondition -import com.arcgismaps.utilitynetworks.UtilityTraceConditionalExpression -import com.arcgismaps.utilitynetworks.UtilityTraceConfiguration -import com.arcgismaps.utilitynetworks.UtilityTraceOrCondition -import com.arcgismaps.utilitynetworks.UtilityTraceParameters -import com.arcgismaps.utilitynetworks.UtilityTraceType -import com.arcgismaps.utilitynetworks.UtilityTraversability -import com.esri.arcgismaps.sample.analyzenetworkwithsubnetworktrace.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.analyzenetworkwithsubnetworktrace.databinding.LoadingOptionsDialogBinding -import com.google.android.material.button.MaterialButton -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar -import com.google.android.material.textfield.TextInputEditText -import kotlinx.coroutines.launch -import kotlinx.coroutines.runBlocking - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val sourceDropdown: AutoCompleteTextView by lazy { - activityMainBinding.sourceDropdown - } - - private val operatorDropdown: AutoCompleteTextView by lazy { - activityMainBinding.operatorDropdown - } - - private val expressionTextView: TextView by lazy { - activityMainBinding.expressionTextView - } - - private val valuesDropdown: AutoCompleteTextView by lazy { - activityMainBinding.valuesDropdown - } - - private val valuesBackgroundView: RelativeLayout by lazy { - activityMainBinding.valuesBackgroundView - } - - private val valueBooleanButton: ToggleButton by lazy { - activityMainBinding.valueBooleanButton - } - - private val valuesEditText: TextInputEditText by lazy { - activityMainBinding.valuesEditText - } - - private val barriersCheckbox: CheckBox by lazy { - activityMainBinding.barriersCheckBox - } - - private val containersCheckbox: CheckBox by lazy { - activityMainBinding.containersCheckbox - } - - private val traceButton: MaterialButton by lazy { - activityMainBinding.traceButton - } - - private val utilityNetwork by lazy { - UtilityNetwork(getString(R.string.utility_network_url)) - } - - private var initialExpression: UtilityTraceConditionalExpression? = null - private var sourceTier: UtilityTier? = null - private var utilityTraceConfiguration: UtilityTraceConfiguration? = null - private var sourcesList: List? = null - private var operatorsList: Array? = null - private var startingLocation: UtilityElement? = null - private var codedValuesList: List? = null - private var sourcePosition: Int = 0 - private var operatorPosition: Int = 0 - private var valuePosition: Int = 0 - private var dialog: AlertDialog? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - ArcGISEnvironment.applicationContext = this - ArcGISEnvironment.authenticationManager.arcGISAuthenticationChallengeHandler = - getAuthenticationChallengeHandler() - - // create and display the loading dialog - showLoadingDialog(true) - - // load the utility network - lifecycleScope.launch { - utilityNetwork.load().getOrElse { - dialog?.dismiss() - traceButton.isEnabled = false - return@launch showError("Error loading utility network: ${it.message}") - } - - // create a list of utility network attributes whose system is not defined - sourcesList = - utilityNetwork.definition?.networkAttributes?.filter { !it.isSystemDefined } - - sourceDropdown.apply { - // add the list of sources to the drop down view - setAdapter(sourcesList?.let { utilityNetworkAttributes -> - ArrayAdapter( - applicationContext, - com.esri.arcgismaps.sample.sampleslib.R.layout.custom_dropdown_item, - utilityNetworkAttributes.map { it.name }) - }) - - // add an on item selected listener which calls on comparison source changed - onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> - sourcePosition = position - sourcesList?.get(position)?.let { onComparisonSourceChanged(it) } - } - } - - // create a list of utility attribute comparison operators - operatorsList = - UtilityAttributeComparisonOperator::class.sealedSubclasses.mapNotNull { it.objectInstance } - .toTypedArray() - - operatorDropdown.apply { - // add the list of sources to the drop down view - setAdapter(operatorsList?.let { utilityAttributeComparisonOperator -> - ArrayAdapter(applicationContext, - com.esri.arcgismaps.sample.sampleslib.R.layout.custom_dropdown_item, - utilityAttributeComparisonOperator.map { it::class.simpleName }) - }) - - // add an on item selected listener which calls on comparison source changed - onItemClickListener = AdapterView.OnItemClickListener { _, _, position, _ -> - operatorPosition = position - } - } - - // create a default starting location - val networkSource = utilityNetwork.definition?.getNetworkSource("Electric Distribution Device") - - val assetGroup = networkSource?.getAssetGroup("Circuit Breaker") - - val assetType = assetGroup?.getAssetType("Three Phase") - - val globalId = Guid("1CAF7740-0BF4-4113-8DB2-654E18800028") - - if (assetType == null) return@launch - - val terminal = assetType.terminalConfiguration?.terminals?.first { it.name == "Load" } - - // utility element to start the trace from - startingLocation = utilityNetwork.createElementOrNull(assetType, globalId, terminal) - - // get a default trace configuration from a tier to update the UI - val domainNetwork = utilityNetwork.definition?.getDomainNetwork( - "ElectricDistribution" - ) - - // set source utility tier from the utility domain network - sourceTier = domainNetwork?.getTier("Medium Voltage Radial")?.apply { - utilityTraceConfiguration = getDefaultTraceConfiguration() - } - - // set initial barrier condition - val defaultConditionalExpression = sourceTier.let { - utilityTraceConfiguration?.traversability?.barriers as UtilityTraceConditionalExpression - } - // set the text view - expressionTextView.text = expressionToString(defaultConditionalExpression) - // use the initial expression when resetting trace - initialExpression = defaultConditionalExpression - - showLoadingDialog(false) - } - } - - /** - * Returns a [ArcGISAuthenticationChallengeHandler] to access the utility network URL. - */ - private fun getAuthenticationChallengeHandler(): ArcGISAuthenticationChallengeHandler { - return ArcGISAuthenticationChallengeHandler { challenge -> - val result: Result = runBlocking { - TokenCredential.create(challenge.requestUrl, "viewer01", "I68VGU^nMurF", 0) - } - if (result.getOrNull() != null) { - val credential = result.getOrNull() - return@ArcGISAuthenticationChallengeHandler ArcGISAuthenticationChallengeResponse - .ContinueWithCredential(credential!!) - } else { - val ex = result.exceptionOrNull() - return@ArcGISAuthenticationChallengeHandler ArcGISAuthenticationChallengeResponse - .ContinueAndFailWithError(ex!!) - } - } - } - - /** - * When a comparison source [attribute] is chosen check if it's a coded value domain and, if it is, - * present a dropdown of coded value domains. If not, show the correct UI view for the utility - * network attribute data type. - */ - private fun onComparisonSourceChanged(attribute: UtilityNetworkAttribute) { - // if the domain is a coded value domain - if (attribute.domain is CodedValueDomain) { - (attribute.domain as CodedValueDomain).let { codedValueDomain -> - // update the list of coded values - codedValuesList = codedValueDomain.codedValues - // show the values dropdown - setVisible(valuesBackgroundView.id) - // update the values dropdown adapter - valuesDropdown.setAdapter(ArrayAdapter(applicationContext, - com.esri.arcgismaps.sample.sampleslib.R.layout.custom_dropdown_item, - // add the coded values from the coded value domain to the values dropdown - codedValueDomain.codedValues.map { it.name })) - // add an on item selected listener which calls on comparison source changed - valuesDropdown.onItemClickListener = - AdapterView.OnItemClickListener { _, _, position, _ -> - valuePosition = position - } - } - } // if the domain is not a coded value domain - else { - when (attribute.dataType) { - UtilityNetworkAttributeDataType.Boolean -> { - // show true/false toggle button - setVisible(valueBooleanButton.id) - } - UtilityNetworkAttributeDataType.Double, UtilityNetworkAttributeDataType.Float -> { - // show the edit text and only allow numbers (decimals allowed) - valuesEditText.inputType = - InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_DECIMAL - setVisible(valuesEditText.id) - } - UtilityNetworkAttributeDataType.Integer -> { - // show the edit text only allowing for integer input - valuesEditText.inputType = InputType.TYPE_CLASS_NUMBER - setVisible(valuesEditText.id) - } - else -> { - showError("Unexpected utility network attribute data type.") - } - } - } - } - - /** - * Add a new barrier condition to the trace options when [addConditionButton] is tapped. - */ - fun addBarrierCondition(addConditionButton: View) { - // if source tier doesn't contain a trace configuration, create one - val traceConfiguration = utilityTraceConfiguration ?: UtilityTraceConfiguration().apply { - // if the trace configuration doesn't contain traversability, create one - traversability ?: UtilityTraversability() - } - - // get the currently selected attribute - sourcesList?.get(sourcePosition)?.let { sourceAttribute -> - // if the other value is a coded value domain - val otherValue = if (sourceAttribute.domain is CodedValueDomain) { - codedValuesList?.get(valuePosition)?.code?.let { - convertToDataType(it, sourceAttribute.dataType) - } - } else { - convertToDataType(valuesEditText.text.toString(), sourceAttribute.dataType) - } - - if (otherValue.toString().contains("Error") || otherValue == null) { - return showError(otherValue.toString()) - } - - // get the currently selected attribute operator> - operatorsList?.get(operatorPosition)?.let { comparisonOperator -> - // NOTE: You may also create a UtilityNetworkAttributeComparison - // with another NetworkAttribute - var expression: UtilityTraceConditionalExpression = - UtilityNetworkAttributeComparison( - sourceAttribute, - comparisonOperator, - otherValue - ) - (traceConfiguration.traversability?.barriers as? UtilityTraceConditionalExpression)?.let { otherExpression -> - // NOTE: You may also combine expressions with UtilityTraceAndCondition - expression = UtilityTraceOrCondition(otherExpression, expression) - } - traceConfiguration.traversability?.barriers = expression - expressionTextView.text = expressionToString(expression) - } - } - } - - /** - * Show the UI of the given [id] and hide the others which share the same space. - */ - private fun setVisible(id: Int) { - when (id) { - valuesBackgroundView.id -> { - valuesBackgroundView.visibility = View.VISIBLE - valueBooleanButton.visibility = View.GONE - valuesEditText.visibility = View.GONE - } - valuesEditText.id -> { - valuesEditText.visibility = View.VISIBLE - valueBooleanButton.visibility = View.GONE - valuesBackgroundView.visibility = View.GONE - } - valueBooleanButton.id -> { - valueBooleanButton.visibility = View.VISIBLE - valuesBackgroundView.visibility = View.GONE - valuesEditText.visibility = View.GONE - } - } - } - - /** - * Run the network trace with the parameters and display the result in an alert dialog - * when the [traceButton] is clicked. - */ - fun trace(traceButton: View) { - if (utilityNetwork.loadStatus.value != LoadStatus.Loaded) { - return showError("Utility network is not loaded") - } - - // set the utility trace parameters - val parameters = UtilityTraceParameters( - UtilityTraceType.Subnetwork, - listOf(startingLocation).requireNoNulls() - ).apply { - // set the utility trace configuration options to include - traceConfiguration = utilityTraceConfiguration?.apply { - includeBarriers = barriersCheckbox.isChecked - includeContainers = containersCheckbox.isChecked - } - } - - // launch trace in a coroutine scope - lifecycleScope.launch { - showLoadingDialog(true) - val utilityTraceResults = utilityNetwork.trace(parameters).getOrElse { - return@launch showError(it.message + getString(R.string.example_condition)) - } - // get the UtilityElementTraceResult - val elementTraceResult = utilityTraceResults.first() as UtilityElementTraceResult - - showLoadingDialog(false) - MaterialAlertDialogBuilder(this@MainActivity).apply { - // set the result dialog title - setTitle("Trace result") - // show the element result count - setMessage(elementTraceResult.elements.count().toString() + " elements found.") - }.show() - } - } - - /** - * Convert the given [expression] into a string. - */ - private fun expressionToString(expression: UtilityTraceConditionalExpression): String? { - when (expression) { - // when the expression is a category comparison expression - is UtilityCategoryComparison -> { - return expression.category.name + " " + expression.comparisonOperator - } - // when the expression is an utility trace AND condition - is UtilityTraceAndCondition -> { - return expressionToString(expression.leftExpression) + " AND\n" + expressionToString( - expression.rightExpression - ) - } - // when the expression is an utility trace OR condition - is UtilityTraceOrCondition -> { - return expressionToString(expression.leftExpression) + " OR\n" + expressionToString( - expression.rightExpression - ) - } - // when the expression is an attribute comparison expression - is UtilityNetworkAttributeComparison -> { - // the name and comparison operator of the expression - val networkAttributeNameAndOperator = expression.networkAttribute.name + " " + - expression.comparisonOperator::class.simpleName + " " - - // check whether the network attribute has a coded value domain - val codedValueDomain = expression.networkAttribute.domain as? CodedValueDomain - return if (codedValueDomain != null) { - networkAttributeNameAndOperator + - getCodedValueFromExpression(codedValueDomain, expression)?.name - } else { - // if there's no coded value domain - networkAttributeNameAndOperator + - (expression.otherNetworkAttribute?.name ?: expression.value) - } - } - else -> { - return null - } - } - } - - /** - * Convert the given value into the correct Kotlin data type by using the attribute's data type. - * - * @param otherValue which will be converted - * @param dataType to be converted to - */ - private fun convertToDataType( - otherValue: Any, - dataType: UtilityNetworkAttributeDataType, - ): Any { - return try { - when (dataType::class.objectInstance) { - UtilityNetworkAttributeDataType.Boolean -> otherValue.toString().toBoolean() - UtilityNetworkAttributeDataType.Double -> otherValue.toString().toDouble() - UtilityNetworkAttributeDataType.Float -> otherValue.toString().toFloat() - UtilityNetworkAttributeDataType.Integer -> otherValue.toString().toInt() - else -> {} - } - } catch (e: Exception) { - return ("Error converting value to a datatype") - } - } - - /** - * Returns a [CodedValue] found in the [expression] using the - * list of coded values in the [codedValueDomain]. - */ - private fun getCodedValueFromExpression( - codedValueDomain: CodedValueDomain, - expression: UtilityNetworkAttributeComparison, - ): CodedValue? { - // if there's a coded value domain name - return codedValueDomain.codedValues.first { codedValue -> - val code = codedValue.code - val value = expression.value - if (code != null && value != null) { - return@first (convertToDataType(code, - expression.networkAttribute.dataType) == convertToDataType(value, - expression.networkAttribute.dataType)) - } else - return null - } - } - - /** - * Reset the current barrier condition to the initial expression - * "Operational Device Status EQUAL Open" and resets the UI. - */ - fun reset(view: View) { - initialExpression?.let { - utilityTraceConfiguration = sourceTier?.getDefaultTraceConfiguration()?.apply { - traversability?.barriers = it - } - expressionTextView.text = expressionToString(it) - } - } - - private fun showLoadingDialog(isVisible: Boolean) { - if (isVisible) { - dialog = MaterialAlertDialogBuilder(this).apply { - setCancelable(false) - setView(LoadingOptionsDialogBinding.inflate(layoutInflater).root) - }.show() - } else { - dialog?.dismiss() - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(activityMainBinding.root, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/analyze-network-with-subnetwork-trace/src/main/res/drawable-v24/ic_launcher_foreground.xml b/analyze-network-with-subnetwork-trace/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/analyze-network-with-subnetwork-trace/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/analyze-network-with-subnetwork-trace/src/main/res/drawable/ic_launcher_background.xml b/analyze-network-with-subnetwork-trace/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/analyze-network-with-subnetwork-trace/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-hdpi/ic_launcher.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-hdpi/ic_launcher_round.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-mdpi/ic_launcher.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-mdpi/ic_launcher_round.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xhdpi/ic_launcher.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxhdpi/ic_launcher.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/analyze-network-with-subnetwork-trace/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/analyze-network-with-subnetwork-trace/src/main/res/values/strings.xml b/analyze-network-with-subnetwork-trace/src/main/res/values/strings.xml deleted file mode 100644 index 494f4ba3e..000000000 --- a/analyze-network-with-subnetwork-trace/src/main/res/values/strings.xml +++ /dev/null @@ -1,20 +0,0 @@ - - Analyze network with subnetwork trace - Trace options: - Include barriers - Include containers - Define new condition: - Example barrier condition for this data:\n\'Transformer Load\' EQUAL \'15\' - False - True - Add condition - Barrier conditions: - Trace - Reset - https://sampleserver7.arcgisonline.com/server/rest/services/UtilityNetwork/NapervilleElectric/FeatureServer - Select source - Select operator - Select value - Value - Loading subnetwork trace - diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 000000000..e196eb04d --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,91 @@ +import java.util.Properties + +plugins { + alias(libs.plugins.arcgismaps.android.application) + alias(libs.plugins.arcgismaps.android.application.compose) + alias(libs.plugins.arcgismaps.kotlin.sample) + alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.gradle.secrets) + alias(libs.plugins.sample.files.copy) + alias(libs.plugins.screenshots.copy) + alias(libs.plugins.ksp) +} + +tasks.named("preBuild").configure { dependsOn("copyCodeFiles") } +tasks.named("preBuild").configure { dependsOn("copyScreenshots") } + +secrets { + // this file doesn't contain secrets, it just provides defaults which can be committed into git. + defaultPropertiesFileName = "secrets.defaults.properties" +} + +android { + namespace = "com.esri.arcgismaps.kotlin.sampleviewer" + + defaultConfig { + applicationId = "com.esri.arcgismaps.kotlin.sampleviewer" + buildConfigField("String", "ARCGIS_VERSION", "\"${rootProject.extra.get("arcgisMapsKotlinVersion")}\"") + } + + // Optional input to apply the external signing configuration for the sample viewer + // Example: ./gradlew assembleRelease -PsigningPropsFilePath=absolute-file-path/signing.properties -D build=200.6.0 + val signingPropsFilePath = project.findProperty("signingPropsFilePath").toString() + val signingPropsFile = rootProject.file(signingPropsFilePath) + + signingConfigs { + create("esriSignature") { + // Check for signing.properties from the external file and apply the properties if present + if (signingPropsFile.exists()) { + val signingProps = Properties().apply { + load(signingPropsFile.inputStream()) + } + keyAlias = signingProps["keyAlias"] as String + keyPassword = signingProps["keyPassword"] as String + storeFile = file(signingProps["storeFilePath"] as String) + storePassword = signingProps["storePassword"] as String + } + } + } + + buildTypes { + release { + ndk { + abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86_64") + } + isMinifyEnabled = false + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + // If signing.properties file not found, gradle will build an unsigned APK. + // For release builds, provide the required "signingPropsFilePath" for a signed APK, using: + // ./gradlew assembleRelease -PsigningPropsFilePath=absolute-file-path/signing.properties + if (signingPropsFile.exists()) + signingConfig = signingConfigs.getByName("esriSignature") + } + } + + buildFeatures { + buildConfig = true + compose = true + dataBinding = true + } +} + +dependencies { + for (sampleFile in file("../samples").listFiles()!!) { + if (sampleFile.isDirectory) { + implementation(project(":samples:" + sampleFile.name)) + } + } + implementation(project(":samples-lib")) + implementation(libs.arcgis.maps.kotlin.toolkit.authentication) + implementation(libs.kotlinx.serialization.json) + implementation(libs.androidx.appcompat) + implementation(libs.accompanist.systemuicontroller) + implementation(libs.androidx.navigation.compose) + implementation(libs.androidx.datastore.preferences) + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.room.ktx) + implementation(libs.coil.compose) + implementation(libs.coil.network.http) + annotationProcessor(libs.androidx.room.compiler) + ksp(libs.androidx.room.compiler) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 000000000..481bb4348 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# 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 \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 000000000..a57feda0a --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/assets/www/highlight/LICENSE b/app/src/main/assets/www/highlight/LICENSE new file mode 100644 index 000000000..2250cc7ec --- /dev/null +++ b/app/src/main/assets/www/highlight/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2006, Ivan Sagalaev. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/app/src/main/assets/www/highlight/highlight.min.js b/app/src/main/assets/www/highlight/highlight.min.js new file mode 100644 index 000000000..bdbf1998c --- /dev/null +++ b/app/src/main/assets/www/highlight/highlight.min.js @@ -0,0 +1,385 @@ +/*! + Highlight.js v11.10.0 (git: 366a8bd012) + (c) 2006-2024 Josh Goebel and other contributors + License: BSD-3-Clause + */ +var hljs=function(){"use strict";function e(t){ +return t instanceof Map?t.clear=t.delete=t.set=()=>{ +throw Error("map is read-only")}:t instanceof Set&&(t.add=t.clear=t.delete=()=>{ +throw Error("set is read-only") +}),Object.freeze(t),Object.getOwnPropertyNames(t).forEach((n=>{ +const i=t[n],s=typeof i;"object"!==s&&"function"!==s||Object.isFrozen(i)||e(i) +})),t}class t{constructor(e){ +void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1} +ignoreMatch(){this.isMatchIgnored=!0}}function n(e){ +return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'") +}function i(e,...t){const n=Object.create(null);for(const t in e)n[t]=e[t] +;return t.forEach((e=>{for(const t in e)n[t]=e[t]})),n}const s=e=>!!e.scope +;class o{constructor(e,t){ +this.buffer="",this.classPrefix=t.classPrefix,e.walk(this)}addText(e){ +this.buffer+=n(e)}openNode(e){if(!s(e))return;const t=((e,{prefix:t})=>{ +if(e.startsWith("language:"))return e.replace("language:","language-") +;if(e.includes(".")){const n=e.split(".") +;return[`${t}${n.shift()}`,...n.map(((e,t)=>`${e}${"_".repeat(t+1)}`))].join(" ") +}return`${t}${e}`})(e.scope,{prefix:this.classPrefix});this.span(t)} +closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){ +this.buffer+=``}}const r=(e={})=>{const t={children:[]} +;return Object.assign(t,e),t};class a{constructor(){ +this.rootNode=r(),this.stack=[this.rootNode]}get top(){ +return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){ +this.top.children.push(e)}openNode(e){const t=r({scope:e}) +;this.add(t),this.stack.push(t)}closeNode(){ +if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){ +for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)} +walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,t){ +return"string"==typeof t?e.addText(t):t.children&&(e.openNode(t), +t.children.forEach((t=>this._walk(e,t))),e.closeNode(t)),e}static _collapse(e){ +"string"!=typeof e&&e.children&&(e.children.every((e=>"string"==typeof e))?e.children=[e.children.join("")]:e.children.forEach((e=>{ +a._collapse(e)})))}}class c extends a{constructor(e){super(),this.options=e} +addText(e){""!==e&&this.add(e)}startScope(e){this.openNode(e)}endScope(){ +this.closeNode()}__addSublanguage(e,t){const n=e.root +;t&&(n.scope="language:"+t),this.add(n)}toHTML(){ +return new o(this,this.options).value()}finalize(){ +return this.closeAllNodes(),!0}}function l(e){ +return e?"string"==typeof e?e:e.source:null}function g(e){return h("(?=",e,")")} +function u(e){return h("(?:",e,")*")}function d(e){return h("(?:",e,")?")} +function h(...e){return e.map((e=>l(e))).join("")}function f(...e){const t=(e=>{ +const t=e[e.length-1] +;return"object"==typeof t&&t.constructor===Object?(e.splice(e.length-1,1),t):{} +})(e);return"("+(t.capture?"":"?:")+e.map((e=>l(e))).join("|")+")"} +function p(e){return RegExp(e.toString()+"|").exec("").length-1} +const b=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./ +;function m(e,{joinWith:t}){let n=0;return e.map((e=>{n+=1;const t=n +;let i=l(e),s="";for(;i.length>0;){const e=b.exec(i);if(!e){s+=i;break} +s+=i.substring(0,e.index), +i=i.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?s+="\\"+(Number(e[1])+t):(s+=e[0], +"("===e[0]&&n++)}return s})).map((e=>`(${e})`)).join(t)} +const E="[a-zA-Z]\\w*",x="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",y="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",_="\\b(0b[01]+)",O={ +begin:"\\\\[\\s\\S]",relevance:0},v={scope:"string",begin:"'",end:"'", +illegal:"\\n",contains:[O]},k={scope:"string",begin:'"',end:'"',illegal:"\\n", +contains:[O]},N=(e,t,n={})=>{const s=i({scope:"comment",begin:e,end:t, +contains:[]},n);s.contains.push({scope:"doctag", +begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)", +end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0}) +;const o=f("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/) +;return s.contains.push({begin:h(/[ ]+/,"(",o,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),s +},S=N("//","$"),M=N("/\\*","\\*/"),R=N("#","$");var j=Object.freeze({ +__proto__:null,APOS_STRING_MODE:v,BACKSLASH_ESCAPE:O,BINARY_NUMBER_MODE:{ +scope:"number",begin:_,relevance:0},BINARY_NUMBER_RE:_,COMMENT:N, +C_BLOCK_COMMENT_MODE:M,C_LINE_COMMENT_MODE:S,C_NUMBER_MODE:{scope:"number", +begin:y,relevance:0},C_NUMBER_RE:y,END_SAME_AS_BEGIN:e=>Object.assign(e,{ +"on:begin":(e,t)=>{t.data._beginMatch=e[1]},"on:end":(e,t)=>{ +t.data._beginMatch!==e[1]&&t.ignoreMatch()}}),HASH_COMMENT_MODE:R,IDENT_RE:E, +MATCH_NOTHING_RE:/\b\B/,METHOD_GUARD:{begin:"\\.\\s*"+x,relevance:0}, +NUMBER_MODE:{scope:"number",begin:w,relevance:0},NUMBER_RE:w, +PHRASAL_WORDS_MODE:{ +begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/ +},QUOTE_STRING_MODE:k,REGEXP_MODE:{scope:"regexp",begin:/\/(?=[^/\n]*\/)/, +end:/\/[gimuy]*/,contains:[O,{begin:/\[/,end:/\]/,relevance:0,contains:[O]}]}, +RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~", +SHEBANG:(e={})=>{const t=/^#![ ]*\// +;return e.binary&&(e.begin=h(t,/.*\b/,e.binary,/\b.*/)),i({scope:"meta",begin:t, +end:/$/,relevance:0,"on:begin":(e,t)=>{0!==e.index&&t.ignoreMatch()}},e)}, +TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_IDENT_RE:x, +UNDERSCORE_TITLE_MODE:{scope:"title",begin:x,relevance:0}});function A(e,t){ +"."===e.input[e.index-1]&&t.ignoreMatch()}function I(e,t){ +void 0!==e.className&&(e.scope=e.className,delete e.className)}function T(e,t){ +t&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)", +e.__beforeBegin=A,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords, +void 0===e.relevance&&(e.relevance=0))}function L(e,t){ +Array.isArray(e.illegal)&&(e.illegal=f(...e.illegal))}function B(e,t){ +if(e.match){ +if(e.begin||e.end)throw Error("begin & end are not supported with match") +;e.begin=e.match,delete e.match}}function P(e,t){ +void 0===e.relevance&&(e.relevance=1)}const D=(e,t)=>{if(!e.beforeMatch)return +;if(e.starts)throw Error("beforeMatch cannot be used with starts") +;const n=Object.assign({},e);Object.keys(e).forEach((t=>{delete e[t] +})),e.keywords=n.keywords,e.begin=h(n.beforeMatch,g(n.begin)),e.starts={ +relevance:0,contains:[Object.assign(n,{endsParent:!0})] +},e.relevance=0,delete n.beforeMatch +},H=["of","and","for","in","not","or","if","then","parent","list","value"],C="keyword" +;function $(e,t,n=C){const i=Object.create(null) +;return"string"==typeof e?s(n,e.split(" ")):Array.isArray(e)?s(n,e):Object.keys(e).forEach((n=>{ +Object.assign(i,$(e[n],t,n))})),i;function s(e,n){ +t&&(n=n.map((e=>e.toLowerCase()))),n.forEach((t=>{const n=t.split("|") +;i[n[0]]=[e,U(n[0],n[1])]}))}}function U(e,t){ +return t?Number(t):(e=>H.includes(e.toLowerCase()))(e)?0:1}const z={},W=e=>{ +console.error(e)},X=(e,...t)=>{console.log("WARN: "+e,...t)},G=(e,t)=>{ +z[`${e}/${t}`]||(console.log(`Deprecated as of ${e}. ${t}`),z[`${e}/${t}`]=!0) +},K=Error();function F(e,t,{key:n}){let i=0;const s=e[n],o={},r={} +;for(let e=1;e<=t.length;e++)r[e+i]=s[e],o[e+i]=!0,i+=p(t[e-1]) +;e[n]=r,e[n]._emit=o,e[n]._multi=!0}function Z(e){(e=>{ +e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope, +delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={ +_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope +}),(e=>{if(Array.isArray(e.begin)){ +if(e.skip||e.excludeBegin||e.returnBegin)throw W("skip, excludeBegin, returnBegin not compatible with beginScope: {}"), +K +;if("object"!=typeof e.beginScope||null===e.beginScope)throw W("beginScope must be object"), +K;F(e,e.begin,{key:"beginScope"}),e.begin=m(e.begin,{joinWith:""})}})(e),(e=>{ +if(Array.isArray(e.end)){ +if(e.skip||e.excludeEnd||e.returnEnd)throw W("skip, excludeEnd, returnEnd not compatible with endScope: {}"), +K +;if("object"!=typeof e.endScope||null===e.endScope)throw W("endScope must be object"), +K;F(e,e.end,{key:"endScope"}),e.end=m(e.end,{joinWith:""})}})(e)}function V(e){ +function t(t,n){ +return RegExp(l(t),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(n?"g":"")) +}class n{constructor(){ +this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0} +addRule(e,t){ +t.position=this.position++,this.matchIndexes[this.matchAt]=t,this.regexes.push([t,e]), +this.matchAt+=p(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null) +;const e=this.regexes.map((e=>e[1]));this.matcherRe=t(m(e,{joinWith:"|" +}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex +;const t=this.matcherRe.exec(e);if(!t)return null +;const n=t.findIndex(((e,t)=>t>0&&void 0!==e)),i=this.matchIndexes[n] +;return t.splice(0,n),Object.assign(t,i)}}class s{constructor(){ +this.rules=[],this.multiRegexes=[], +this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){ +if(this.multiRegexes[e])return this.multiRegexes[e];const t=new n +;return this.rules.slice(e).forEach((([e,n])=>t.addRule(e,n))), +t.compile(),this.multiRegexes[e]=t,t}resumingScanAtSamePosition(){ +return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,t){ +this.rules.push([e,t]),"begin"===t.type&&this.count++}exec(e){ +const t=this.getMatcher(this.regexIndex);t.lastIndex=this.lastIndex +;let n=t.exec(e) +;if(this.resumingScanAtSamePosition())if(n&&n.index===this.lastIndex);else{ +const t=this.getMatcher(0);t.lastIndex=this.lastIndex+1,n=t.exec(e)} +return n&&(this.regexIndex+=n.position+1, +this.regexIndex===this.count&&this.considerAll()),n}} +if(e.compilerExtensions||(e.compilerExtensions=[]), +e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.") +;return e.classNameAliases=i(e.classNameAliases||{}),function n(o,r){const a=o +;if(o.isCompiled)return a +;[I,B,Z,D].forEach((e=>e(o,r))),e.compilerExtensions.forEach((e=>e(o,r))), +o.__beforeBegin=null,[T,L,P].forEach((e=>e(o,r))),o.isCompiled=!0;let c=null +;return"object"==typeof o.keywords&&o.keywords.$pattern&&(o.keywords=Object.assign({},o.keywords), +c=o.keywords.$pattern, +delete o.keywords.$pattern),c=c||/\w+/,o.keywords&&(o.keywords=$(o.keywords,e.case_insensitive)), +a.keywordPatternRe=t(c,!0), +r&&(o.begin||(o.begin=/\B|\b/),a.beginRe=t(a.begin),o.end||o.endsWithParent||(o.end=/\B|\b/), +o.end&&(a.endRe=t(a.end)), +a.terminatorEnd=l(a.end)||"",o.endsWithParent&&r.terminatorEnd&&(a.terminatorEnd+=(o.end?"|":"")+r.terminatorEnd)), +o.illegal&&(a.illegalRe=t(o.illegal)), +o.contains||(o.contains=[]),o.contains=[].concat(...o.contains.map((e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map((t=>i(e,{ +variants:null},t)))),e.cachedVariants?e.cachedVariants:q(e)?i(e,{ +starts:e.starts?i(e.starts):null +}):Object.isFrozen(e)?i(e):e))("self"===e?o:e)))),o.contains.forEach((e=>{n(e,a) +})),o.starts&&n(o.starts,r),a.matcher=(e=>{const t=new s +;return e.contains.forEach((e=>t.addRule(e.begin,{rule:e,type:"begin" +}))),e.terminatorEnd&&t.addRule(e.terminatorEnd,{type:"end" +}),e.illegal&&t.addRule(e.illegal,{type:"illegal"}),t})(a),a}(e)}function q(e){ +return!!e&&(e.endsWithParent||q(e.starts))}class J extends Error{ +constructor(e,t){super(e),this.name="HTMLInjectionError",this.html=t}} +const Y=n,Q=i,ee=Symbol("nomatch"),te=n=>{ +const i=Object.create(null),s=Object.create(null),o=[];let r=!0 +;const a="Could not find the language '{}', did you forget to load/include a language module?",l={ +disableAutodetect:!0,name:"Plain text",contains:[]};let p={ +ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i, +languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-", +cssSelector:"pre code",languages:null,__emitter:c};function b(e){ +return p.noHighlightRe.test(e)}function m(e,t,n){let i="",s="" +;"object"==typeof t?(i=e, +n=t.ignoreIllegals,s=t.language):(G("10.7.0","highlight(lang, code, ...args) has been deprecated."), +G("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"), +s=e,i=t),void 0===n&&(n=!0);const o={code:i,language:s};N("before:highlight",o) +;const r=o.result?o.result:E(o.language,o.code,n) +;return r.code=o.code,N("after:highlight",r),r}function E(e,n,s,o){ +const c=Object.create(null);function l(){if(!N.keywords)return void M.addText(R) +;let e=0;N.keywordPatternRe.lastIndex=0;let t=N.keywordPatternRe.exec(R),n="" +;for(;t;){n+=R.substring(e,t.index) +;const s=_.case_insensitive?t[0].toLowerCase():t[0],o=(i=s,N.keywords[i]);if(o){ +const[e,i]=o +;if(M.addText(n),n="",c[s]=(c[s]||0)+1,c[s]<=7&&(j+=i),e.startsWith("_"))n+=t[0];else{ +const n=_.classNameAliases[e]||e;u(t[0],n)}}else n+=t[0] +;e=N.keywordPatternRe.lastIndex,t=N.keywordPatternRe.exec(R)}var i +;n+=R.substring(e),M.addText(n)}function g(){null!=N.subLanguage?(()=>{ +if(""===R)return;let e=null;if("string"==typeof N.subLanguage){ +if(!i[N.subLanguage])return void M.addText(R) +;e=E(N.subLanguage,R,!0,S[N.subLanguage]),S[N.subLanguage]=e._top +}else e=x(R,N.subLanguage.length?N.subLanguage:null) +;N.relevance>0&&(j+=e.relevance),M.__addSublanguage(e._emitter,e.language) +})():l(),R=""}function u(e,t){ +""!==e&&(M.startScope(t),M.addText(e),M.endScope())}function d(e,t){let n=1 +;const i=t.length-1;for(;n<=i;){if(!e._emit[n]){n++;continue} +const i=_.classNameAliases[e[n]]||e[n],s=t[n];i?u(s,i):(R=s,l(),R=""),n++}} +function h(e,t){ +return e.scope&&"string"==typeof e.scope&&M.openNode(_.classNameAliases[e.scope]||e.scope), +e.beginScope&&(e.beginScope._wrap?(u(R,_.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap), +R=""):e.beginScope._multi&&(d(e.beginScope,t),R="")),N=Object.create(e,{parent:{ +value:N}}),N}function f(e,n,i){let s=((e,t)=>{const n=e&&e.exec(t) +;return n&&0===n.index})(e.endRe,i);if(s){if(e["on:end"]){const i=new t(e) +;e["on:end"](n,i),i.isMatchIgnored&&(s=!1)}if(s){ +for(;e.endsParent&&e.parent;)e=e.parent;return e}} +if(e.endsWithParent)return f(e.parent,n,i)}function b(e){ +return 0===N.matcher.regexIndex?(R+=e[0],1):(T=!0,0)}function m(e){ +const t=e[0],i=n.substring(e.index),s=f(N,e,i);if(!s)return ee;const o=N +;N.endScope&&N.endScope._wrap?(g(), +u(t,N.endScope._wrap)):N.endScope&&N.endScope._multi?(g(), +d(N.endScope,e)):o.skip?R+=t:(o.returnEnd||o.excludeEnd||(R+=t), +g(),o.excludeEnd&&(R=t));do{ +N.scope&&M.closeNode(),N.skip||N.subLanguage||(j+=N.relevance),N=N.parent +}while(N!==s.parent);return s.starts&&h(s.starts,e),o.returnEnd?0:t.length} +let w={};function y(i,o){const a=o&&o[0];if(R+=i,null==a)return g(),0 +;if("begin"===w.type&&"end"===o.type&&w.index===o.index&&""===a){ +if(R+=n.slice(o.index,o.index+1),!r){const t=Error(`0 width match regex (${e})`) +;throw t.languageName=e,t.badRule=w.rule,t}return 1} +if(w=o,"begin"===o.type)return(e=>{ +const n=e[0],i=e.rule,s=new t(i),o=[i.__beforeBegin,i["on:begin"]] +;for(const t of o)if(t&&(t(e,s),s.isMatchIgnored))return b(n) +;return i.skip?R+=n:(i.excludeBegin&&(R+=n), +g(),i.returnBegin||i.excludeBegin||(R=n)),h(i,e),i.returnBegin?0:n.length})(o) +;if("illegal"===o.type&&!s){ +const e=Error('Illegal lexeme "'+a+'" for mode "'+(N.scope||"")+'"') +;throw e.mode=N,e}if("end"===o.type){const e=m(o);if(e!==ee)return e} +if("illegal"===o.type&&""===a)return 1 +;if(I>1e5&&I>3*o.index)throw Error("potential infinite loop, way more iterations than matches") +;return R+=a,a.length}const _=O(e) +;if(!_)throw W(a.replace("{}",e)),Error('Unknown language: "'+e+'"') +;const v=V(_);let k="",N=o||v;const S={},M=new p.__emitter(p);(()=>{const e=[] +;for(let t=N;t!==_;t=t.parent)t.scope&&e.unshift(t.scope) +;e.forEach((e=>M.openNode(e)))})();let R="",j=0,A=0,I=0,T=!1;try{ +if(_.__emitTokens)_.__emitTokens(n,M);else{for(N.matcher.considerAll();;){ +I++,T?T=!1:N.matcher.considerAll(),N.matcher.lastIndex=A +;const e=N.matcher.exec(n);if(!e)break;const t=y(n.substring(A,e.index),e) +;A=e.index+t}y(n.substring(A))}return M.finalize(),k=M.toHTML(),{language:e, +value:k,relevance:j,illegal:!1,_emitter:M,_top:N}}catch(t){ +if(t.message&&t.message.includes("Illegal"))return{language:e,value:Y(n), +illegal:!0,relevance:0,_illegalBy:{message:t.message,index:A, +context:n.slice(A-100,A+100),mode:t.mode,resultSoFar:k},_emitter:M};if(r)return{ +language:e,value:Y(n),illegal:!1,relevance:0,errorRaised:t,_emitter:M,_top:N} +;throw t}}function x(e,t){t=t||p.languages||Object.keys(i);const n=(e=>{ +const t={value:Y(e),illegal:!1,relevance:0,_top:l,_emitter:new p.__emitter(p)} +;return t._emitter.addText(e),t})(e),s=t.filter(O).filter(k).map((t=>E(t,e,!1))) +;s.unshift(n);const o=s.sort(((e,t)=>{ +if(e.relevance!==t.relevance)return t.relevance-e.relevance +;if(e.language&&t.language){if(O(e.language).supersetOf===t.language)return 1 +;if(O(t.language).supersetOf===e.language)return-1}return 0})),[r,a]=o,c=r +;return c.secondBest=a,c}function w(e){let t=null;const n=(e=>{ +let t=e.className+" ";t+=e.parentNode?e.parentNode.className:"" +;const n=p.languageDetectRe.exec(t);if(n){const t=O(n[1]) +;return t||(X(a.replace("{}",n[1])), +X("Falling back to no-highlight mode for this block.",e)),t?n[1]:"no-highlight"} +return t.split(/\s+/).find((e=>b(e)||O(e)))})(e);if(b(n))return +;if(N("before:highlightElement",{el:e,language:n +}),e.dataset.highlighted)return void console.log("Element previously highlighted. To highlight again, first unset `dataset.highlighted`.",e) +;if(e.children.length>0&&(p.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."), +console.warn("https://github.com/highlightjs/highlight.js/wiki/security"), +console.warn("The element with unescaped HTML:"), +console.warn(e)),p.throwUnescapedHTML))throw new J("One of your code blocks includes unescaped HTML.",e.innerHTML) +;t=e;const i=t.textContent,o=n?m(i,{language:n,ignoreIllegals:!0}):x(i) +;e.innerHTML=o.value,e.dataset.highlighted="yes",((e,t,n)=>{const i=t&&s[t]||n +;e.classList.add("hljs"),e.classList.add("language-"+i) +})(e,n,o.language),e.result={language:o.language,re:o.relevance, +relevance:o.relevance},o.secondBest&&(e.secondBest={ +language:o.secondBest.language,relevance:o.secondBest.relevance +}),N("after:highlightElement",{el:e,result:o,text:i})}let y=!1;function _(){ +"loading"!==document.readyState?document.querySelectorAll(p.cssSelector).forEach(w):y=!0 +}function O(e){return e=(e||"").toLowerCase(),i[e]||i[s[e]]} +function v(e,{languageName:t}){"string"==typeof e&&(e=[e]),e.forEach((e=>{ +s[e.toLowerCase()]=t}))}function k(e){const t=O(e) +;return t&&!t.disableAutodetect}function N(e,t){const n=e;o.forEach((e=>{ +e[n]&&e[n](t)}))} +"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",(()=>{ +y&&_()}),!1),Object.assign(n,{highlight:m,highlightAuto:x,highlightAll:_, +highlightElement:w, +highlightBlock:e=>(G("10.7.0","highlightBlock will be removed entirely in v12.0"), +G("10.7.0","Please use highlightElement now."),w(e)),configure:e=>{p=Q(p,e)}, +initHighlighting:()=>{ +_(),G("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")}, +initHighlightingOnLoad:()=>{ +_(),G("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.") +},registerLanguage:(e,t)=>{let s=null;try{s=t(n)}catch(t){ +if(W("Language definition for '{}' could not be registered.".replace("{}",e)), +!r)throw t;W(t),s=l} +s.name||(s.name=e),i[e]=s,s.rawDefinition=t.bind(null,n),s.aliases&&v(s.aliases,{ +languageName:e})},unregisterLanguage:e=>{delete i[e] +;for(const t of Object.keys(s))s[t]===e&&delete s[t]}, +listLanguages:()=>Object.keys(i),getLanguage:O,registerAliases:v, +autoDetection:k,inherit:Q,addPlugin:e=>{(e=>{ +e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=t=>{ +e["before:highlightBlock"](Object.assign({block:t.el},t)) +}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=t=>{ +e["after:highlightBlock"](Object.assign({block:t.el},t))})})(e),o.push(e)}, +removePlugin:e=>{const t=o.indexOf(e);-1!==t&&o.splice(t,1)}}),n.debugMode=()=>{ +r=!1},n.safeMode=()=>{r=!0},n.versionString="11.10.0",n.regex={concat:h, +lookahead:g,either:f,optional:d,anyNumberOfTimes:u} +;for(const t in j)"object"==typeof j[t]&&e(j[t]);return Object.assign(n,j),n +},ne=te({});return ne.newInstance=()=>te({}),ne}() +;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `kotlin` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;var e="[0-9](_*[0-9])*",n=`\\.(${e})`,a="[0-9a-fA-F](_*[0-9a-fA-F])*",i={ +className:"number",variants:[{ +begin:`(\\b(${e})((${n})|\\.)?|(${n}))[eE][+-]?(${e})[fFdD]?\\b`},{ +begin:`\\b(${e})((${n})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${n})[fFdD]?\\b` +},{begin:`\\b(${e})[fFdD]\\b`},{ +begin:`\\b0[xX]((${a})\\.?|(${a})?\\.(${a}))[pP][+-]?(${e})[fFdD]?\\b`},{ +begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${a})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};return e=>{const n={ +keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual", +built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing", +literal:"true false null"},a={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@" +},s={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},t={ +className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},r={className:"string", +variants:[{begin:'"""',end:'"""(?=[^"])',contains:[t,s]},{begin:"'",end:"'", +illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/, +contains:[e.BACKSLASH_ESCAPE,t,s]}]};s.contains.push(r);const l={ +className:"meta", +begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?" +},c={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/, +end:/\)/,contains:[e.inherit(r,{className:"string"}),"self"]}] +},o=i,b=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),E={ +variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/, +contains:[]}]},d=E;return d.variants[1].contains=[E],E.variants[1].contains=[d], +{name:"Kotlin",aliases:["kt","kts"],keywords:n, +contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag", +begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,b,{className:"keyword", +begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol", +begin:/@\w+/}]}},a,l,c,{className:"function",beginKeywords:"fun",end:"[(]|$", +returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{ +begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, +contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://, +keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/, +endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/, +endsWithParent:!0,contains:[E,e.C_LINE_COMMENT_MODE,b],relevance:0 +},e.C_LINE_COMMENT_MODE,b,l,c,r,e.C_NUMBER_MODE]},b]},{ +begin:[/class|interface|trait/,/\s+/,e.UNDERSCORE_IDENT_RE],beginScope:{ +3:"title.class"},keywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0, +illegal:"extends implements",contains:[{ +beginKeywords:"public protected internal private constructor" +},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0, +excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,){\s]|$/, +excludeBegin:!0,returnEnd:!0},l,c]},r,{className:"meta",begin:"^#!/usr/bin/env", +end:"$",illegal:"\n"},o]}}})();hljs.registerLanguage("kotlin",e)})();/*! `markdown` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict";return e=>{const n={begin:/<\/?[A-Za-z_]/, +end:">",subLanguage:"xml",relevance:0},a={variants:[{begin:/\[.+?\]\[.*?\]/, +relevance:0},{ +begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/, +relevance:2},{ +begin:e.regex.concat(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/), +relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{ +begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/ +},{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0, +returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)", +excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[", +end:"\\]",excludeBegin:!0,excludeEnd:!0}]},i={className:"strong",contains:[], +variants:[{begin:/_{2}(?!\s)/,end:/_{2}/},{begin:/\*{2}(?!\s)/,end:/\*{2}/}] +},s={className:"emphasis",contains:[],variants:[{begin:/\*(?![*\s])/,end:/\*/},{ +begin:/_(?![_\s])/,end:/_/,relevance:0}]},c=e.inherit(i,{contains:[] +}),t=e.inherit(s,{contains:[]});i.contains.push(t),s.contains.push(c) +;let g=[n,a];return[i,s,c,t].forEach((e=>{e.contains=e.contains.concat(g) +})),g=g.concat(i,s),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{ +className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:g},{ +begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n", +contains:g}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)", +end:"\\s+",excludeEnd:!0},i,s,{className:"quote",begin:"^>\\s+",contains:g, +end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{ +begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{ +begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))", +contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{ +begin:"^[-\\*]{3,}",end:"$"},a,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{ +className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{ +className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]},{scope:"literal", +match:/&([a-zA-Z0-9]+|#[0-9]{1,7}|#[Xx][0-9a-fA-F]{1,6});/}]}}})() +;hljs.registerLanguage("markdown",e)})(); \ No newline at end of file diff --git a/app/src/main/assets/www/highlight/languages/kotlin.js b/app/src/main/assets/www/highlight/languages/kotlin.js new file mode 100644 index 000000000..fcaf2fb21 --- /dev/null +++ b/app/src/main/assets/www/highlight/languages/kotlin.js @@ -0,0 +1,296 @@ +/*! `kotlin` grammar compiled for Highlight.js 11.10.0 */ + (function(){ + var hljsGrammar = (function () { + 'use strict'; + + // https://docs.oracle.com/javase/specs/jls/se15/html/jls-3.html#jls-3.10 + var decimalDigits = '[0-9](_*[0-9])*'; + var frac = `\\.(${decimalDigits})`; + var hexDigits = '[0-9a-fA-F](_*[0-9a-fA-F])*'; + var NUMERIC = { + className: 'number', + variants: [ + // DecimalFloatingPointLiteral + // including ExponentPart + { begin: `(\\b(${decimalDigits})((${frac})|\\.)?|(${frac}))` + + `[eE][+-]?(${decimalDigits})[fFdD]?\\b` }, + // excluding ExponentPart + { begin: `\\b(${decimalDigits})((${frac})[fFdD]?\\b|\\.([fFdD]\\b)?)` }, + { begin: `(${frac})[fFdD]?\\b` }, + { begin: `\\b(${decimalDigits})[fFdD]\\b` }, + + // HexadecimalFloatingPointLiteral + { begin: `\\b0[xX]((${hexDigits})\\.?|(${hexDigits})?\\.(${hexDigits}))` + + `[pP][+-]?(${decimalDigits})[fFdD]?\\b` }, + + // DecimalIntegerLiteral + { begin: '\\b(0|[1-9](_*[0-9])*)[lL]?\\b' }, + + // HexIntegerLiteral + { begin: `\\b0[xX](${hexDigits})[lL]?\\b` }, + + // OctalIntegerLiteral + { begin: '\\b0(_*[0-7])*[lL]?\\b' }, + + // BinaryIntegerLiteral + { begin: '\\b0[bB][01](_*[01])*[lL]?\\b' }, + ], + relevance: 0 + }; + + /* + Language: Kotlin + Description: Kotlin is an OSS statically typed programming language that targets the JVM, Android, JavaScript and Native. + Author: Sergey Mashkov + Website: https://kotlinlang.org + Category: common + */ + + + function kotlin(hljs) { + const KEYWORDS = { + keyword: + 'abstract as val var vararg get set class object open private protected public noinline ' + + 'crossinline dynamic final enum if else do while for when throw try catch finally ' + + 'import package is in fun override companion reified inline lateinit init ' + + 'interface annotation data sealed internal infix operator out by constructor super ' + + 'tailrec where const inner suspend typealias external expect actual', + built_in: + 'Byte Short Char Int Long Boolean Float Double Void Unit Nothing', + literal: + 'true false null' + }; + const KEYWORDS_WITH_LABEL = { + className: 'keyword', + begin: /\b(break|continue|return|this)\b/, + starts: { contains: [ + { + className: 'symbol', + begin: /@\w+/ + } + ] } + }; + const LABEL = { + className: 'symbol', + begin: hljs.UNDERSCORE_IDENT_RE + '@' + }; + + // for string templates + const SUBST = { + className: 'subst', + begin: /\$\{/, + end: /\}/, + contains: [ hljs.C_NUMBER_MODE ] + }; + const VARIABLE = { + className: 'variable', + begin: '\\$' + hljs.UNDERSCORE_IDENT_RE + }; + const STRING = { + className: 'string', + variants: [ + { + begin: '"""', + end: '"""(?=[^"])', + contains: [ + VARIABLE, + SUBST + ] + }, + // Can't use built-in modes easily, as we want to use STRING in the meta + // context as 'meta-string' and there's no syntax to remove explicitly set + // classNames in built-in modes. + { + begin: '\'', + end: '\'', + illegal: /\n/, + contains: [ hljs.BACKSLASH_ESCAPE ] + }, + { + begin: '"', + end: '"', + illegal: /\n/, + contains: [ + hljs.BACKSLASH_ESCAPE, + VARIABLE, + SUBST + ] + } + ] + }; + SUBST.contains.push(STRING); + + const ANNOTATION_USE_SITE = { + className: 'meta', + begin: '@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*' + hljs.UNDERSCORE_IDENT_RE + ')?' + }; + const ANNOTATION = { + className: 'meta', + begin: '@' + hljs.UNDERSCORE_IDENT_RE, + contains: [ + { + begin: /\(/, + end: /\)/, + contains: [ + hljs.inherit(STRING, { className: 'string' }), + "self" + ] + } + ] + }; + + // https://kotlinlang.org/docs/reference/whatsnew11.html#underscores-in-numeric-literals + // According to the doc above, the number mode of kotlin is the same as java 8, + // so the code below is copied from java.js + const KOTLIN_NUMBER_MODE = NUMERIC; + const KOTLIN_NESTED_COMMENT = hljs.COMMENT( + '/\\*', '\\*/', + { contains: [ hljs.C_BLOCK_COMMENT_MODE ] } + ); + const KOTLIN_PAREN_TYPE = { variants: [ + { + className: 'type', + begin: hljs.UNDERSCORE_IDENT_RE + }, + { + begin: /\(/, + end: /\)/, + contains: [] // defined later + } + ] }; + const KOTLIN_PAREN_TYPE2 = KOTLIN_PAREN_TYPE; + KOTLIN_PAREN_TYPE2.variants[1].contains = [ KOTLIN_PAREN_TYPE ]; + KOTLIN_PAREN_TYPE.variants[1].contains = [ KOTLIN_PAREN_TYPE2 ]; + + return { + name: 'Kotlin', + aliases: [ + 'kt', + 'kts' + ], + keywords: KEYWORDS, + contains: [ + hljs.COMMENT( + '/\\*\\*', + '\\*/', + { + relevance: 0, + contains: [ + { + className: 'doctag', + begin: '@[A-Za-z]+' + } + ] + } + ), + hljs.C_LINE_COMMENT_MODE, + KOTLIN_NESTED_COMMENT, + KEYWORDS_WITH_LABEL, + LABEL, + ANNOTATION_USE_SITE, + ANNOTATION, + { + className: 'function', + beginKeywords: 'fun', + end: '[(]|$', + returnBegin: true, + excludeEnd: true, + keywords: KEYWORDS, + relevance: 5, + contains: [ + { + begin: hljs.UNDERSCORE_IDENT_RE + '\\s*\\(', + returnBegin: true, + relevance: 0, + contains: [ hljs.UNDERSCORE_TITLE_MODE ] + }, + { + className: 'type', + begin: //, + keywords: 'reified', + relevance: 0 + }, + { + className: 'params', + begin: /\(/, + end: /\)/, + endsParent: true, + keywords: KEYWORDS, + relevance: 0, + contains: [ + { + begin: /:/, + end: /[=,\/]/, + endsWithParent: true, + contains: [ + KOTLIN_PAREN_TYPE, + hljs.C_LINE_COMMENT_MODE, + KOTLIN_NESTED_COMMENT + ], + relevance: 0 + }, + hljs.C_LINE_COMMENT_MODE, + KOTLIN_NESTED_COMMENT, + ANNOTATION_USE_SITE, + ANNOTATION, + STRING, + hljs.C_NUMBER_MODE + ] + }, + KOTLIN_NESTED_COMMENT + ] + }, + { + begin: [ + /class|interface|trait/, + /\s+/, + hljs.UNDERSCORE_IDENT_RE + ], + beginScope: { + 3: "title.class" + }, + keywords: 'class interface trait', + end: /[:\{(]|$/, + excludeEnd: true, + illegal: 'extends implements', + contains: [ + { beginKeywords: 'public protected internal private constructor' }, + hljs.UNDERSCORE_TITLE_MODE, + { + className: 'type', + begin: //, + excludeBegin: true, + excludeEnd: true, + relevance: 0 + }, + { + className: 'type', + begin: /[,:]\s*/, + end: /[<\(,){\s]|$/, + excludeBegin: true, + returnEnd: true + }, + ANNOTATION_USE_SITE, + ANNOTATION + ] + }, + STRING, + { + className: 'meta', + begin: "^#!/usr/bin/env", + end: '$', + illegal: '\n' + }, + KOTLIN_NUMBER_MODE + ] + }; + } + + return kotlin; + +})(); + + hljs.registerLanguage('kotlin', hljsGrammar); + })(); \ No newline at end of file diff --git a/app/src/main/assets/www/highlight/languages/kotlin.min.js b/app/src/main/assets/www/highlight/languages/kotlin.min.js new file mode 100644 index 000000000..ece9533bc --- /dev/null +++ b/app/src/main/assets/www/highlight/languages/kotlin.min.js @@ -0,0 +1,46 @@ +/*! `kotlin` grammar compiled for Highlight.js 11.10.0 */ +(()=>{var e=(()=>{"use strict" +;var e="[0-9](_*[0-9])*",n=`\\.(${e})`,a="[0-9a-fA-F](_*[0-9a-fA-F])*",i={ +className:"number",variants:[{ +begin:`(\\b(${e})((${n})|\\.)?|(${n}))[eE][+-]?(${e})[fFdD]?\\b`},{ +begin:`\\b(${e})((${n})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${n})[fFdD]?\\b` +},{begin:`\\b(${e})[fFdD]\\b`},{ +begin:`\\b0[xX]((${a})\\.?|(${a})?\\.(${a}))[pP][+-]?(${e})[fFdD]?\\b`},{ +begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${a})[lL]?\\b`},{ +begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}], +relevance:0};return e=>{const n={ +keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual", +built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing", +literal:"true false null"},a={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@" +},s={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},t={ +className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},r={className:"string", +variants:[{begin:'"""',end:'"""(?=[^"])',contains:[t,s]},{begin:"'",end:"'", +illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/, +contains:[e.BACKSLASH_ESCAPE,t,s]}]};s.contains.push(r);const l={ +className:"meta", +begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?" +},c={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/, +end:/\)/,contains:[e.inherit(r,{className:"string"}),"self"]}] +},o=i,b=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),E={ +variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/, +contains:[]}]},d=E;return d.variants[1].contains=[E],E.variants[1].contains=[d], +{name:"Kotlin",aliases:["kt","kts"],keywords:n, +contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag", +begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,b,{className:"keyword", +begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol", +begin:/@\w+/}]}},a,l,c,{className:"function",beginKeywords:"fun",end:"[(]|$", +returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{ +begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0, +contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://, +keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/, +endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/, +endsWithParent:!0,contains:[E,e.C_LINE_COMMENT_MODE,b],relevance:0 +},e.C_LINE_COMMENT_MODE,b,l,c,r,e.C_NUMBER_MODE]},b]},{ +begin:[/class|interface|trait/,/\s+/,e.UNDERSCORE_IDENT_RE],beginScope:{ +3:"title.class"},keywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0, +illegal:"extends implements",contains:[{ +beginKeywords:"public protected internal private constructor" +},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0, +excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,){\s]|$/, +excludeBegin:!0,returnEnd:!0},l,c]},r,{className:"meta",begin:"^#!/usr/bin/env", +end:"$",illegal:"\n"},o]}}})();hljs.registerLanguage("kotlin",e)})(); \ No newline at end of file diff --git a/app/src/main/assets/www/highlight/showdown.min.js b/app/src/main/assets/www/highlight/showdown.min.js new file mode 100644 index 000000000..da89bffe8 --- /dev/null +++ b/app/src/main/assets/www/highlight/showdown.min.js @@ -0,0 +1,3 @@ +/*! showdown v 2.1.0 - 21-04-2022 */ +!function(){function a(e){"use strict";var r={omitExtraWLInCodeBlocks:{defaultValue:!1,describe:"Omit the default extra whiteline added to code blocks",type:"boolean"},noHeaderId:{defaultValue:!1,describe:"Turn on/off generated header id",type:"boolean"},prefixHeaderId:{defaultValue:!1,describe:"Add a prefix to the generated header ids. Passing a string will prefix that string to the header id. Setting to true will add a generic 'section-' prefix",type:"string"},rawPrefixHeaderId:{defaultValue:!1,describe:'Setting this option to true will prevent showdown from modifying the prefix. This might result in malformed IDs (if, for instance, the " char is used in the prefix)',type:"boolean"},ghCompatibleHeaderId:{defaultValue:!1,describe:"Generate header ids compatible with github style (spaces are replaced with dashes, a bunch of non alphanumeric chars are removed)",type:"boolean"},rawHeaderId:{defaultValue:!1,describe:"Remove only spaces, ' and \" from generated header ids (including prefixes), replacing them with dashes (-). WARNING: This might result in malformed ids",type:"boolean"},headerLevelStart:{defaultValue:!1,describe:"The header blocks level start",type:"integer"},parseImgDimensions:{defaultValue:!1,describe:"Turn on/off image dimension parsing",type:"boolean"},simplifiedAutoLink:{defaultValue:!1,describe:"Turn on/off GFM autolink style",type:"boolean"},excludeTrailingPunctuationFromURLs:{defaultValue:!1,describe:"Excludes trailing punctuation from links generated with autoLinking",type:"boolean"},literalMidWordUnderscores:{defaultValue:!1,describe:"Parse midword underscores as literal underscores",type:"boolean"},literalMidWordAsterisks:{defaultValue:!1,describe:"Parse midword asterisks as literal asterisks",type:"boolean"},strikethrough:{defaultValue:!1,describe:"Turn on/off strikethrough support",type:"boolean"},tables:{defaultValue:!1,describe:"Turn on/off tables support",type:"boolean"},tablesHeaderId:{defaultValue:!1,describe:"Add an id to table headers",type:"boolean"},ghCodeBlocks:{defaultValue:!0,describe:"Turn on/off GFM fenced code blocks support",type:"boolean"},tasklists:{defaultValue:!1,describe:"Turn on/off GFM tasklist support",type:"boolean"},smoothLivePreview:{defaultValue:!1,describe:"Prevents weird effects in live previews due to incomplete input",type:"boolean"},smartIndentationFix:{defaultValue:!1,describe:"Tries to smartly fix indentation in es6 strings",type:"boolean"},disableForced4SpacesIndentedSublists:{defaultValue:!1,describe:"Disables the requirement of indenting nested sublists by 4 spaces",type:"boolean"},simpleLineBreaks:{defaultValue:!1,describe:"Parses simple line breaks as
(GFM Style)",type:"boolean"},requireSpaceBeforeHeadingText:{defaultValue:!1,describe:"Makes adding a space between `#` and the header text mandatory (GFM Style)",type:"boolean"},ghMentions:{defaultValue:!1,describe:"Enables github @mentions",type:"boolean"},ghMentionsLink:{defaultValue:"https://github.com/{u}",describe:"Changes the link generated by @mentions. Only applies if ghMentions option is enabled.",type:"string"},encodeEmails:{defaultValue:!0,describe:"Encode e-mail addresses through the use of Character Entities, transforming ASCII e-mail addresses into its equivalent decimal entities",type:"boolean"},openLinksInNewWindow:{defaultValue:!1,describe:"Open all links in new windows",type:"boolean"},backslashEscapesHTMLTags:{defaultValue:!1,describe:"Support for HTML Tag escaping. ex:
foo
",type:"boolean"},emoji:{defaultValue:!1,describe:"Enable emoji support. Ex: `this is a :smile: emoji`",type:"boolean"},underline:{defaultValue:!1,describe:"Enable support for underline. Syntax is double or triple underscores: `__underline word__`. With this option enabled, underscores no longer parses into `` and ``",type:"boolean"},ellipsis:{defaultValue:!0,describe:"Replaces three dots with the ellipsis unicode character",type:"boolean"},completeHTMLDocument:{defaultValue:!1,describe:"Outputs a complete html document, including ``, `` and `` tags",type:"boolean"},metadata:{defaultValue:!1,describe:"Enable support for document metadata (defined at the top of the document between `«««` and `»»»` or between `---` and `---`).",type:"boolean"},splitAdjacentBlockquotes:{defaultValue:!1,describe:"Split adjacent blockquote blocks",type:"boolean"}};if(!1===e)return JSON.parse(JSON.stringify(r));var t,a={};for(t in r)r.hasOwnProperty(t)&&(a[t]=r[t].defaultValue);return a}var x={},t={},d={},p=a(!0),h="vanilla",_={github:{omitExtraWLInCodeBlocks:!0,simplifiedAutoLink:!0,excludeTrailingPunctuationFromURLs:!0,literalMidWordUnderscores:!0,strikethrough:!0,tables:!0,tablesHeaderId:!0,ghCodeBlocks:!0,tasklists:!0,disableForced4SpacesIndentedSublists:!0,simpleLineBreaks:!0,requireSpaceBeforeHeadingText:!0,ghCompatibleHeaderId:!0,ghMentions:!0,backslashEscapesHTMLTags:!0,emoji:!0,splitAdjacentBlockquotes:!0},original:{noHeaderId:!0,ghCodeBlocks:!1},ghost:{omitExtraWLInCodeBlocks:!0,parseImgDimensions:!0,simplifiedAutoLink:!0,excludeTrailingPunctuationFromURLs:!0,literalMidWordUnderscores:!0,strikethrough:!0,tables:!0,tablesHeaderId:!0,ghCodeBlocks:!0,tasklists:!0,smoothLivePreview:!0,simpleLineBreaks:!0,requireSpaceBeforeHeadingText:!0,ghMentions:!1,encodeEmails:!0},vanilla:a(!0),allOn:function(){"use strict";var e,r=a(!0),t={};for(e in r)r.hasOwnProperty(e)&&(t[e]=!0);return t}()};function g(e,r){"use strict";var t=r?"Error in "+r+" extension->":"Error in unnamed extension",a={valid:!0,error:""};x.helper.isArray(e)||(e=[e]);for(var n=0;n").replace(/&/g,"&")};function u(e,r,t,a){"use strict";var n,s,o,i=-1<(a=a||"").indexOf("g"),l=new RegExp(r+"|"+t,"g"+a.replace(/g/g,"")),c=new RegExp(r,a.replace(/g/g,"")),u=[];do{for(n=0;p=l.exec(e);)if(c.test(p[0]))n++||(o=(s=l.lastIndex)-p[0].length);else if(n&&!--n){var d=p.index+p[0].length,p={left:{start:o,end:s},match:{start:s,end:p.index},right:{start:p.index,end:d},wholeMatch:{start:o,end:d}};if(u.push(p),!i)return u}}while(n&&(l.lastIndex=s));return u}function s(u){"use strict";return function(e,r,t,a,n,s,o){var i=t=t.replace(x.helper.regexes.asteriskDashAndColon,x.helper.escapeCharactersCallback),l="",c="",r=r||"",o=o||"";return/^www\./i.test(t)&&(t=t.replace(/^www\./i,"http://www.")),u.excludeTrailingPunctuationFromURLs&&s&&(l=s),r+'"+i+""+l+o}}function o(n,s){"use strict";return function(e,r,t){var a="mailto:";return r=r||"",t=x.subParser("unescapeSpecialChars")(t,n,s),n.encodeEmails?(a=x.helper.encodeEmailAddress(a+t),t=x.helper.encodeEmailAddress(t)):a+=t,r+''+t+""}}x.helper.matchRecursiveRegExp=function(e,r,t,a){"use strict";for(var n=u(e,r,t,a),s=[],o=0;o>=0,t=String(t||" "),e.length>r?String(e):((r-=e.length)>t.length&&(t+=t.repeat(r/t.length)),String(e)+t.slice(0,r))},"undefined"==typeof console&&(console={warn:function(e){"use strict";alert(e)},log:function(e){"use strict";alert(e)},error:function(e){"use strict";throw e}}),x.helper.regexes={asteriskDashAndColon:/([*_:~])/g},x.helper.emojis={"+1":"👍","-1":"👎",100:"💯",1234:"🔢","1st_place_medal":"🥇","2nd_place_medal":"🥈","3rd_place_medal":"🥉","8ball":"🎱",a:"🅰️",ab:"🆎",abc:"🔤",abcd:"🔡",accept:"🉑",aerial_tramway:"🚡",airplane:"✈️",alarm_clock:"⏰",alembic:"⚗️",alien:"👽",ambulance:"🚑",amphora:"🏺",anchor:"⚓️",angel:"👼",anger:"💢",angry:"😠",anguished:"😧",ant:"🐜",apple:"🍎",aquarius:"♒️",aries:"♈️",arrow_backward:"◀️",arrow_double_down:"⏬",arrow_double_up:"⏫",arrow_down:"⬇️",arrow_down_small:"🔽",arrow_forward:"▶️",arrow_heading_down:"⤵️",arrow_heading_up:"⤴️",arrow_left:"⬅️",arrow_lower_left:"↙️",arrow_lower_right:"↘️",arrow_right:"➡️",arrow_right_hook:"↪️",arrow_up:"⬆️",arrow_up_down:"↕️",arrow_up_small:"🔼",arrow_upper_left:"↖️",arrow_upper_right:"↗️",arrows_clockwise:"🔃",arrows_counterclockwise:"🔄",art:"🎨",articulated_lorry:"🚛",artificial_satellite:"🛰",astonished:"😲",athletic_shoe:"👟",atm:"🏧",atom_symbol:"⚛️",avocado:"🥑",b:"🅱️",baby:"👶",baby_bottle:"🍼",baby_chick:"🐤",baby_symbol:"🚼",back:"🔙",bacon:"🥓",badminton:"🏸",baggage_claim:"🛄",baguette_bread:"🥖",balance_scale:"⚖️",balloon:"🎈",ballot_box:"🗳",ballot_box_with_check:"☑️",bamboo:"🎍",banana:"🍌",bangbang:"‼️",bank:"🏦",bar_chart:"📊",barber:"💈",baseball:"⚾️",basketball:"🏀",basketball_man:"⛹️",basketball_woman:"⛹️‍♀️",bat:"🦇",bath:"🛀",bathtub:"🛁",battery:"🔋",beach_umbrella:"🏖",bear:"🐻",bed:"🛏",bee:"🐝",beer:"🍺",beers:"🍻",beetle:"🐞",beginner:"🔰",bell:"🔔",bellhop_bell:"🛎",bento:"🍱",biking_man:"🚴",bike:"🚲",biking_woman:"🚴‍♀️",bikini:"👙",biohazard:"☣️",bird:"🐦",birthday:"🎂",black_circle:"⚫️",black_flag:"🏴",black_heart:"🖤",black_joker:"🃏",black_large_square:"⬛️",black_medium_small_square:"◾️",black_medium_square:"◼️",black_nib:"✒️",black_small_square:"▪️",black_square_button:"🔲",blonde_man:"👱",blonde_woman:"👱‍♀️",blossom:"🌼",blowfish:"🐡",blue_book:"📘",blue_car:"🚙",blue_heart:"💙",blush:"😊",boar:"🐗",boat:"⛵️",bomb:"💣",book:"📖",bookmark:"🔖",bookmark_tabs:"📑",books:"📚",boom:"💥",boot:"👢",bouquet:"💐",bowing_man:"🙇",bow_and_arrow:"🏹",bowing_woman:"🙇‍♀️",bowling:"🎳",boxing_glove:"🥊",boy:"👦",bread:"🍞",bride_with_veil:"👰",bridge_at_night:"🌉",briefcase:"💼",broken_heart:"💔",bug:"🐛",building_construction:"🏗",bulb:"💡",bullettrain_front:"🚅",bullettrain_side:"🚄",burrito:"🌯",bus:"🚌",business_suit_levitating:"🕴",busstop:"🚏",bust_in_silhouette:"👤",busts_in_silhouette:"👥",butterfly:"🦋",cactus:"🌵",cake:"🍰",calendar:"📆",call_me_hand:"🤙",calling:"📲",camel:"🐫",camera:"📷",camera_flash:"📸",camping:"🏕",cancer:"♋️",candle:"🕯",candy:"🍬",canoe:"🛶",capital_abcd:"🔠",capricorn:"♑️",car:"🚗",card_file_box:"🗃",card_index:"📇",card_index_dividers:"🗂",carousel_horse:"🎠",carrot:"🥕",cat:"🐱",cat2:"🐈",cd:"💿",chains:"⛓",champagne:"🍾",chart:"💹",chart_with_downwards_trend:"📉",chart_with_upwards_trend:"📈",checkered_flag:"🏁",cheese:"🧀",cherries:"🍒",cherry_blossom:"🌸",chestnut:"🌰",chicken:"🐔",children_crossing:"🚸",chipmunk:"🐿",chocolate_bar:"🍫",christmas_tree:"🎄",church:"⛪️",cinema:"🎦",circus_tent:"🎪",city_sunrise:"🌇",city_sunset:"🌆",cityscape:"🏙",cl:"🆑",clamp:"🗜",clap:"👏",clapper:"🎬",classical_building:"🏛",clinking_glasses:"🥂",clipboard:"📋",clock1:"🕐",clock10:"🕙",clock1030:"🕥",clock11:"🕚",clock1130:"🕦",clock12:"🕛",clock1230:"🕧",clock130:"🕜",clock2:"🕑",clock230:"🕝",clock3:"🕒",clock330:"🕞",clock4:"🕓",clock430:"🕟",clock5:"🕔",clock530:"🕠",clock6:"🕕",clock630:"🕡",clock7:"🕖",clock730:"🕢",clock8:"🕗",clock830:"🕣",clock9:"🕘",clock930:"🕤",closed_book:"📕",closed_lock_with_key:"🔐",closed_umbrella:"🌂",cloud:"☁️",cloud_with_lightning:"🌩",cloud_with_lightning_and_rain:"⛈",cloud_with_rain:"🌧",cloud_with_snow:"🌨",clown_face:"🤡",clubs:"♣️",cocktail:"🍸",coffee:"☕️",coffin:"⚰️",cold_sweat:"😰",comet:"☄️",computer:"💻",computer_mouse:"🖱",confetti_ball:"🎊",confounded:"😖",confused:"😕",congratulations:"㊗️",construction:"🚧",construction_worker_man:"👷",construction_worker_woman:"👷‍♀️",control_knobs:"🎛",convenience_store:"🏪",cookie:"🍪",cool:"🆒",policeman:"👮",copyright:"©️",corn:"🌽",couch_and_lamp:"🛋",couple:"👫",couple_with_heart_woman_man:"💑",couple_with_heart_man_man:"👨‍❤️‍👨",couple_with_heart_woman_woman:"👩‍❤️‍👩",couplekiss_man_man:"👨‍❤️‍💋‍👨",couplekiss_man_woman:"💏",couplekiss_woman_woman:"👩‍❤️‍💋‍👩",cow:"🐮",cow2:"🐄",cowboy_hat_face:"🤠",crab:"🦀",crayon:"🖍",credit_card:"💳",crescent_moon:"🌙",cricket:"🏏",crocodile:"🐊",croissant:"🥐",crossed_fingers:"🤞",crossed_flags:"🎌",crossed_swords:"⚔️",crown:"👑",cry:"😢",crying_cat_face:"😿",crystal_ball:"🔮",cucumber:"🥒",cupid:"💘",curly_loop:"➰",currency_exchange:"💱",curry:"🍛",custard:"🍮",customs:"🛃",cyclone:"🌀",dagger:"🗡",dancer:"💃",dancing_women:"👯",dancing_men:"👯‍♂️",dango:"🍡",dark_sunglasses:"🕶",dart:"🎯",dash:"💨",date:"📅",deciduous_tree:"🌳",deer:"🦌",department_store:"🏬",derelict_house:"🏚",desert:"🏜",desert_island:"🏝",desktop_computer:"🖥",male_detective:"🕵️",diamond_shape_with_a_dot_inside:"💠",diamonds:"♦️",disappointed:"😞",disappointed_relieved:"😥",dizzy:"💫",dizzy_face:"😵",do_not_litter:"🚯",dog:"🐶",dog2:"🐕",dollar:"💵",dolls:"🎎",dolphin:"🐬",door:"🚪",doughnut:"🍩",dove:"🕊",dragon:"🐉",dragon_face:"🐲",dress:"👗",dromedary_camel:"🐪",drooling_face:"🤤",droplet:"💧",drum:"🥁",duck:"🦆",dvd:"📀","e-mail":"📧",eagle:"🦅",ear:"👂",ear_of_rice:"🌾",earth_africa:"🌍",earth_americas:"🌎",earth_asia:"🌏",egg:"🥚",eggplant:"🍆",eight_pointed_black_star:"✴️",eight_spoked_asterisk:"✳️",electric_plug:"🔌",elephant:"🐘",email:"✉️",end:"🔚",envelope_with_arrow:"📩",euro:"💶",european_castle:"🏰",european_post_office:"🏤",evergreen_tree:"🌲",exclamation:"❗️",expressionless:"😑",eye:"👁",eye_speech_bubble:"👁‍🗨",eyeglasses:"👓",eyes:"👀",face_with_head_bandage:"🤕",face_with_thermometer:"🤒",fist_oncoming:"👊",factory:"🏭",fallen_leaf:"🍂",family_man_woman_boy:"👪",family_man_boy:"👨‍👦",family_man_boy_boy:"👨‍👦‍👦",family_man_girl:"👨‍👧",family_man_girl_boy:"👨‍👧‍👦",family_man_girl_girl:"👨‍👧‍👧",family_man_man_boy:"👨‍👨‍👦",family_man_man_boy_boy:"👨‍👨‍👦‍👦",family_man_man_girl:"👨‍👨‍👧",family_man_man_girl_boy:"👨‍👨‍👧‍👦",family_man_man_girl_girl:"👨‍👨‍👧‍👧",family_man_woman_boy_boy:"👨‍👩‍👦‍👦",family_man_woman_girl:"👨‍👩‍👧",family_man_woman_girl_boy:"👨‍👩‍👧‍👦",family_man_woman_girl_girl:"👨‍👩‍👧‍👧",family_woman_boy:"👩‍👦",family_woman_boy_boy:"👩‍👦‍👦",family_woman_girl:"👩‍👧",family_woman_girl_boy:"👩‍👧‍👦",family_woman_girl_girl:"👩‍👧‍👧",family_woman_woman_boy:"👩‍👩‍👦",family_woman_woman_boy_boy:"👩‍👩‍👦‍👦",family_woman_woman_girl:"👩‍👩‍👧",family_woman_woman_girl_boy:"👩‍👩‍👧‍👦",family_woman_woman_girl_girl:"👩‍👩‍👧‍👧",fast_forward:"⏩",fax:"📠",fearful:"😨",feet:"🐾",female_detective:"🕵️‍♀️",ferris_wheel:"🎡",ferry:"⛴",field_hockey:"🏑",file_cabinet:"🗄",file_folder:"📁",film_projector:"📽",film_strip:"🎞",fire:"🔥",fire_engine:"🚒",fireworks:"🎆",first_quarter_moon:"🌓",first_quarter_moon_with_face:"🌛",fish:"🐟",fish_cake:"🍥",fishing_pole_and_fish:"🎣",fist_raised:"✊",fist_left:"🤛",fist_right:"🤜",flags:"🎏",flashlight:"🔦",fleur_de_lis:"⚜️",flight_arrival:"🛬",flight_departure:"🛫",floppy_disk:"💾",flower_playing_cards:"🎴",flushed:"😳",fog:"🌫",foggy:"🌁",football:"🏈",footprints:"👣",fork_and_knife:"🍴",fountain:"⛲️",fountain_pen:"🖋",four_leaf_clover:"🍀",fox_face:"🦊",framed_picture:"🖼",free:"🆓",fried_egg:"🍳",fried_shrimp:"🍤",fries:"🍟",frog:"🐸",frowning:"😦",frowning_face:"☹️",frowning_man:"🙍‍♂️",frowning_woman:"🙍",middle_finger:"🖕",fuelpump:"⛽️",full_moon:"🌕",full_moon_with_face:"🌝",funeral_urn:"⚱️",game_die:"🎲",gear:"⚙️",gem:"💎",gemini:"♊️",ghost:"👻",gift:"🎁",gift_heart:"💝",girl:"👧",globe_with_meridians:"🌐",goal_net:"🥅",goat:"🐐",golf:"⛳️",golfing_man:"🏌️",golfing_woman:"🏌️‍♀️",gorilla:"🦍",grapes:"🍇",green_apple:"🍏",green_book:"📗",green_heart:"💚",green_salad:"🥗",grey_exclamation:"❕",grey_question:"❔",grimacing:"😬",grin:"😁",grinning:"😀",guardsman:"💂",guardswoman:"💂‍♀️",guitar:"🎸",gun:"🔫",haircut_woman:"💇",haircut_man:"💇‍♂️",hamburger:"🍔",hammer:"🔨",hammer_and_pick:"⚒",hammer_and_wrench:"🛠",hamster:"🐹",hand:"✋",handbag:"👜",handshake:"🤝",hankey:"💩",hatched_chick:"🐥",hatching_chick:"🐣",headphones:"🎧",hear_no_evil:"🙉",heart:"❤️",heart_decoration:"💟",heart_eyes:"😍",heart_eyes_cat:"😻",heartbeat:"💓",heartpulse:"💗",hearts:"♥️",heavy_check_mark:"✔️",heavy_division_sign:"➗",heavy_dollar_sign:"💲",heavy_heart_exclamation:"❣️",heavy_minus_sign:"➖",heavy_multiplication_x:"✖️",heavy_plus_sign:"➕",helicopter:"🚁",herb:"🌿",hibiscus:"🌺",high_brightness:"🔆",high_heel:"👠",hocho:"🔪",hole:"🕳",honey_pot:"🍯",horse:"🐴",horse_racing:"🏇",hospital:"🏥",hot_pepper:"🌶",hotdog:"🌭",hotel:"🏨",hotsprings:"♨️",hourglass:"⌛️",hourglass_flowing_sand:"⏳",house:"🏠",house_with_garden:"🏡",houses:"🏘",hugs:"🤗",hushed:"😯",ice_cream:"🍨",ice_hockey:"🏒",ice_skate:"⛸",icecream:"🍦",id:"🆔",ideograph_advantage:"🉐",imp:"👿",inbox_tray:"📥",incoming_envelope:"📨",tipping_hand_woman:"💁",information_source:"ℹ️",innocent:"😇",interrobang:"⁉️",iphone:"📱",izakaya_lantern:"🏮",jack_o_lantern:"🎃",japan:"🗾",japanese_castle:"🏯",japanese_goblin:"👺",japanese_ogre:"👹",jeans:"👖",joy:"😂",joy_cat:"😹",joystick:"🕹",kaaba:"🕋",key:"🔑",keyboard:"⌨️",keycap_ten:"🔟",kick_scooter:"🛴",kimono:"👘",kiss:"💋",kissing:"😗",kissing_cat:"😽",kissing_closed_eyes:"😚",kissing_heart:"😘",kissing_smiling_eyes:"😙",kiwi_fruit:"🥝",koala:"🐨",koko:"🈁",label:"🏷",large_blue_circle:"🔵",large_blue_diamond:"🔷",large_orange_diamond:"🔶",last_quarter_moon:"🌗",last_quarter_moon_with_face:"🌜",latin_cross:"✝️",laughing:"😆",leaves:"🍃",ledger:"📒",left_luggage:"🛅",left_right_arrow:"↔️",leftwards_arrow_with_hook:"↩️",lemon:"🍋",leo:"♌️",leopard:"🐆",level_slider:"🎚",libra:"♎️",light_rail:"🚈",link:"🔗",lion:"🦁",lips:"👄",lipstick:"💄",lizard:"🦎",lock:"🔒",lock_with_ink_pen:"🔏",lollipop:"🍭",loop:"➿",loud_sound:"🔊",loudspeaker:"📢",love_hotel:"🏩",love_letter:"💌",low_brightness:"🔅",lying_face:"🤥",m:"Ⓜ️",mag:"🔍",mag_right:"🔎",mahjong:"🀄️",mailbox:"📫",mailbox_closed:"📪",mailbox_with_mail:"📬",mailbox_with_no_mail:"📭",man:"👨",man_artist:"👨‍🎨",man_astronaut:"👨‍🚀",man_cartwheeling:"🤸‍♂️",man_cook:"👨‍🍳",man_dancing:"🕺",man_facepalming:"🤦‍♂️",man_factory_worker:"👨‍🏭",man_farmer:"👨‍🌾",man_firefighter:"👨‍🚒",man_health_worker:"👨‍⚕️",man_in_tuxedo:"🤵",man_judge:"👨‍⚖️",man_juggling:"🤹‍♂️",man_mechanic:"👨‍🔧",man_office_worker:"👨‍💼",man_pilot:"👨‍✈️",man_playing_handball:"🤾‍♂️",man_playing_water_polo:"🤽‍♂️",man_scientist:"👨‍🔬",man_shrugging:"🤷‍♂️",man_singer:"👨‍🎤",man_student:"👨‍🎓",man_teacher:"👨‍🏫",man_technologist:"👨‍💻",man_with_gua_pi_mao:"👲",man_with_turban:"👳",tangerine:"🍊",mans_shoe:"👞",mantelpiece_clock:"🕰",maple_leaf:"🍁",martial_arts_uniform:"🥋",mask:"😷",massage_woman:"💆",massage_man:"💆‍♂️",meat_on_bone:"🍖",medal_military:"🎖",medal_sports:"🏅",mega:"📣",melon:"🍈",memo:"📝",men_wrestling:"🤼‍♂️",menorah:"🕎",mens:"🚹",metal:"🤘",metro:"🚇",microphone:"🎤",microscope:"🔬",milk_glass:"🥛",milky_way:"🌌",minibus:"🚐",minidisc:"💽",mobile_phone_off:"📴",money_mouth_face:"🤑",money_with_wings:"💸",moneybag:"💰",monkey:"🐒",monkey_face:"🐵",monorail:"🚝",moon:"🌔",mortar_board:"🎓",mosque:"🕌",motor_boat:"🛥",motor_scooter:"🛵",motorcycle:"🏍",motorway:"🛣",mount_fuji:"🗻",mountain:"⛰",mountain_biking_man:"🚵",mountain_biking_woman:"🚵‍♀️",mountain_cableway:"🚠",mountain_railway:"🚞",mountain_snow:"🏔",mouse:"🐭",mouse2:"🐁",movie_camera:"🎥",moyai:"🗿",mrs_claus:"🤶",muscle:"💪",mushroom:"🍄",musical_keyboard:"🎹",musical_note:"🎵",musical_score:"🎼",mute:"🔇",nail_care:"💅",name_badge:"📛",national_park:"🏞",nauseated_face:"🤢",necktie:"👔",negative_squared_cross_mark:"❎",nerd_face:"🤓",neutral_face:"😐",new:"🆕",new_moon:"🌑",new_moon_with_face:"🌚",newspaper:"📰",newspaper_roll:"🗞",next_track_button:"⏭",ng:"🆖",no_good_man:"🙅‍♂️",no_good_woman:"🙅",night_with_stars:"🌃",no_bell:"🔕",no_bicycles:"🚳",no_entry:"⛔️",no_entry_sign:"🚫",no_mobile_phones:"📵",no_mouth:"😶",no_pedestrians:"🚷",no_smoking:"🚭","non-potable_water":"🚱",nose:"👃",notebook:"📓",notebook_with_decorative_cover:"📔",notes:"🎶",nut_and_bolt:"🔩",o:"⭕️",o2:"🅾️",ocean:"🌊",octopus:"🐙",oden:"🍢",office:"🏢",oil_drum:"🛢",ok:"🆗",ok_hand:"👌",ok_man:"🙆‍♂️",ok_woman:"🙆",old_key:"🗝",older_man:"👴",older_woman:"👵",om:"🕉",on:"🔛",oncoming_automobile:"🚘",oncoming_bus:"🚍",oncoming_police_car:"🚔",oncoming_taxi:"🚖",open_file_folder:"📂",open_hands:"👐",open_mouth:"😮",open_umbrella:"☂️",ophiuchus:"⛎",orange_book:"📙",orthodox_cross:"☦️",outbox_tray:"📤",owl:"🦉",ox:"🐂",package:"📦",page_facing_up:"📄",page_with_curl:"📃",pager:"📟",paintbrush:"🖌",palm_tree:"🌴",pancakes:"🥞",panda_face:"🐼",paperclip:"📎",paperclips:"🖇",parasol_on_ground:"⛱",parking:"🅿️",part_alternation_mark:"〽️",partly_sunny:"⛅️",passenger_ship:"🛳",passport_control:"🛂",pause_button:"⏸",peace_symbol:"☮️",peach:"🍑",peanuts:"🥜",pear:"🍐",pen:"🖊",pencil2:"✏️",penguin:"🐧",pensive:"😔",performing_arts:"🎭",persevere:"😣",person_fencing:"🤺",pouting_woman:"🙎",phone:"☎️",pick:"⛏",pig:"🐷",pig2:"🐖",pig_nose:"🐽",pill:"💊",pineapple:"🍍",ping_pong:"🏓",pisces:"♓️",pizza:"🍕",place_of_worship:"🛐",plate_with_cutlery:"🍽",play_or_pause_button:"⏯",point_down:"👇",point_left:"👈",point_right:"👉",point_up:"☝️",point_up_2:"👆",police_car:"🚓",policewoman:"👮‍♀️",poodle:"🐩",popcorn:"🍿",post_office:"🏣",postal_horn:"📯",postbox:"📮",potable_water:"🚰",potato:"🥔",pouch:"👝",poultry_leg:"🍗",pound:"💷",rage:"😡",pouting_cat:"😾",pouting_man:"🙎‍♂️",pray:"🙏",prayer_beads:"📿",pregnant_woman:"🤰",previous_track_button:"⏮",prince:"🤴",princess:"👸",printer:"🖨",purple_heart:"💜",purse:"👛",pushpin:"📌",put_litter_in_its_place:"🚮",question:"❓",rabbit:"🐰",rabbit2:"🐇",racehorse:"🐎",racing_car:"🏎",radio:"📻",radio_button:"🔘",radioactive:"☢️",railway_car:"🚃",railway_track:"🛤",rainbow:"🌈",rainbow_flag:"🏳️‍🌈",raised_back_of_hand:"🤚",raised_hand_with_fingers_splayed:"🖐",raised_hands:"🙌",raising_hand_woman:"🙋",raising_hand_man:"🙋‍♂️",ram:"🐏",ramen:"🍜",rat:"🐀",record_button:"⏺",recycle:"♻️",red_circle:"🔴",registered:"®️",relaxed:"☺️",relieved:"😌",reminder_ribbon:"🎗",repeat:"🔁",repeat_one:"🔂",rescue_worker_helmet:"⛑",restroom:"🚻",revolving_hearts:"💞",rewind:"⏪",rhinoceros:"🦏",ribbon:"🎀",rice:"🍚",rice_ball:"🍙",rice_cracker:"🍘",rice_scene:"🎑",right_anger_bubble:"🗯",ring:"💍",robot:"🤖",rocket:"🚀",rofl:"🤣",roll_eyes:"🙄",roller_coaster:"🎢",rooster:"🐓",rose:"🌹",rosette:"🏵",rotating_light:"🚨",round_pushpin:"📍",rowing_man:"🚣",rowing_woman:"🚣‍♀️",rugby_football:"🏉",running_man:"🏃",running_shirt_with_sash:"🎽",running_woman:"🏃‍♀️",sa:"🈂️",sagittarius:"♐️",sake:"🍶",sandal:"👡",santa:"🎅",satellite:"📡",saxophone:"🎷",school:"🏫",school_satchel:"🎒",scissors:"✂️",scorpion:"🦂",scorpius:"♏️",scream:"😱",scream_cat:"🙀",scroll:"📜",seat:"💺",secret:"㊙️",see_no_evil:"🙈",seedling:"🌱",selfie:"🤳",shallow_pan_of_food:"🥘",shamrock:"☘️",shark:"🦈",shaved_ice:"🍧",sheep:"🐑",shell:"🐚",shield:"🛡",shinto_shrine:"⛩",ship:"🚢",shirt:"👕",shopping:"🛍",shopping_cart:"🛒",shower:"🚿",shrimp:"🦐",signal_strength:"📶",six_pointed_star:"🔯",ski:"🎿",skier:"⛷",skull:"💀",skull_and_crossbones:"☠️",sleeping:"😴",sleeping_bed:"🛌",sleepy:"😪",slightly_frowning_face:"🙁",slightly_smiling_face:"🙂",slot_machine:"🎰",small_airplane:"🛩",small_blue_diamond:"🔹",small_orange_diamond:"🔸",small_red_triangle:"🔺",small_red_triangle_down:"🔻",smile:"😄",smile_cat:"😸",smiley:"😃",smiley_cat:"😺",smiling_imp:"😈",smirk:"😏",smirk_cat:"😼",smoking:"🚬",snail:"🐌",snake:"🐍",sneezing_face:"🤧",snowboarder:"🏂",snowflake:"❄️",snowman:"⛄️",snowman_with_snow:"☃️",sob:"😭",soccer:"⚽️",soon:"🔜",sos:"🆘",sound:"🔉",space_invader:"👾",spades:"♠️",spaghetti:"🍝",sparkle:"❇️",sparkler:"🎇",sparkles:"✨",sparkling_heart:"💖",speak_no_evil:"🙊",speaker:"🔈",speaking_head:"🗣",speech_balloon:"💬",speedboat:"🚤",spider:"🕷",spider_web:"🕸",spiral_calendar:"🗓",spiral_notepad:"🗒",spoon:"🥄",squid:"🦑",stadium:"🏟",star:"⭐️",star2:"🌟",star_and_crescent:"☪️",star_of_david:"✡️",stars:"🌠",station:"🚉",statue_of_liberty:"🗽",steam_locomotive:"🚂",stew:"🍲",stop_button:"⏹",stop_sign:"🛑",stopwatch:"⏱",straight_ruler:"📏",strawberry:"🍓",stuck_out_tongue:"😛",stuck_out_tongue_closed_eyes:"😝",stuck_out_tongue_winking_eye:"😜",studio_microphone:"🎙",stuffed_flatbread:"🥙",sun_behind_large_cloud:"🌥",sun_behind_rain_cloud:"🌦",sun_behind_small_cloud:"🌤",sun_with_face:"🌞",sunflower:"🌻",sunglasses:"😎",sunny:"☀️",sunrise:"🌅",sunrise_over_mountains:"🌄",surfing_man:"🏄",surfing_woman:"🏄‍♀️",sushi:"🍣",suspension_railway:"🚟",sweat:"😓",sweat_drops:"💦",sweat_smile:"😅",sweet_potato:"🍠",swimming_man:"🏊",swimming_woman:"🏊‍♀️",symbols:"🔣",synagogue:"🕍",syringe:"💉",taco:"🌮",tada:"🎉",tanabata_tree:"🎋",taurus:"♉️",taxi:"🚕",tea:"🍵",telephone_receiver:"📞",telescope:"🔭",tennis:"🎾",tent:"⛺️",thermometer:"🌡",thinking:"🤔",thought_balloon:"💭",ticket:"🎫",tickets:"🎟",tiger:"🐯",tiger2:"🐅",timer_clock:"⏲",tipping_hand_man:"💁‍♂️",tired_face:"😫",tm:"™️",toilet:"🚽",tokyo_tower:"🗼",tomato:"🍅",tongue:"👅",top:"🔝",tophat:"🎩",tornado:"🌪",trackball:"🖲",tractor:"🚜",traffic_light:"🚥",train:"🚋",train2:"🚆",tram:"🚊",triangular_flag_on_post:"🚩",triangular_ruler:"📐",trident:"🔱",triumph:"😤",trolleybus:"🚎",trophy:"🏆",tropical_drink:"🍹",tropical_fish:"🐠",truck:"🚚",trumpet:"🎺",tulip:"🌷",tumbler_glass:"🥃",turkey:"🦃",turtle:"🐢",tv:"📺",twisted_rightwards_arrows:"🔀",two_hearts:"💕",two_men_holding_hands:"👬",two_women_holding_hands:"👭",u5272:"🈹",u5408:"🈴",u55b6:"🈺",u6307:"🈯️",u6708:"🈷️",u6709:"🈶",u6e80:"🈵",u7121:"🈚️",u7533:"🈸",u7981:"🈲",u7a7a:"🈳",umbrella:"☔️",unamused:"😒",underage:"🔞",unicorn:"🦄",unlock:"🔓",up:"🆙",upside_down_face:"🙃",v:"✌️",vertical_traffic_light:"🚦",vhs:"📼",vibration_mode:"📳",video_camera:"📹",video_game:"🎮",violin:"🎻",virgo:"♍️",volcano:"🌋",volleyball:"🏐",vs:"🆚",vulcan_salute:"🖖",walking_man:"🚶",walking_woman:"🚶‍♀️",waning_crescent_moon:"🌘",waning_gibbous_moon:"🌖",warning:"⚠️",wastebasket:"🗑",watch:"⌚️",water_buffalo:"🐃",watermelon:"🍉",wave:"👋",wavy_dash:"〰️",waxing_crescent_moon:"🌒",wc:"🚾",weary:"😩",wedding:"💒",weight_lifting_man:"🏋️",weight_lifting_woman:"🏋️‍♀️",whale:"🐳",whale2:"🐋",wheel_of_dharma:"☸️",wheelchair:"♿️",white_check_mark:"✅",white_circle:"⚪️",white_flag:"🏳️",white_flower:"💮",white_large_square:"⬜️",white_medium_small_square:"◽️",white_medium_square:"◻️",white_small_square:"▫️",white_square_button:"🔳",wilted_flower:"🥀",wind_chime:"🎐",wind_face:"🌬",wine_glass:"🍷",wink:"😉",wolf:"🐺",woman:"👩",woman_artist:"👩‍🎨",woman_astronaut:"👩‍🚀",woman_cartwheeling:"🤸‍♀️",woman_cook:"👩‍🍳",woman_facepalming:"🤦‍♀️",woman_factory_worker:"👩‍🏭",woman_farmer:"👩‍🌾",woman_firefighter:"👩‍🚒",woman_health_worker:"👩‍⚕️",woman_judge:"👩‍⚖️",woman_juggling:"🤹‍♀️",woman_mechanic:"👩‍🔧",woman_office_worker:"👩‍💼",woman_pilot:"👩‍✈️",woman_playing_handball:"🤾‍♀️",woman_playing_water_polo:"🤽‍♀️",woman_scientist:"👩‍🔬",woman_shrugging:"🤷‍♀️",woman_singer:"👩‍🎤",woman_student:"👩‍🎓",woman_teacher:"👩‍🏫",woman_technologist:"👩‍💻",woman_with_turban:"👳‍♀️",womans_clothes:"👚",womans_hat:"👒",women_wrestling:"🤼‍♀️",womens:"🚺",world_map:"🗺",worried:"😟",wrench:"🔧",writing_hand:"✍️",x:"❌",yellow_heart:"💛",yen:"💴",yin_yang:"☯️",yum:"😋",zap:"⚡️",zipper_mouth_face:"🤐",zzz:"💤",octocat:':octocat:',showdown:"S"},x.Converter=function(e){"use strict";var r,t,n={},i=[],l=[],o={},a=h,s={parsed:{},raw:"",format:""};for(r in e=e||{},p)p.hasOwnProperty(r)&&(n[r]=p[r]);if("object"!=typeof e)throw Error("Converter expects the passed parameter to be an object, but "+typeof e+" was passed instead.");for(t in e)e.hasOwnProperty(t)&&(n[t]=e[t]);function c(e,r){if(r=r||null,x.helper.isString(e)){if(r=e=x.helper.stdExtName(e),x.extensions[e]){console.warn("DEPRECATION WARNING: "+e+" is an old extension that uses a deprecated loading method.Please inform the developer that the extension should be updated!");var t=x.extensions[e],a=e;if("function"==typeof t&&(t=t(new x.Converter)),x.helper.isArray(t)||(t=[t]),!(a=g(t,a)).valid)throw Error(a.error);for(var n=0;n[ \t]+¨NBSP;<"),!r){if(!window||!window.document)throw new Error("HTMLParser is undefined. If in a webworker or nodejs environment, you need to provide a WHATWG DOM and HTML such as JSDOM");r=window.document}for(var r=r.createElement("div"),t=(r.innerHTML=e,{preList:function(e){for(var r=e.querySelectorAll("pre"),t=[],a=0;a'}else t.push(r[a].innerHTML),r[a].innerHTML="",r[a].setAttribute("prenum",a.toString());return t}(r)}),a=(!function e(r){for(var t=0;t? ?(['"].*['"])?\)$/m))a="";else if(!a){if(a="#"+(t=t||r.toLowerCase().replace(/ ?\n/g," ")),x.helper.isUndefined(l.gUrls[t]))return e;a=l.gUrls[t],x.helper.isUndefined(l.gTitles[t])||(o=l.gTitles[t])}return e='"}return e=(e=(e=(e=(e=l.converter._dispatch("anchors.before",e,i,l)).replace(/\[((?:\[[^\]]*]|[^\[\]])*)] ?(?:\n *)?\[(.*?)]()()()()/g,r)).replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]?<([^>]*)>(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,r)).replace(/\[((?:\[[^\]]*]|[^\[\]])*)]()[ \t]*\([ \t]??(?:[ \t]*((["'])([^"]*?)\5))?[ \t]?\)/g,r)).replace(/\[([^\[\]]+)]()()()()()/g,r),i.ghMentions&&(e=e.replace(/(^|\s)(\\)?(@([a-z\d]+(?:[a-z\d.-]+?[a-z\d]+)*))/gim,function(e,r,t,a,n){if("\\"===t)return r+a;if(!x.helper.isString(i.ghMentionsLink))throw new Error("ghMentionsLink option must be a string");t="";return r+'"+a+""})),e=l.converter._dispatch("anchors.after",e,i,l)});var i=/([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+?\.[^'">\s]+?)()(\1)?(?=\s|$)(?!["<>])/gi,l=/([*~_]+|\b)(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+?)([.!?,()\[\]])?(\1)?(?=\s|$)(?!["<>])/gi,c=/()<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)()>()/gi,m=/(^|\s)(?:mailto:)?([A-Za-z0-9!#$%&'*+-/=?^_`{|}~.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?=$|\s)/gim,f=/<()(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;x.subParser("autoLinks",function(e,r,t){"use strict";return e=(e=(e=t.converter._dispatch("autoLinks.before",e,r,t)).replace(c,s(r))).replace(f,o(r,t)),e=t.converter._dispatch("autoLinks.after",e,r,t)}),x.subParser("simplifiedAutoLinks",function(e,r,t){"use strict";return r.simplifiedAutoLink?(e=t.converter._dispatch("simplifiedAutoLinks.before",e,r,t),e=(e=r.excludeTrailingPunctuationFromURLs?e.replace(l,s(r)):e.replace(i,s(r))).replace(m,o(r,t)),t.converter._dispatch("simplifiedAutoLinks.after",e,r,t)):e}),x.subParser("blockGamut",function(e,r,t){"use strict";return e=t.converter._dispatch("blockGamut.before",e,r,t),e=x.subParser("blockQuotes")(e,r,t),e=x.subParser("headers")(e,r,t),e=x.subParser("horizontalRule")(e,r,t),e=x.subParser("lists")(e,r,t),e=x.subParser("codeBlocks")(e,r,t),e=x.subParser("tables")(e,r,t),e=x.subParser("hashHTMLBlocks")(e,r,t),e=x.subParser("paragraphs")(e,r,t),e=t.converter._dispatch("blockGamut.after",e,r,t)}),x.subParser("blockQuotes",function(e,r,t){"use strict";e=t.converter._dispatch("blockQuotes.before",e,r,t);var a=/(^ {0,3}>[ \t]?.+\n(.+\n)*\n*)+/gm;return r.splitAdjacentBlockquotes&&(a=/^ {0,3}>[\s\S]*?(?:\n\n)/gm),e=(e+="\n\n").replace(a,function(e){return e=(e=(e=e.replace(/^[ \t]*>[ \t]?/gm,"")).replace(/¨0/g,"")).replace(/^[ \t]+$/gm,""),e=x.subParser("githubCodeBlocks")(e,r,t),e=(e=(e=x.subParser("blockGamut")(e,r,t)).replace(/(^|\n)/g,"$1 ")).replace(/(\s*
[^\r]+?<\/pre>)/gm,function(e,r){return r.replace(/^  /gm,"¨0").replace(/¨0/g,"")}),x.subParser("hashBlock")("
\n"+e+"\n
",r,t)}),e=t.converter._dispatch("blockQuotes.after",e,r,t)}),x.subParser("codeBlocks",function(e,n,s){"use strict";e=s.converter._dispatch("codeBlocks.before",e,n,s);return e=(e=(e+="¨0").replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=¨0))/g,function(e,r,t){var a="\n",r=x.subParser("outdent")(r,n,s);return r=x.subParser("encodeCode")(r,n,s),r="
"+(r=(r=(r=x.subParser("detab")(r,n,s)).replace(/^\n+/g,"")).replace(/\n+$/g,""))+(a=n.omitExtraWLInCodeBlocks?"":a)+"
",x.subParser("hashBlock")(r,n,s)+t})).replace(/¨0/,""),e=s.converter._dispatch("codeBlocks.after",e,n,s)}),x.subParser("codeSpans",function(e,n,s){"use strict";return e=(e=void 0===(e=s.converter._dispatch("codeSpans.before",e,n,s))?"":e).replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,function(e,r,t,a){return a=(a=a.replace(/^([ \t]*)/g,"")).replace(/[ \t]*$/g,""),a=r+""+(a=x.subParser("encodeCode")(a,n,s))+"",a=x.subParser("hashHTMLSpans")(a,n,s)}),e=s.converter._dispatch("codeSpans.after",e,n,s)}),x.subParser("completeHTMLDocument",function(e,r,t){"use strict";if(!r.completeHTMLDocument)return e;e=t.converter._dispatch("completeHTMLDocument.before",e,r,t);var a,n="html",s="\n",o="",i='\n',l="",c="";for(a in void 0!==t.metadata.parsed.doctype&&(s="\n","html"!==(n=t.metadata.parsed.doctype.toString().toLowerCase())&&"html5"!==n||(i='')),t.metadata.parsed)if(t.metadata.parsed.hasOwnProperty(a))switch(a.toLowerCase()){case"doctype":break;case"title":o=""+t.metadata.parsed.title+"\n";break;case"charset":i="html"===n||"html5"===n?'\n':'\n';break;case"language":case"lang":l=' lang="'+t.metadata.parsed[a]+'"',c+='\n';break;default:c+='\n'}return e=s+"\n\n"+o+i+c+"\n\n"+e.trim()+"\n\n",e=t.converter._dispatch("completeHTMLDocument.after",e,r,t)}),x.subParser("detab",function(e,r,t){"use strict";return e=(e=(e=(e=(e=(e=t.converter._dispatch("detab.before",e,r,t)).replace(/\t(?=\t)/g," ")).replace(/\t/g,"¨A¨B")).replace(/¨B(.+?)¨A/g,function(e,r){for(var t=r,a=4-t.length%4,n=0;n/g,">"),e=t.converter._dispatch("encodeAmpsAndAngles.after",e,r,t)}),x.subParser("encodeBackslashEscapes",function(e,r,t){"use strict";return e=(e=(e=t.converter._dispatch("encodeBackslashEscapes.before",e,r,t)).replace(/\\(\\)/g,x.helper.escapeCharactersCallback)).replace(/\\([`*_{}\[\]()>#+.!~=|:-])/g,x.helper.escapeCharactersCallback),e=t.converter._dispatch("encodeBackslashEscapes.after",e,r,t)}),x.subParser("encodeCode",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("encodeCode.before",e,r,t)).replace(/&/g,"&").replace(//g,">").replace(/([*_{}\[\]\\=~-])/g,x.helper.escapeCharactersCallback),e=t.converter._dispatch("encodeCode.after",e,r,t)}),x.subParser("escapeSpecialCharsWithinTagAttributes",function(e,r,t){"use strict";return e=(e=(e=t.converter._dispatch("escapeSpecialCharsWithinTagAttributes.before",e,r,t)).replace(/<\/?[a-z\d_:-]+(?:[\s]+[\s\S]+?)?>/gi,function(e){return e.replace(/(.)<\/?code>(?=.)/g,"$1`").replace(/([\\`*_~=|])/g,x.helper.escapeCharactersCallback)})).replace(/-]|-[^>])(?:[^-]|-[^-])*)--)>/gi,function(e){return e.replace(/([\\`*_~=|])/g,x.helper.escapeCharactersCallback)}),e=t.converter._dispatch("escapeSpecialCharsWithinTagAttributes.after",e,r,t)}),x.subParser("githubCodeBlocks",function(e,s,o){"use strict";return s.ghCodeBlocks?(e=o.converter._dispatch("githubCodeBlocks.before",e,s,o),e=(e=(e+="¨0").replace(/(?:^|\n)(?: {0,3})(```+|~~~+)(?: *)([^\s`~]*)\n([\s\S]*?)\n(?: {0,3})\1/g,function(e,r,t,a){var n=s.omitExtraWLInCodeBlocks?"":"\n";return a=x.subParser("encodeCode")(a,s,o),a="
"+(a=(a=(a=x.subParser("detab")(a,s,o)).replace(/^\n+/g,"")).replace(/\n+$/g,""))+n+"
",a=x.subParser("hashBlock")(a,s,o),"\n\n¨G"+(o.ghCodeBlocks.push({text:e,codeblock:a})-1)+"G\n\n"})).replace(/¨0/,""),o.converter._dispatch("githubCodeBlocks.after",e,s,o)):e}),x.subParser("hashBlock",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("hashBlock.before",e,r,t)).replace(/(^\n+|\n+$)/g,""),e="\n\n¨K"+(t.gHtmlBlocks.push(e)-1)+"K\n\n",e=t.converter._dispatch("hashBlock.after",e,r,t)}),x.subParser("hashCodeTags",function(e,n,s){"use strict";e=s.converter._dispatch("hashCodeTags.before",e,n,s);return e=x.helper.replaceRecursiveRegExp(e,function(e,r,t,a){t=t+x.subParser("encodeCode")(r,n,s)+a;return"¨C"+(s.gHtmlSpans.push(t)-1)+"C"},"]*>","","gim"),e=s.converter._dispatch("hashCodeTags.after",e,n,s)}),x.subParser("hashElement",function(e,r,t){"use strict";return function(e,r){return r=(r=(r=r.replace(/\n\n/g,"\n")).replace(/^\n/,"")).replace(/\n+$/g,""),r="\n\n¨K"+(t.gHtmlBlocks.push(r)-1)+"K\n\n"}}),x.subParser("hashHTMLBlocks",function(e,r,n){"use strict";e=n.converter._dispatch("hashHTMLBlocks.before",e,r,n);function t(e,r,t,a){return-1!==t.search(/\bmarkdown\b/)&&(e=t+n.converter.makeHtml(r)+a),"\n\n¨K"+(n.gHtmlBlocks.push(e)-1)+"K\n\n"}var a=["pre","div","h1","h2","h3","h4","h5","h6","blockquote","table","dl","ol","ul","script","noscript","form","fieldset","iframe","math","style","section","header","footer","nav","article","aside","address","audio","canvas","figure","hgroup","output","video","p"];r.backslashEscapesHTMLTags&&(e=e.replace(/\\<(\/?[^>]+?)>/g,function(e,r){return"<"+r+">"}));for(var s=0;s]*>)","im"),i="<"+a[s]+"\\b[^>]*>",l="";-1!==(c=x.helper.regexIndexOf(e,o));){var c=x.helper.splitAtIndex(e,c),u=x.helper.replaceRecursiveRegExp(c[1],t,i,l,"im");if(u===c[1])break;e=c[0].concat(u)}return e=e.replace(/(\n {0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,x.subParser("hashElement")(e,r,n)),e=(e=x.helper.replaceRecursiveRegExp(e,function(e){return"\n\n¨K"+(n.gHtmlBlocks.push(e)-1)+"K\n\n"},"^ {0,3}\x3c!--","--\x3e","gm")).replace(/(?:\n\n)( {0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,x.subParser("hashElement")(e,r,n)),e=n.converter._dispatch("hashHTMLBlocks.after",e,r,n)}),x.subParser("hashHTMLSpans",function(e,r,t){"use strict";function a(e){return"¨C"+(t.gHtmlSpans.push(e)-1)+"C"}return e=(e=(e=(e=(e=t.converter._dispatch("hashHTMLSpans.before",e,r,t)).replace(/<[^>]+?\/>/gi,a)).replace(/<([^>]+?)>[\s\S]*?<\/\1>/g,a)).replace(/<([^>]+?)\s[^>]+?>[\s\S]*?<\/\1>/g,a)).replace(/<[^>]+?>/gi,a),e=t.converter._dispatch("hashHTMLSpans.after",e,r,t)}),x.subParser("unhashHTMLSpans",function(e,r,t){"use strict";e=t.converter._dispatch("unhashHTMLSpans.before",e,r,t);for(var a=0;a]*>\\s*]*>","^ {0,3}\\s*
","gim"),e=s.converter._dispatch("hashPreCodeTags.after",e,n,s)}),x.subParser("headers",function(e,n,s){"use strict";e=s.converter._dispatch("headers.before",e,n,s);var o=isNaN(parseInt(n.headerLevelStart))?1:parseInt(n.headerLevelStart),r=n.smoothLivePreview?/^(.+)[ \t]*\n={2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n=+[ \t]*\n+/gm,t=n.smoothLivePreview?/^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm:/^(.+)[ \t]*\n-+[ \t]*\n+/gm,r=(e=(e=e.replace(r,function(e,r){var t=x.subParser("spanGamut")(r,n,s),r=n.noHeaderId?"":' id="'+i(r)+'"',r=""+t+"";return x.subParser("hashBlock")(r,n,s)})).replace(t,function(e,r){var t=x.subParser("spanGamut")(r,n,s),r=n.noHeaderId?"":' id="'+i(r)+'"',a=o+1,r=""+t+"";return x.subParser("hashBlock")(r,n,s)}),n.requireSpaceBeforeHeadingText?/^(#{1,6})[ \t]+(.+?)[ \t]*#*\n+/gm:/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm);function i(e){var r=e=n.customizedHeaderId&&(r=e.match(/\{([^{]+?)}\s*$/))&&r[1]?r[1]:e,e=x.helper.isString(n.prefixHeaderId)?n.prefixHeaderId:!0===n.prefixHeaderId?"section-":"";return n.rawPrefixHeaderId||(r=e+r),r=(n.ghCompatibleHeaderId?r.replace(/ /g,"-").replace(/&/g,"").replace(/¨T/g,"").replace(/¨D/g,"").replace(/[&+$,\/:;=?@"#{}|^¨~\[\]`\\*)(%.!'<>]/g,""):n.rawHeaderId?r.replace(/ /g,"-").replace(/&/g,"&").replace(/¨T/g,"¨").replace(/¨D/g,"$").replace(/["']/g,"-"):r.replace(/[^\w]/g,"")).toLowerCase(),n.rawPrefixHeaderId&&(r=e+r),s.hashLinkCounts[r]?r=r+"-"+s.hashLinkCounts[r]++:s.hashLinkCounts[r]=1,r}return e=e.replace(r,function(e,r,t){var a=t,a=(n.customizedHeaderId&&(a=t.replace(/\s?\{([^{]+?)}\s*$/,"")),x.subParser("spanGamut")(a,n,s)),t=n.noHeaderId?"":' id="'+i(t)+'"',r=o-1+r.length,t=""+a+"";return x.subParser("hashBlock")(t,n,s)}),e=s.converter._dispatch("headers.after",e,n,s)}),x.subParser("horizontalRule",function(e,r,t){"use strict";e=t.converter._dispatch("horizontalRule.before",e,r,t);var a=x.subParser("hashBlock")("
",r,t);return e=(e=(e=e.replace(/^ {0,2}( ?-){3,}[ \t]*$/gm,a)).replace(/^ {0,2}( ?\*){3,}[ \t]*$/gm,a)).replace(/^ {0,2}( ?_){3,}[ \t]*$/gm,a),e=t.converter._dispatch("horizontalRule.after",e,r,t)}),x.subParser("images",function(e,r,d){"use strict";function l(e,r,t,a,n,s,o,i){var l=d.gUrls,c=d.gTitles,u=d.gDimensions;if(t=t.toLowerCase(),i=i||"",-1? ?(['"].*['"])?\)$/m))a="";else if(""===a||null===a){if(a="#"+(t=""!==t&&null!==t?t:r.toLowerCase().replace(/ ?\n/g," ")),x.helper.isUndefined(l[t]))return e;a=l[t],x.helper.isUndefined(c[t])||(i=c[t]),x.helper.isUndefined(u[t])||(n=u[t].width,s=u[t].height)}r=r.replace(/"/g,""").replace(x.helper.regexes.asteriskDashAndColon,x.helper.escapeCharactersCallback);e=''+r+'"}return e=(e=(e=(e=(e=(e=d.converter._dispatch("images.before",e,r,d)).replace(/!\[([^\]]*?)] ?(?:\n *)?\[([\s\S]*?)]()()()()()/g,l)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,function(e,r,t,a,n,s,o,i){return l(e,r,t,a=a.replace(/\s/g,""),n,s,0,i)})).replace(/!\[([^\]]*?)][ \t]*()\([ \t]?<([^>]*)>(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(?:(["'])([^"]*?)\6))?[ \t]?\)/g,l)).replace(/!\[([^\]]*?)][ \t]*()\([ \t]??(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(["'])([^"]*?)\6)?[ \t]?\)/g,l)).replace(/!\[([^\[\]]+)]()()()()()/g,l),e=d.converter._dispatch("images.after",e,r,d)}),x.subParser("italicsAndBold",function(e,r,t){"use strict";return e=t.converter._dispatch("italicsAndBold.before",e,r,t),e=r.literalMidWordUnderscores?(e=(e=e.replace(/\b___(\S[\s\S]*?)___\b/g,function(e,r){return""+r+""})).replace(/\b__(\S[\s\S]*?)__\b/g,function(e,r){return""+r+""})).replace(/\b_(\S[\s\S]*?)_\b/g,function(e,r){return""+r+""}):(e=(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,r){return/\S$/.test(r)?""+r+"":e})).replace(/__(\S[\s\S]*?)__/g,function(e,r){return/\S$/.test(r)?""+r+"":e})).replace(/_([^\s_][\s\S]*?)_/g,function(e,r){return/\S$/.test(r)?""+r+"":e}),e=r.literalMidWordAsterisks?(e=(e=e.replace(/([^*]|^)\B\*\*\*(\S[\s\S]*?)\*\*\*\B(?!\*)/g,function(e,r,t){return r+""+t+""})).replace(/([^*]|^)\B\*\*(\S[\s\S]*?)\*\*\B(?!\*)/g,function(e,r,t){return r+""+t+""})).replace(/([^*]|^)\B\*(\S[\s\S]*?)\*\B(?!\*)/g,function(e,r,t){return r+""+t+""}):(e=(e=e.replace(/\*\*\*(\S[\s\S]*?)\*\*\*/g,function(e,r){return/\S$/.test(r)?""+r+"":e})).replace(/\*\*(\S[\s\S]*?)\*\*/g,function(e,r){return/\S$/.test(r)?""+r+"":e})).replace(/\*([^\s*][\s\S]*?)\*/g,function(e,r){return/\S$/.test(r)?""+r+"":e}),e=t.converter._dispatch("italicsAndBold.after",e,r,t)}),x.subParser("lists",function(e,d,c){"use strict";function p(e,r){c.gListLevel++,e=e.replace(/\n{2,}$/,"\n");var t=/(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0| {0,3}([*+-]|\d+[.])[ \t]+))/gm,l=/\n[ \t]*\n(?!¨0)/.test(e+="¨0");return d.disableForced4SpacesIndentedSublists&&(t=/(\n)?(^ {0,3})([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(¨0|\2([*+-]|\d+[.])[ \t]+))/gm),e=(e=e.replace(t,function(e,r,t,a,n,s,o){o=o&&""!==o.trim();var n=x.subParser("outdent")(n,d,c),i="";return s&&d.tasklists&&(i=' class="task-list-item" style="list-style-type: none;"',n=n.replace(/^[ \t]*\[(x|X| )?]/m,function(){var e='"+(n=(n=r||-1\n"})).replace(/¨0/g,""),c.gListLevel--,e=r?e.replace(/\s+$/,""):e}function h(e,r){if("ol"===r){r=e.match(/^ *(\d+)\./);if(r&&"1"!==r[1])return' start="'+r[1]+'"'}return""}function n(n,s,o){var e,i=d.disableForced4SpacesIndentedSublists?/^ ?\d+\.[ \t]/gm:/^ {0,3}\d+\.[ \t]/gm,l=d.disableForced4SpacesIndentedSublists?/^ ?[*+-][ \t]/gm:/^ {0,3}[*+-][ \t]/gm,c="ul"===s?i:l,u="";return-1!==n.search(c)?function e(r){var t=r.search(c),a=h(n,s);-1!==t?(u+="\n\n<"+s+a+">\n"+p(r.slice(0,t),!!o)+"\n",c="ul"===(s="ul"===s?"ol":"ul")?i:l,e(r.slice(t))):u+="\n\n<"+s+a+">\n"+p(r,!!o)+"\n"}(n):(e=h(n,s),u="\n\n<"+s+e+">\n"+p(n,!!o)+"\n"),u}return e=c.converter._dispatch("lists.before",e,d,c),e+="¨0",e=(e=c.gListLevel?e.replace(/^(( {0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(¨0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm,function(e,r,t){return n(r,-1"),i+="

",n.push(i))}for(s=n.length,o=0;o]*>\s*]*>/.test(c)&&(u=!0)}n[o]=c}return e=(e=(e=n.join("\n")).replace(/^\n+/g,"")).replace(/\n+$/g,""),t.converter._dispatch("paragraphs.after",e,r,t)}),x.subParser("runExtension",function(e,r,t,a){"use strict";return e.filter?r=e.filter(r,a.converter,t):e.regex&&((a=e.regex)instanceof RegExp||(a=new RegExp(a,"g")),r=r.replace(a,e.replace)),r}),x.subParser("spanGamut",function(e,r,t){"use strict";return e=t.converter._dispatch("spanGamut.before",e,r,t),e=x.subParser("codeSpans")(e,r,t),e=x.subParser("escapeSpecialCharsWithinTagAttributes")(e,r,t),e=x.subParser("encodeBackslashEscapes")(e,r,t),e=x.subParser("images")(e,r,t),e=x.subParser("anchors")(e,r,t),e=x.subParser("autoLinks")(e,r,t),e=x.subParser("simplifiedAutoLinks")(e,r,t),e=x.subParser("emoji")(e,r,t),e=x.subParser("underline")(e,r,t),e=x.subParser("italicsAndBold")(e,r,t),e=x.subParser("strikethrough")(e,r,t),e=x.subParser("ellipsis")(e,r,t),e=x.subParser("hashHTMLSpans")(e,r,t),e=x.subParser("encodeAmpsAndAngles")(e,r,t),r.simpleLineBreaks?/\n\n¨K/.test(e)||(e=e.replace(/\n+/g,"
\n")):e=e.replace(/ +\n/g,"
\n"),e=t.converter._dispatch("spanGamut.after",e,r,t)}),x.subParser("strikethrough",function(e,t,a){"use strict";return t.strikethrough&&(e=(e=a.converter._dispatch("strikethrough.before",e,t,a)).replace(/(?:~){2}([\s\S]+?)(?:~){2}/g,function(e,r){return r=r,""+(r=t.simplifiedAutoLink?x.subParser("simplifiedAutoLinks")(r,t,a):r)+""}),e=a.converter._dispatch("strikethrough.after",e,t,a)),e}),x.subParser("stripLinkDefinitions",function(i,l,c){"use strict";function e(e,r,t,a,n,s,o){return r=r.toLowerCase(),i.toLowerCase().split(r).length-1<2?e:(t.match(/^data:.+?\/.+?;base64,/)?c.gUrls[r]=t.replace(/\s/g,""):c.gUrls[r]=x.subParser("encodeAmpsAndAngles")(t,l,c),s?s+o:(o&&(c.gTitles[r]=o.replace(/"|'/g,""")),l.parseImgDimensions&&a&&n&&(c.gDimensions[r]={width:a,height:n}),""))}return i=(i=(i=(i+="¨0").replace(/^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n\n|(?=¨0)|(?=\n\[))/gm,e)).replace(/^ {0,3}\[([^\]]+)]:[ \t]*\n?[ \t]*\s]+)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=¨0))/gm,e)).replace(/¨0/,"")}),x.subParser("tables",function(e,y,P){"use strict";if(!y.tables)return e;function r(e){for(var r=e.split("\n"),t=0;t"+(n=x.subParser("spanGamut")(n,y,P))+"\n"));for(t=0;t"+x.subParser("spanGamut")(i,y,P)+"\n"));h.push(_)}for(var m=d,f=h,b="\n\n\n",w=m.length,k=0;k\n\n\n",k=0;k\n";for(var v=0;v\n"}return b+="\n
\n"}return e=(e=(e=(e=P.converter._dispatch("tables.before",e,y,P)).replace(/\\(\|)/g,x.helper.escapeCharactersCallback)).replace(/^ {0,3}\|?.+\|.+\n {0,3}\|?[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:[-=]){2,}[\s\S]+?(?:\n\n|¨0)/gm,r)).replace(/^ {0,3}\|.+\|[ \t]*\n {0,3}\|[ \t]*:?[ \t]*(?:[-=]){2,}[ \t]*:?[ \t]*\|[ \t]*\n( {0,3}\|.+\|[ \t]*\n)*(?:\n|¨0)/gm,r),e=P.converter._dispatch("tables.after",e,y,P)}),x.subParser("underline",function(e,r,t){"use strict";return r.underline?(e=t.converter._dispatch("underline.before",e,r,t),e=(e=r.literalMidWordUnderscores?(e=e.replace(/\b___(\S[\s\S]*?)___\b/g,function(e,r){return""+r+""})).replace(/\b__(\S[\s\S]*?)__\b/g,function(e,r){return""+r+""}):(e=e.replace(/___(\S[\s\S]*?)___/g,function(e,r){return/\S$/.test(r)?""+r+"":e})).replace(/__(\S[\s\S]*?)__/g,function(e,r){return/\S$/.test(r)?""+r+"":e})).replace(/(_)/g,x.helper.escapeCharactersCallback),t.converter._dispatch("underline.after",e,r,t)):e}),x.subParser("unescapeSpecialChars",function(e,r,t){"use strict";return e=(e=t.converter._dispatch("unescapeSpecialChars.before",e,r,t)).replace(/¨E(\d+)E/g,function(e,r){r=parseInt(r);return String.fromCharCode(r)}),e=t.converter._dispatch("unescapeSpecialChars.after",e,r,t)}),x.subParser("makeMarkdown.blockquote",function(e,r){"use strict";var t="";if(e.hasChildNodes())for(var a=e.childNodes,n=a.length,s=0;s ")}),x.subParser("makeMarkdown.codeBlock",function(e,r){"use strict";var t=e.getAttribute("language"),e=e.getAttribute("precodenum");return"```"+t+"\n"+r.preList[e]+"\n```"}),x.subParser("makeMarkdown.codeSpan",function(e){"use strict";return"`"+e.innerHTML+"`"}),x.subParser("makeMarkdown.emphasis",function(e,r){"use strict";var t="";if(e.hasChildNodes()){t+="*";for(var a=e.childNodes,n=a.length,s=0;s",e.hasAttribute("width")&&e.hasAttribute("height")&&(r+=" ="+e.getAttribute("width")+"x"+e.getAttribute("height")),e.hasAttribute("title")&&(r+=' "'+e.getAttribute("title")+'"'),r+=")"),r}),x.subParser("makeMarkdown.links",function(e,r){"use strict";var t="";if(e.hasChildNodes()&&e.hasAttribute("href")){for(var a=e.childNodes,n=a.length,t="[",s=0;s"),e.hasAttribute("title")&&(t+=' "'+e.getAttribute("title")+'"'),t+=")"}return t}),x.subParser("makeMarkdown.list",function(e,r,t){"use strict";var a="";if(!e.hasChildNodes())return"";for(var n=e.childNodes,s=n.length,o=e.getAttribute("start")||1,i=0;i"+r.preList[e]+""}),x.subParser("makeMarkdown.strikethrough",function(e,r){"use strict";var t="";if(e.hasChildNodes()){t+="~~";for(var a=e.childNodes,n=a.length,s=0;str>th"),s=e.querySelectorAll("tbody>tr"),o=0;o/g,"\\$1>")).replace(/^#/gm,"\\#")).replace(/^(\s*)([-=]{3,})(\s*)$/,"$1\\$2$3")).replace(/^( {0,3}\d+)\./gm,"$1\\.")).replace(/^( {0,3})([+-])/gm,"$1\\$2")).replace(/]([\s]*)\(/g,"\\]$1\\(")).replace(/^ {0,3}\[([\S \t]*?)]:/gm,"\\[$1]:")});"function"==typeof define&&define.amd?define(function(){"use strict";return x}):"undefined"!=typeof module&&module.exports?module.exports=x:this.showdown=x}.call(this); +//# sourceMappingURL=showdown.min.js.map \ No newline at end of file diff --git a/app/src/main/assets/www/highlight/styles/github-dark.css b/app/src/main/assets/www/highlight/styles/github-dark.css new file mode 100644 index 000000000..1e37b83bb --- /dev/null +++ b/app/src/main/assets/www/highlight/styles/github-dark.css @@ -0,0 +1,122 @@ +pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em +} +code.hljs { + padding: 3px 5px +} +* { + margin: 0; + padding: 0; +} +/*! + Theme: GitHub Dark + Description: Dark theme as seen on github.com + Author: github.com + Maintainer: @Hirse + Updated: 2021-05-15 + + Outdated base version: https://github.com/primer/github-syntax-dark + Current colors taken from GitHub's CSS +*/ +.hljs { + color: #c9d1d9; + background: #0d1117 +} +.hljs-doctag, +.hljs-keyword, +.hljs-meta .hljs-keyword, +.hljs-template-tag, +.hljs-template-variable, +.hljs-type, +.hljs-variable.language_ { + /* prettylights-syntax-keyword */ + color: #ff7b72 +} +.hljs-title, +.hljs-title.class_, +.hljs-title.class_.inherited__, +.hljs-title.function_ { + /* prettylights-syntax-entity */ + color: #d2a8ff +} +.hljs-attr, +.hljs-attribute, +.hljs-literal, +.hljs-meta, +.hljs-number, +.hljs-operator, +.hljs-variable, +.hljs-selector-attr, +.hljs-selector-class, +.hljs-selector-id { + /* prettylights-syntax-constant */ + color: #79c0ff +} +.hljs-regexp, +.hljs-string, +.hljs-meta .hljs-string { + /* prettylights-syntax-string */ + color: #a5d6ff +} +.hljs-built_in, +.hljs-symbol { + /* prettylights-syntax-variable */ + color: #ffa657 +} +.hljs-comment, +.hljs-code, +.hljs-formula { + /* prettylights-syntax-comment */ + color: #8b949e +} +.hljs-name, +.hljs-quote, +.hljs-selector-tag, +.hljs-selector-pseudo { + /* prettylights-syntax-entity-tag */ + color: #7ee787 +} +.hljs-subst { + /* prettylights-syntax-storage-modifier-import */ + color: #c9d1d9 +} +.hljs-section { + /* prettylights-syntax-markup-heading */ + color: #1f6feb; + font-weight: bold +} +.hljs-bullet { + /* prettylights-syntax-markup-list */ + color: #f2cc60 +} +.hljs-emphasis { + /* prettylights-syntax-markup-italic */ + color: #c9d1d9; + font-style: italic +} +.hljs-strong { + /* prettylights-syntax-markup-bold */ + color: #c9d1d9; + font-weight: bold +} +.hljs-addition { + /* prettylights-syntax-markup-inserted */ + color: #aff5b4; + background-color: #033a16 +} +.hljs-deletion { + /* prettylights-syntax-markup-deleted */ + color: #ffdcd7; + background-color: #67060c +} +.hljs-char.escape_, +.hljs-link, +.hljs-params, +.hljs-property, +.hljs-punctuation, +.hljs-tag { + /* purposely ignored */ + +} \ No newline at end of file diff --git a/app/src/main/assets/www/highlight/styles/github.css b/app/src/main/assets/www/highlight/styles/github.css new file mode 100644 index 000000000..49a2a0540 --- /dev/null +++ b/app/src/main/assets/www/highlight/styles/github.css @@ -0,0 +1,122 @@ +pre code.hljs { + display: block; + overflow-x: auto; + padding: 1em +} +code.hljs { + padding: 3px 5px +} +* { + margin: 0; + padding: 0; +} +/*! + Theme: GitHub + Description: Light theme as seen on github.com + Author: github.com + Maintainer: @Hirse + Updated: 2021-05-15 + + Outdated base version: https://github.com/primer/github-syntax-light + Current colors taken from GitHub's CSS +*/ +.hljs { + color: #24292e; + background: #ffffff +} +.hljs-doctag, +.hljs-keyword, +.hljs-meta .hljs-keyword, +.hljs-template-tag, +.hljs-template-variable, +.hljs-type, +.hljs-variable.language_ { + /* prettylights-syntax-keyword */ + color: #d73a49 +} +.hljs-title, +.hljs-title.class_, +.hljs-title.class_.inherited__, +.hljs-title.function_ { + /* prettylights-syntax-entity */ + color: #6f42c1 +} +.hljs-attr, +.hljs-attribute, +.hljs-literal, +.hljs-meta, +.hljs-number, +.hljs-operator, +.hljs-variable, +.hljs-selector-attr, +.hljs-selector-class, +.hljs-selector-id { + /* prettylights-syntax-constant */ + color: #005cc5 +} +.hljs-regexp, +.hljs-string, +.hljs-meta .hljs-string { + /* prettylights-syntax-string */ + color: #032f62 +} +.hljs-built_in, +.hljs-symbol { + /* prettylights-syntax-variable */ + color: #e36209 +} +.hljs-comment, +.hljs-code, +.hljs-formula { + /* prettylights-syntax-comment */ + color: #6a737d +} +.hljs-name, +.hljs-quote, +.hljs-selector-tag, +.hljs-selector-pseudo { + /* prettylights-syntax-entity-tag */ + color: #22863a +} +.hljs-subst { + /* prettylights-syntax-storage-modifier-import */ + color: #24292e +} +.hljs-section { + /* prettylights-syntax-markup-heading */ + color: #005cc5; + font-weight: bold +} +.hljs-bullet { + /* prettylights-syntax-markup-list */ + color: #735c0f +} +.hljs-emphasis { + /* prettylights-syntax-markup-italic */ + color: #24292e; + font-style: italic +} +.hljs-strong { + /* prettylights-syntax-markup-bold */ + color: #24292e; + font-weight: bold +} +.hljs-addition { + /* prettylights-syntax-markup-inserted */ + color: #22863a; + background-color: #f0fff4 +} +.hljs-deletion { + /* prettylights-syntax-markup-deleted */ + color: #b31d28; + background-color: #ffeef0 +} +.hljs-char.escape_, +.hljs-link, +.hljs-params, +.hljs-property, +.hljs-punctuation, +.hljs-tag { + /* purposely ignored */ + +} \ No newline at end of file diff --git a/app/src/main/assets/www/highlight/styles/info.css b/app/src/main/assets/www/highlight/styles/info.css new file mode 100644 index 000000000..39383a5d7 --- /dev/null +++ b/app/src/main/assets/www/highlight/styles/info.css @@ -0,0 +1,68 @@ +html { + -webkit-text-size-adjust: 100%; + font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"; +} + +body { + line-height: 1.5; + padding: 1em; + word-wrap: break-word; +} + +h1, h2, h3, h4, h5, h6 { + margin-top: 24px; + margin-bottom: 16px; + font-weight: 600; + line-height: 1.25; +} + +h1 { + margin-top: 6px; + padding-bottom: .3em; + font-size: 2em; + border-bottom: 1px solid hsla(210,18%,87%,1); +} + +h2 { + padding-bottom: .3em; + font-size: 1.5em; + border-bottom: 1px solid hsla(210,18%,87%,1); +} + +ol, ul { + margin: 0; + padding: 0; + margin-left: 1.5rem; + margin-bottom: 1rem; + list-style-position: outside; + line-height: 1.6; +} + +a { + color: #0E0EFF; +} + +code { + font-family: ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace; + padding: 0.2em 0.4em; + margin: 0; + font-size: 85%; + background-color: rgba(99,110,123,0.1); + border-radius: 6px; +} + +/* Dark Mode */ +@media (prefers-color-scheme: dark) { + html { + background-color: #1F1F24; + color: #FFFFFF; + } + + code { + background-color: rgba(110,118,129,0.4); + } + + a { + color: #5482FF; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/MainActivity.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/MainActivity.kt new file mode 100644 index 000000000..e48103c5f --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/MainActivity.kt @@ -0,0 +1,43 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import com.esri.arcgismaps.kotlin.sampleviewer.navigation.NavGraph +import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + setContent { + setContent { + + SampleAppTheme { + Surface(color = MaterialTheme.colorScheme.background) { + NavGraph() + } + } + } + } + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/SampleViewerApplication.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/SampleViewerApplication.kt new file mode 100644 index 000000000..b7405d9e2 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/SampleViewerApplication.kt @@ -0,0 +1,18 @@ +package com.esri.arcgismaps.kotlin.sampleviewer + +import android.app.Application +import com.esri.arcgismaps.kotlin.sampleviewer.model.DefaultSampleInfoRepository +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class SampleViewerApplication : Application() { + + override fun onCreate() { + super.onCreate() + CoroutineScope(Dispatchers.IO).launch { + // Load the repository once at app launch + DefaultSampleInfoRepository.load(applicationContext) + } + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/Category.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/Category.kt new file mode 100644 index 000000000..5aa187103 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/Category.kt @@ -0,0 +1,93 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model + +import com.esri.arcgismaps.kotlin.sampleviewer.R + +/** + * Represents a sample category. + */ +data class Category( + val title: SampleCategory, + val icon: Int, + val backgroundImage: Int +) { + companion object { + val SAMPLE_CATEGORIES = listOf( + Category( + SampleCategory.ANALYSIS, + R.drawable.ic_analysis, + R.drawable.analysis_background, + ), + Category( + SampleCategory.AUGMENTED_REALITY, + R.drawable.ic_augmented_reality, + R.drawable.augmented_reality_background, + ), + Category( + SampleCategory.CLOUD_AND_PORTAL, + R.drawable.ic_cloud, + R.drawable.cloud_background, + ), + Category( + SampleCategory.EDIT_AND_MANAGE_DATA, + R.drawable.ic_manage_data, + R.drawable.manage_data_background, + ), + Category( + SampleCategory.LAYERS, + R.drawable.ic_layers, + R.drawable.layers_background, + ), + Category( + SampleCategory.MAPS, + R.drawable.ic_map, + R.drawable.maps_and_scenes_background, + ), + Category( + SampleCategory.ROUTING_AND_LOGISTICS, + R.drawable.ic_routing_and_logistics, + R.drawable.routing_and_logistics_background, + ), + Category( + SampleCategory.SCENES, + R.drawable.ic_scenes, + R.drawable.scenes_background, + ), + Category( + SampleCategory.SEARCH_AND_QUERY, + R.drawable.ic_search_and_query, + R.drawable.search_and_query_background, + ), + Category( + SampleCategory.UTILITY_NETWORKS, + R.drawable.ic_utility, + R.drawable.utility_background, + ), + Category( + SampleCategory.VISUALIZATION, + R.drawable.ic_visualization, + R.drawable.visualization_background, + ), + Category( + SampleCategory.FAVORITES, + R.drawable.ic_favorite_selected, + R.drawable.maps_and_scenes_background, + ), + ) + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/CodeFile.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/CodeFile.kt new file mode 100644 index 000000000..5ee355fd7 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/CodeFile.kt @@ -0,0 +1,28 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model + +import kotlinx.serialization.Serializable + +/** + * Represents a single code file in a sample. + */ +@Serializable +data class CodeFile( + val name: String, + val code: String +) diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/DefaultSampleInfoRepository.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/DefaultSampleInfoRepository.kt new file mode 100644 index 000000000..559983f9d --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/DefaultSampleInfoRepository.kt @@ -0,0 +1,120 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model + +import android.content.Context +import android.util.Log +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample.Companion.loadActivityPath +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample.Companion.loadReadMe +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample.Companion.loadScreenshot +import com.esri.arcgismaps.kotlin.sampleviewer.model.room.AppDatabase +import com.esri.arcgismaps.kotlin.sampleviewer.model.room.Converters +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import kotlinx.serialization.json.Json +import java.util.concurrent.atomic.AtomicBoolean + +/** + * The single source of truth for app wide data. It reads the sample metadata to create as list of + * [Sample] objects and populates the database used for search. + * It also provides functions to get samples by category, name, or all samples. + */ +object DefaultSampleInfoRepository : SampleInfoRepository { + + private val isInitialized = AtomicBoolean(false) + + private val json = Json { ignoreUnknownKeys = true } + + private val sampleList = mutableListOf() + + /** + * Load the sample metadata from the metadata folder in the assets directory and updates sampleList + * of [Sample] objects. + */ + suspend fun load(context: Context) { + if (isInitialized.compareAndSet(false, true)) { + // Iterate through the metadata folder for all metadata files + + context.assets.list("samples")?.forEach { samplePath -> + // Get this metadata files as a string + context.assets.open("samples/$samplePath/README.metadata.json").use { inputStream -> + val metadataJsonString = inputStream.bufferedReader().use { it.readText() } + try { + val metadata = json.decodeFromString(metadataJsonString) + + // Create and add a new sample metadata data class object to the list + val sample = Sample( + name = metadata.title, + codeFiles = Sample.loadCodeFiles( + context = context, + sampleName = metadata.title + ), + url = "https://developers.arcgis.com/kotlin/sample-code/" + + metadata.title.replace(" ", "-").lowercase(), + readMe = loadReadMe( + context = context, + sampleName = samplePath + ), + screenshotURL = loadScreenshot( + sampleName = metadata.title, + imageArray = metadata.imagePaths + ), + mainActivity = loadActivityPath( + codePaths = metadata.codePaths + ), + metadata = metadata, + ) + // Add the new sample to the list + sampleList.add(sample) + } catch (e: Exception) { + Log.e( + DefaultSampleInfoRepository::class.simpleName, + "Exception at $samplePath: " + e.printStackTrace() + ) + } + } + } + withContext(Dispatchers.IO) { + // Populates the Room SQL database + populateDatabase(context) + } + } + } + + /** + * Populates the Room SQL database with all samples and sample info + */ + private suspend fun populateDatabase(context: Context) { + val sampleEntities = sampleList.map { Converters().convertToEntity(sample = it) } + AppDatabase.getDatabase(context).clearAllTables() + AppDatabase.getDatabase(context).sampleDao().insertAll(samples = sampleEntities) + } + + /** + * Get a sample by its name. Either the formal name or title. + */ + override fun getSampleByName(sampleName: String): Sample { + return sampleList.first { it.metadata.formalName == sampleName || it.metadata.title == sampleName } + } + + /** + * Get a list of samples for the given [SampleCategory]. + */ + override fun getSamplesInCategory(sampleCategory: SampleCategory): List { + return sampleList.filter { it.metadata.sampleCategory == sampleCategory } + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/Sample.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/Sample.kt new file mode 100644 index 000000000..45cc14542 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/Sample.kt @@ -0,0 +1,165 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model + +import android.app.Activity +import android.content.Context +import android.content.ContextWrapper +import android.content.Intent +import com.arcgismaps.ArcGISEnvironment +import com.arcgismaps.toolkit.authentication.signOut +import kotlinx.serialization.Serializable + +/** + * Holds information about a sample. + */ +@Serializable +data class Sample( + val name: String, + val mainActivity: String, + val codeFiles: List, + val readMe: String, + val screenshotURL: String, + val url: String, + val metadata: SampleMetadata, + val isFavorite: Boolean = false, + var score: Double = 0.0 +) { + companion object { + val PREVIEW_INSTANCE = Sample( + name = "Analyze hotspots", + codeFiles = listOf(CodeFile("", "")), + url = "", + readMe = "", + screenshotURL = "", + metadata = SampleMetadata( + description = "", + formalName = "Analyze hotspots", + ignore = false, + imagePaths = listOf(""), + keywords = listOf(""), + relevantApis = listOf(""), + codePaths = listOf(""), + sampleCategory = SampleCategory.ANALYSIS, + title = "Analyze hotspots" + ), + isFavorite = false, + mainActivity = "" + ) + + /** + * Returns a list of [CodeFile] objects for the given sample name. + */ + fun loadCodeFiles(context: Context, sampleName: String): List { + // List of code files to be populated + val codeFiles = mutableListOf() + // Code file folders stored in assets directory as kebab case + val sampleNameKebabCase = sampleName.replace(" ", "-").lowercase() + val sampleAssetFiles = context.assets.list("samples/$sampleNameKebabCase/") + // Get the code files from sub-directories (components/, screens/) + sampleAssetFiles?.forEach { sampleAssetFile -> + if (sampleAssetFile.contains(".kt")) { + val codeString = context.assets.open( + /* fileName = */ "samples/$sampleNameKebabCase/$sampleAssetFile" + ).bufferedReader().use { it.readText() } + codeFiles.add( + CodeFile( + name = sampleAssetFile, + code = codeString + ) + ) + } + } + return codeFiles + } + + /** + * Returns the readme for a given sample name. + */ + fun loadReadMe(context: Context, sampleName: String): String { + // Get this metadata files as a string + context.assets.open("samples/$sampleName/README.md").use { inputStream -> + val readMeString = inputStream.bufferedReader().use { it.readText() } + // Remove screenshot markdown text from the README + return readMeString.lines().filterNot { it.contains("![") }.joinToString("\n") + } + } + + /** + * Returns the screenshot URL for a given sample name. + */ + fun loadScreenshot( + sampleName: String, imageArray: List, + ): String { + // Assuming imageArray will always have one image. + // Otherwise, function should be modified to return list of URLs for each image + val modifiedJsonSampleName = sampleName.replace(" ", "-").lowercase() + val imageFileName = imageArray.first().toString().replace("\"", "") + return "https://raw.githubusercontent.com/Esri/arcgis-maps-sdk-kotlin-samples/v.next/samples/$modifiedJsonSampleName/$imageFileName" + } + + /** + * Return's a path to DownloadActivity if one exists, otherwise returns the path to + * MainActivity. + */ + fun loadActivityPath(codePaths: List): String { + // Return a path to DownloadActivity if one exists + codePaths.find { it.contains("DownloadActivity.kt") }?.let { samplePath -> + val activityPath = samplePath + .substring(14, samplePath.indexOf(".")) + .replace("/".toRegex(), ".") + .replace("\\", "") + return activityPath + } + + // Otherwise return the path the MainActivity + codePaths.find { it.contains("MainActivity.kt") }.apply { + val samplePath = this.toString() + val activityPath = samplePath + .substring(14, samplePath.indexOf(".")) + .replace("/".toRegex(), ".") + .replace("\\", "") + return activityPath + } + } + } +} + +/** + * Starts the sample activity. + */ +suspend fun Sample.start(context: Context) { + // Revoke previously configured ArcGISEnvironment settings like ApiKeys/OAuth tokens/Credentials + ArcGISEnvironment.authenticationManager.signOut() + ArcGISEnvironment.apiKey = null + // Obtain and launch the sample activity + val className = Class.forName(mainActivity) as Class<*> + val sampleLauncherActivity = context.getActivityOrNull() ?: return + sampleLauncherActivity.startActivity(Intent(sampleLauncherActivity, className)) +} + +/** + * Returns the activity from the context. + */ +fun Context.getActivityOrNull(): Activity? { + var context = this + while (context is ContextWrapper) { + if (context is Activity) return context + context = context.baseContext + } + return null +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleCategory.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleCategory.kt new file mode 100644 index 000000000..477e1dec4 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleCategory.kt @@ -0,0 +1,73 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +/** + * Holds the enum of each Sample Category. + */ +@Serializable +enum class SampleCategory(val text: String) { + ANALYSIS("Analysis"), + AUGMENTED_REALITY("Augmented Reality"), + CLOUD_AND_PORTAL("Cloud and Portal"), + LAYERS("Layers"), + EDIT_AND_MANAGE_DATA("Edit and Manage Data"), + MAPS("Maps"), + SCENES("Scenes"), + ROUTING_AND_LOGISTICS("Routing and Logistics"), + UTILITY_NETWORKS("Utility Networks"), + SEARCH_AND_QUERY("Search and Query"), + VISUALIZATION("Visualization"), + FAVORITES("Favorites"); + + /** + * Return string of category enum. + */ + override fun toString(): String { + return text + } + + /** + * Return the enum of the category string. + */ + companion object { + fun toEnum(categoryString: String): SampleCategory { + return entries.firstOrNull {it.text == categoryString}!! + } + } +} + +object SampleCategorySerializer : KSerializer { + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("SampleCategory", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): SampleCategory { + val value = decoder.decodeString() + return SampleCategory.toEnum(value) + } + + override fun serialize(encoder: Encoder, value: SampleCategory) { + encoder.encodeString(value.text) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleInfoRepository.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleInfoRepository.kt new file mode 100644 index 000000000..fe5a4ae06 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleInfoRepository.kt @@ -0,0 +1,27 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model + +/** + * A repository interface to fetch sample information. + */ +interface SampleInfoRepository { + + fun getSamplesInCategory(sampleCategory: SampleCategory): List + + fun getSampleByName(sampleName: String): Sample +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleMetadata.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleMetadata.kt new file mode 100644 index 000000000..81c607cfc --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/SampleMetadata.kt @@ -0,0 +1,37 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +/** + * A data class to hold detailed information about the [Sample] + */ +@Serializable +data class SampleMetadata( + @Serializable(with = SampleCategorySerializer::class) + @SerialName("category") val sampleCategory: SampleCategory, + val description: String, + @SerialName("formal_name") val formalName: String, + val ignore: Boolean?, + @SerialName("images") val imagePaths: List, + val keywords: List, + @SerialName("relevant_apis") val relevantApis: List, + @SerialName("snippets") val codePaths: List, + val title: String +) diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/AppDatabase.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/AppDatabase.kt new file mode 100644 index 000000000..cea8b9e0a --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/AppDatabase.kt @@ -0,0 +1,53 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model.room + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import com.esri.arcgismaps.kotlin.sampleviewer.BuildConfig + +/** + * [AppDatabase] inherits from Room and makes an instance of [SampleDao] + */ +@Database( + entities = [SampleEntity::class], + version = BuildConfig.VERSION_CODE, + exportSchema = false +) +abstract class AppDatabase : RoomDatabase() { + abstract fun sampleDao(): SampleDao + + companion object { + + @Volatile + private var INSTANCE: AppDatabase? = null + + fun getDatabase(context: Context): AppDatabase { + return INSTANCE ?: synchronized(this) { + val instance = Room.databaseBuilder( + context.applicationContext, + AppDatabase::class.java, + "arcgis_maps_kotlin_samples_database" + ).build() + INSTANCE = instance + instance + } + } + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/Converters.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/Converters.kt new file mode 100644 index 000000000..5edd21c07 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/Converters.kt @@ -0,0 +1,63 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model.room + +import androidx.room.TypeConverter +import com.esri.arcgismaps.kotlin.sampleviewer.model.CodeFile +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json + +/** + * Room cannot convert complex data types like [CodeFile] or [List], + * thus, this class helps to convert them into JSON [String] format + */ +class Converters { + + private val json = Json { encodeDefaults = true } + + @TypeConverter + fun fromCodeFileList(codeFiles: List): String { + return codeFiles.let { json.encodeToString(it) } + } + + @TypeConverter + fun toCodeFileList(jsonString: String): List { + return jsonString.let { json.decodeFromString(it) } + } + + @TypeConverter + fun fromRelevantApiList(relevantApi: List): String { + return relevantApi.let { json.encodeToString(it) } + } + + @TypeConverter + fun toRelevantApiList(relevantApiJsonString: String): List { + return relevantApiJsonString.let { json.decodeFromString(it) } + } + + // Converts Sample to SampleEntity in order to select relevant fields + fun convertToEntity(sample: Sample): SampleEntity { + return SampleEntity( + sampleName = sample.name, + sampleCodeFile = sample.codeFiles, + sampleReadMe = sample.readMe, + sampleRelevantApi = sample.metadata.relevantApis + ) + } + +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/OkapiBM25.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/OkapiBM25.kt new file mode 100644 index 000000000..84a730813 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/OkapiBM25.kt @@ -0,0 +1,80 @@ +/* + * MIT License + * + * Copyright (c) 2018 Pablo Pallocchi + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the “Software”), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model.room + +import kotlin.math.log + +class OkapiBM25 { + + companion object { + /** + * Calculates the OkapiBM25 score for a given column in an FTS4 table. + */ + fun score(matchInfo: Array, column: Int, b: Double = 0.75, k1: Double = 1.2): Double { + + val pOffset = 0 + val cOffset = 1 + val nOffset = 2 + val aOffset = 3 + + // the number of matchable phrases in the query + val termCount = matchInfo[pOffset] + // the number of user defined columns in the FTS table + val colCount = matchInfo[cOffset] + + val lOffset = aOffset + colCount + val xOffset = lOffset + colCount + + // the number of rows in the FTS4 table + val totalDocs = matchInfo[nOffset].toDouble() + val avgLength = matchInfo[aOffset + column].toDouble() + val docLength = matchInfo[lOffset + column].toDouble() + + var score = 0.0 + + for (i in 0 until termCount) { + + val currentX = xOffset + (3 * (column + i * colCount)) + + // in the current row, the number of times the phrase appears in the column + val termFrequency = matchInfo[currentX].toDouble() + // the total number of rows in the FTS table for which the column contains at least one instance of the phrase. + val docsWithTerm = matchInfo[currentX + 2].toDouble() + + val p = totalDocs - docsWithTerm + 0.5 + val q = docsWithTerm + 0.5 + val idf = log(p, q) + + val r = termFrequency * (k1 + 1) + val s = b * (docLength / avgLength) + val t = termFrequency + (k1 * (1 - b + s)) + val rightSide = r / t + + score += (idf * rightSide) + } + + return score + } + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/SampleDao.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/SampleDao.kt new file mode 100644 index 000000000..8ba7a5421 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/SampleDao.kt @@ -0,0 +1,57 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model.room + +import android.database.Cursor +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query + +/** + * Holds all operations that uses Room + */ +@Dao +interface SampleDao { + + @Insert(onConflict = OnConflictStrategy.REPLACE) + suspend fun insertAll(samples: List) + + // In support of ranked search. + @Query( + """SELECT name, codeFile, readMe, relevantAPIs, MATCHINFO(samplesDB, 'pcnalx') FROM samplesDB + WHERE samplesDB MATCH :query""" + ) + fun matchInfoSearch(query: String): Cursor + + // Offers samples as search suggestions. + @Query( + """SELECT rowid, name, codeFile, readMe, relevantAPIs FROM samplesDB + WHERE LOWER(name) LIKE LOWER('%' || :searchQuery || '%' ) + OR LOWER(readMe) LIKE LOWER('%' || :searchQuery || '%' ) + OR LOWER(codeFile) LIKE LOWER('%' || :searchQuery || '%' ) + OR LOWER(relevantAPIs) LIKE LOWER('%' || :searchQuery || '%' )""" + ) + fun getFilteredSamples(searchQuery: String): List + + // Offers relevant APIs as search suggestions. + @Query( + """SELECT rowid, name, codeFile, readMe, relevantAPIs FROM samplesDB + WHERE LOWER(relevantAPIs) LIKE LOWER('%' || :searchQuery || '%' )""" + ) + fun getFilteredRelevantAPIs(searchQuery: String): List +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/SampleEntity.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/SampleEntity.kt new file mode 100644 index 000000000..ac867c2fe --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/model/room/SampleEntity.kt @@ -0,0 +1,40 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.model.room + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.Fts4 +import androidx.room.PrimaryKey +import androidx.room.TypeConverters +import com.esri.arcgismaps.kotlin.sampleviewer.model.CodeFile + +/** + * Define the structure of the Database records. The first column and the primary key is an integer + * rowid, which is a requirement of FTS4 tables. The other columns are the fields of the Sample + * class. + */ +@Fts4 +@Entity(tableName = "samplesDB") +@TypeConverters(Converters::class) +data class SampleEntity( + @PrimaryKey @ColumnInfo(name = "rowid") val id: Int = 0, + @ColumnInfo(name = "name") val sampleName: String, + @ColumnInfo(name = "codeFile") val sampleCodeFile: List, + @ColumnInfo(name = "readMe") val sampleReadMe: String, + @ColumnInfo(name = "relevantAPIs") val sampleRelevantApi: List, +) diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/navigation/NavGraph.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/navigation/NavGraph.kt new file mode 100644 index 000000000..f01611e20 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/navigation/NavGraph.kt @@ -0,0 +1,199 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.navigation + +import android.content.Context +import android.util.Log +import android.widget.Toast +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.navigation.NavGraph.Companion.findStartDestination +import androidx.navigation.NavHostController +import androidx.navigation.NavType +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import androidx.navigation.navArgument +import com.esri.arcgismaps.kotlin.sampleviewer.model.DefaultSampleInfoRepository +import com.esri.arcgismaps.kotlin.sampleviewer.model.SampleCategory +import com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.about.AboutScreen +import com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.codePager.SampleInfoScreen +import com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.home.HomeCategoryScreen +import com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.sampleList.SampleListScreen +import com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.search.SearchResults +import com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.search.SearchScreen + +/** + * A composable function to host the navigation system. + */ +@Composable +internal fun NavGraph() { + val context = LocalContext.current + val navController = rememberNavController() + NavHost( + navController = navController, + startDestination = Routes.HOME_SCREEN, + ) { + + composable(Routes.HOME_SCREEN) { + HomeCategoryScreen( + onNavigateToSearch = { navController.navigate(Routes.SEARCH_SCREEN) }, + onNavigateToAbout = { navController.navigate(Routes.ABOUT_SCREEN) }, + onNavigateToCategory = { navController.navigate(Routes.createCategoryRoute(it)) } + ) + } + + composable(Routes.ABOUT_SCREEN) { + AboutScreen(onBackPressed = { navController.pop() }) + } + + composable( + route = Routes.CATEGORY_SAMPLE_LIST_ROUTE, + arguments = listOf(navArgument("category") { type = NavType.StringType }) + ) { backStackEntry -> + val categoryNavEntry = backStackEntry.arguments?.getString("category") + if (!categoryNavEntry.isNullOrEmpty()) + SampleListScreen( + categoryNavEntry = categoryNavEntry, + onNavigateToInfo = { optionPosition, sample -> + navController.navigate( + Routes.createSampleInfoRoute(optionPosition, sample.name) + ) + }, + onBackPressed = { navController.pop() } + ) + else { + navController.displayError("categoryNavEntry is null/empty", context) + } + } + + composable( + route = Routes.SAMPLE_INFO_ROUTE, + arguments = listOf( + navArgument("optionPosition") { type = NavType.IntType }, + navArgument("sampleName") { type = NavType.StringType } + ) + ) { backStackEntry -> + val optionPositionNavEntry = backStackEntry.arguments?.getInt("optionPosition") + val sampleNameNavEntry = backStackEntry.arguments?.getString("sampleName") + + if (optionPositionNavEntry != null && !sampleNameNavEntry.isNullOrEmpty()) { + val sampleNavEntry = DefaultSampleInfoRepository.getSampleByName(sampleNameNavEntry) + SampleInfoScreen( + sample = sampleNavEntry, + optionPosition = optionPositionNavEntry, + onBackPressed = { navController.pop() } + ) + } else if (optionPositionNavEntry == null) { + navController.displayError("optionPositionNavEntry is null", context) + } else { + navController.displayError("sampleNameNavEntry is null/empty", context) + } + } + + composable(Routes.SEARCH_SCREEN) { + SearchScreen( + onNavigateToSearchResults = { + navController.navigate(Routes.createSearchResultsRoute(it)) + }, + onBackPressed = { navController.pop() } + ) + } + + composable( + route = Routes.SEARCH_RESULTS_ROUTE, + arguments = listOf(navArgument("query") { type = NavType.StringType }) + ) { backStackEntry -> + val queryNavEntry = backStackEntry.arguments?.getString("query") + if (!queryNavEntry.isNullOrEmpty()) { + SearchResults( + searchQuery = queryNavEntry, + navigateToInfo = { optionPosition, sample -> + navController.navigate( + Routes.createSampleInfoRoute( + optionPosition, + sample.name + ) + ) + }, + onBackPressed = { navController.pop() } + ) + } else { + navController.displayError("queryNavEntry is null/empty", context) + } + } + } +} + + +/** + * Displays a Toast and a Log for the given [message] on route errors, + * then reset navigation to home screen. + */ +private fun NavHostController.displayError(message: String, context: Context) { + val exceptionTag = "InvalidRouteError" + Toast.makeText(context, "$exceptionTag: $message", Toast.LENGTH_SHORT).show() + Log.e(exceptionTag, message) + navigateToHome() +} + +/** + * Attempts to pop the controller's back stack. Checks if screen was navigated to + * another destination, or navigate to home if no items in stack. + */ +private fun NavHostController.pop() { + if (!popBackStack()) { + navigateToHome() + } +} + +/** + * Navigates to the home screen, clearing the back stack and restoring the state. + */ +private fun NavHostController.navigateToHome() { + navigate(Routes.HOME_SCREEN) { + popUpTo(graph.findStartDestination().id) + launchSingleTop = true + } +} + +/** + * Navigation Routes for the application. + */ +private object Routes { + private const val SAMPLE_LIST = "Sample List" + private const val SAMPLE_INFO = "Sample Info" + private const val SEARCH_RESULTS = "Search Results" + const val HOME_SCREEN = "Sample Categories" + const val ABOUT_SCREEN = "About" + const val SEARCH_SCREEN = "Search" + const val CATEGORY_SAMPLE_LIST_ROUTE = "$SAMPLE_LIST/{category}" + const val SAMPLE_INFO_ROUTE = "$SAMPLE_INFO/{optionPosition}/{sampleName}" + const val SEARCH_RESULTS_ROUTE = "$SEARCH_RESULTS/{query}" + + fun createCategoryRoute(category: SampleCategory): String { + return "$SAMPLE_LIST/${category}" + } + + fun createSearchResultsRoute(query: String): String { + return "$SEARCH_RESULTS/$query" + } + + fun createSampleInfoRoute(optionPosition: Int, sampleName: String): String { + return "$SAMPLE_INFO/$optionPosition/$sampleName" + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/CategoryCard.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/CategoryCard.kt new file mode 100644 index 000000000..7c228ff3f --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/CategoryCard.kt @@ -0,0 +1,133 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.components + +import android.content.res.Configuration +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.esri.arcgismaps.kotlin.sampleviewer.R +import com.esri.arcgismaps.kotlin.sampleviewer.model.Category +import com.esri.arcgismaps.kotlin.sampleviewer.model.SampleCategory +import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme + +/** + * A composable used in the HomeCategoryScreen to display the category cards. + */ +@Composable +fun CategoryCard( + category: Category, + onClick: () -> Unit +) { + ElevatedCard( + modifier = Modifier + .size(width = 175.dp, height = 175.dp) + .clickable { onClick() }, + elevation = CardDefaults.cardElevation(defaultElevation = 4.dp), + shape = MaterialTheme.shapes.medium + ) { + Box { + CategoryBackground(category) + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(12.dp, Alignment.CenterVertically) + ) { + CategoryIconBackground(category) + Text( + modifier = Modifier.wrapContentSize(Alignment.Center), + text = category.title.text, + color = Color.White, + textAlign = TextAlign.Center, + style = MaterialTheme.typography.titleMedium + ) + } + } + } +} + +@Composable +private fun CategoryIconBackground(item: Category) { + Box( + Modifier + .background( + color = Color.Black.copy(alpha = 0.8f), + shape = CircleShape + ) + .padding(8.dp) + ) { + Icon( + modifier = Modifier + .size(30.dp), + painter = painterResource(item.icon), + contentDescription = "Category Icon", + tint = Color.White + ) + } +} + +@Composable +private fun CategoryBackground(item: Category) { + Image( + modifier = Modifier.fillMaxSize(), + painter = painterResource(item.backgroundImage), + contentDescription = item.title.text, + contentScale = ContentScale.Crop + ) + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Black.copy(alpha = 0.6f)) + ) +} + +@Preview(showBackground = true) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true) +@Composable +fun PreviewCategoryCard() { + SampleAppTheme { + CategoryCard( + Category( + title = SampleCategory.ANALYSIS, + icon = R.drawable.ic_analysis, + backgroundImage = R.drawable.analysis_background + ), + ) { } + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleCard.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleCard.kt new file mode 100644 index 000000000..abcd19efe --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleCard.kt @@ -0,0 +1,204 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.components + +import android.content.res.Configuration +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.expandVertically +import androidx.compose.animation.shrinkVertically +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Info +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample +import com.esri.arcgismaps.kotlin.sampleviewer.model.start +import com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.sampleList.DropdownItemData +import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme +import kotlinx.coroutines.launch + +/** + * Row to display Sample information and its contents + */ +@Composable +fun SampleRow( + sample: Sample, + dropdownSampleItems: List +) { + val context = LocalContext.current + val scope = rememberCoroutineScope() + Column(Modifier.clickable { scope.launch { sample.start(context) } }) { + TitleAndIcons(sample, dropdownSampleItems) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun TitleAndIcons( + sample: Sample, + dropdownSampleItems: List +) { + var expandedMenu by rememberSaveable { mutableStateOf(false) } + var expandedDescription by rememberSaveable { mutableStateOf(false) } + + Row( + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.surfaceContainer) + .padding(start = 16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween + ) { + Column( + modifier = Modifier + .weight(1f) + .padding(vertical = 16.dp) + ) { + Text( + text = sample.name, + style = MaterialTheme.typography.bodyLarge, + color = MaterialTheme.colorScheme.onSurface + ) + ExpandedDescriptionAnimation(expandedDescription, sample) + } + + IconButton(onClick = { expandedDescription = !expandedDescription }) { + Icon( + imageVector = if (expandedDescription) Icons.Filled.Info else Icons.Outlined.Info, + contentDescription = "Sample Info", + tint = MaterialTheme.colorScheme.primary + ) + } + + Column { + IconButton(onClick = { expandedMenu = !expandedMenu }) { + Icon( + imageVector = Icons.Filled.MoreVert, + contentDescription = "More options", + tint = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + DropdownMenu( + modifier = Modifier + .height(IntrinsicSize.Max) + .background(MaterialTheme.colorScheme.surfaceContainer), + expanded = expandedMenu, + onDismissRequest = { expandedMenu = false } + ) { + dropdownSampleItems.forEach { option -> + DropdownMenuItem( + text = { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy( + space = 8.dp, + alignment = Alignment.CenterHorizontally + ) + ) { + Icon( + painter = painterResource(id = option.icon), + contentDescription = "${option.title} Icon", + tint = MaterialTheme.colorScheme.onSurface + ) + Text( + text = option.title, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } + }, + onClick = { + expandedMenu = option.title.lowercase().contains("favorite") + option.onClick() + }, + contentPadding = ExposedDropdownMenuDefaults.ItemContentPadding + ) + } + } + } + } +} + +@Composable +private fun ExpandedDescriptionAnimation( + expandedDescription: Boolean, + sample: Sample +) { + AnimatedVisibility( + visible = expandedDescription, + enter = expandVertically(), + exit = shrinkVertically() + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start + ) { + Text( + text = sample.metadata.description, + textAlign = TextAlign.Start, + style = MaterialTheme.typography.bodyMedium, + color = Color.Gray + ) + } + } +} + +@Preview(showBackground = true) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true) +@Composable +fun PreviewSampleRow() { + SampleAppTheme { + val dropdownItemData = listOf() + SampleRow( + sample = Sample.PREVIEW_INSTANCE, + dropdownSampleItems = dropdownItemData + ) + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleViewerTopAppBar.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleViewerTopAppBar.kt new file mode 100644 index 000000000..1d3b72c9b --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleViewerTopAppBar.kt @@ -0,0 +1,72 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.components + +import android.content.res.Configuration +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.outlined.ArrowBack +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.esri.arcgismaps.kotlin.sampleviewer.R +import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme + +/** + * The common [TopAppBar] used to display screen title and the back button for all screens. + */ +@Composable +@OptIn(ExperimentalMaterial3Api::class) +fun SampleViewerTopAppBar(title: String, onBackPressed: () -> Unit) { + TopAppBar( + title = { + Text( + text = title, + style = MaterialTheme.typography.titleLarge + ) + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer, + navigationIconContentColor = MaterialTheme.colorScheme.onPrimaryContainer + ), + navigationIcon = { + IconButton(onClick = onBackPressed) { + Icon( + imageVector = Icons.AutoMirrored.Outlined.ArrowBack, + contentDescription = stringResource(R.string.backButton) + ) + } + } + ) +} + +@Preview(showBackground = true) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true) +@Composable +fun PreviewSampleViewerTopAppBar() { + SampleAppTheme { + SampleViewerTopAppBar(title = "Sample Viewer title", onBackPressed = {}) + } +} + diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleWebView.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleWebView.kt new file mode 100644 index 000000000..ded309cb0 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/components/SampleWebView.kt @@ -0,0 +1,181 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.components + +import android.annotation.SuppressLint +import android.content.Context +import android.webkit.WebView +import androidx.compose.foundation.background +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.viewinterop.AndroidView + +/** + * WebViewer to display formatted .kt code files. + */ +@Composable +fun CodeView(code: String) { + if (LocalInspectionMode.current) { + return // if composition is composed inside a preview component + } + + val isDeviceInDarkMode = isSystemInDarkTheme() + AndroidView( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background), + factory = { ctx -> createWebView(ctx) }, + update = { webView -> + webView.loadDataWithBaseURL( + /* baseUrl = */ "file:///android_asset/www/highlight/", + /* data = */ formatWebViewHTMLContent( + rawFileContents = code, + webViewType = WebViewType.CODE_VIEW, + isDeviceInDarkMode = isDeviceInDarkMode + ), + /* mimeType = */ "text/html", + /* encoding = */ "utf-8", + /* historyUrl = */ null + ) + } + ) +} + +/** + * WebViewer to display README.md files. + */ +@Composable +fun ReadmeView( + markdownText: String +) { + if (LocalInspectionMode.current) { + return // if composition is composed inside a preview component + } + + val isDeviceInDarkMode = isSystemInDarkTheme() + AndroidView( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.background), + factory = { ctx -> + createWebView(ctx).apply { + loadDataWithBaseURL( + /* baseUrl = */ "file:///android_asset/www/highlight/", + /* data = */ formatWebViewHTMLContent( + rawFileContents = markdownText, + webViewType = WebViewType.README_VIEW, + isDeviceInDarkMode = isDeviceInDarkMode + ), + /* mimeType = */ "text/html", + /* encoding = */ "utf-8", + /* historyUrl = */ null + ) + } + } + ) +} + +/** + * Set up the HTML [String] to be displayed based on the given [rawFileContents] + * given the [webViewType]. + */ +fun formatWebViewHTMLContent( + rawFileContents: String, + webViewType: WebViewType, + isDeviceInDarkMode: Boolean +): String { + val webViewHTML = if (webViewType == WebViewType.README_VIEW) { + readmeHTML.replace("\\(content)", rawFileContents) + } else { + if (!isDeviceInDarkMode) { + codeViewHTML + .replace("github-dark", "github") + .replace("\\(content)", rawFileContents) + } else { + codeViewHTML.replace("\\(content)", rawFileContents) + } + } + return webViewHTML +} + +/** + * Create the [WebView] using the default settings to load the static html. + */ +@SuppressLint("SetJavaScriptEnabled") +fun createWebView(context: Context): WebView { + return WebView(context).apply { + settings.apply { + javaScriptEnabled = true + domStorageEnabled = true + } + alpha = 0.99f // TODO: Weirdly, without this the screen crashes on popBackStack (#4632) + } +} + +enum class WebViewType { + README_VIEW, + CODE_VIEW +} + +val codeViewHTML: String = """ + + + + + + + + + + + + + + + +
\(content)
+ + +""".trimIndent() + +val readmeHTML: String = """ + + + + + + + + +
+
\(content)
+
+ + + + +""".trimIndent() diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/about/AboutScreen.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/about/AboutScreen.kt new file mode 100644 index 000000000..d79852566 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/about/AboutScreen.kt @@ -0,0 +1,511 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +@file:OptIn(ExperimentalMaterial3Api::class) + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.about + +import android.content.Intent +import android.content.res.Configuration +import android.net.Uri +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.BasicAlertDialog +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.esri.arcgismaps.kotlin.sampleviewer.BuildConfig +import com.esri.arcgismaps.kotlin.sampleviewer.R +import com.esri.arcgismaps.kotlin.sampleviewer.ui.components.SampleViewerTopAppBar +import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme + +/** + * Showcase information about the application. + */ +@Composable +fun AboutScreen(onBackPressed: () -> Unit) { + Scaffold( + modifier = Modifier + .fillMaxSize(), + topBar = { SampleViewerTopAppBar(title = "About", onBackPressed) }, + containerColor = MaterialTheme.colorScheme.background, + contentColor = MaterialTheme.colorScheme.onBackground + ) { innerPadding -> + AboutContent(Modifier.padding(innerPadding)) + } +} + +@Composable +fun AboutContent(modifier: Modifier) { + Column( + modifier + .fillMaxSize() + .verticalScroll(rememberScrollState()), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + Column( + modifier = Modifier.padding(20.dp), + verticalArrangement = Arrangement.spacedBy(20.dp) + ) { + TitleAndCopyrightSection() + VersionsSection() + PoweredBySection() + EsriCommunitySection() + GithubSection() + ApiDetailsSection() + } + } +} + +@Composable +private fun AboutIcon() { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + val size = (LocalConfiguration.current.screenWidthDp * 0.20).dp + Image( + modifier = Modifier.size(size), + painter = painterResource(com.esri.arcgismaps.sample.sampleslib.R.drawable.arcgis_maps_sdks_64), + contentDescription = stringResource(R.string.sdk_sample_icon_description) + ) + } +} + +@Composable +private fun TitleAndCopyrightSection() { + Column( + modifier = Modifier + .fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + AboutIcon() + Text( + modifier = Modifier.align(Alignment.CenterHorizontally), + text = stringResource(R.string.about_title), + textAlign = TextAlign.Center, + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleMedium + ) + Text( + modifier = Modifier.align(Alignment.CenterHorizontally), + text = stringResource(R.string.copyright_text), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.labelMedium + ) + } +} + +@Composable +private fun VersionsSection() { + Column( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.surfaceContainer, RoundedCornerShape(8.dp)) + .padding(16.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = stringResource(R.string.app_version), + textAlign = TextAlign.Start, + style = MaterialTheme.typography.labelLarge, + ) + Text( + text = BuildConfig.VERSION_CODE.toString(), + textAlign = TextAlign.End, + style = MaterialTheme.typography.bodyMedium + ) + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween + ) { + Text( + text = stringResource(R.string.SDK_version), + textAlign = TextAlign.Start, + style = MaterialTheme.typography.labelLarge + ) + Text( + text = BuildConfig.ARCGIS_VERSION, + textAlign = TextAlign.End, + style = MaterialTheme.typography.bodyMedium + ) + } + } + +} + +@Composable +private fun PoweredBySection() { + var isAcknowledgementsDialogVisible by rememberSaveable { mutableStateOf(false) } + val context = LocalContext.current + Column( + modifier = Modifier + .fillMaxSize() + .background(MaterialTheme.colorScheme.surfaceContainer, RoundedCornerShape(8.dp)) + .padding(start = 16.dp, top = 16.dp, bottom = 8.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Start + ) { + Text( + text = stringResource(R.string.powered_by), + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleSmall + ) + } + Column(modifier = Modifier.padding(start = 16.dp, top = 8.dp)) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + val intent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://github.com/Esri/arcgis-runtime-toolkit-android") + ) + context.startActivity(intent) + }, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.weight(1f), + text = stringResource(R.string.ArcGIS_Maps_SDK_Toolkit), + textAlign = TextAlign.Start, + style = MaterialTheme.typography.bodyMedium + ) + Box( + modifier = Modifier + .size(48.dp) + .padding(8.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.keyboard_arrow_right), + contentDescription = stringResource(R.string.forward_button) + ) + } + } + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { + val intent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://developers.arcgis.com/kotlin/") + ) + context.startActivity(intent) + }, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.weight(1f), + text = stringResource(R.string.ArcGIS_Maps_SDK_Kotlin), + textAlign = TextAlign.Start, + style = MaterialTheme.typography.bodyMedium + ) + Box( + modifier = Modifier + .size(48.dp) + .padding(8.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.keyboard_arrow_right), + contentDescription = stringResource(R.string.forward_button) + ) + } + } + Row( + modifier = Modifier + .fillMaxWidth() + .clickable { isAcknowledgementsDialogVisible = true }, + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.weight(1f), + text = "Acknowledgements", + textAlign = TextAlign.Start, + style = MaterialTheme.typography.bodyMedium + ) + Box( + modifier = Modifier + .size(48.dp) // Size of the clickable area + .padding(8.dp) // Padding inside the Box + ) { + Icon( + painter = painterResource(id = R.drawable.keyboard_arrow_right), + contentDescription = stringResource(R.string.forward_button) + ) + } + } + } + if (isAcknowledgementsDialogVisible) { + AcknowledgementsDialog { + isAcknowledgementsDialogVisible = false + } + } + } +} + +@Composable +private fun EsriCommunitySection() { + val context = LocalContext.current + Column( + modifier = Modifier + .fillMaxSize() + .clip(RoundedCornerShape(8.dp)) + .background(MaterialTheme.colorScheme.surfaceContainer) + .clickable { + val intent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://community.esri.com/t5/kotlin-maps-sdk-questions/bd-p/kotlin-maps-sdk-questions") + ) + context.startActivity(intent) + } + .padding(start = 16.dp, top = 16.dp, bottom = 8.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Start + ) { + Text( + text = stringResource(R.string.browse_and_discuss), + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleSmall + ) + } + Column(modifier = Modifier.padding(start = 16.dp)) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.weight(1f), + text = stringResource(R.string.esri_community), + textAlign = TextAlign.Start, + style = MaterialTheme.typography.bodyMedium + ) + Box( + modifier = Modifier + .size(48.dp) + .padding(8.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.keyboard_arrow_right), + contentDescription = stringResource(R.string.forward_button) + ) + } + } + } + } +} + +@Composable +fun AcknowledgementsDialog(onDismissRequest: () -> Unit) { + BasicAlertDialog( + modifier = Modifier.clip(RoundedCornerShape(8.dp)), + onDismissRequest = onDismissRequest + ) { + Column( + modifier = Modifier + .background(MaterialTheme.colorScheme.background) + .padding(24.dp) + .clip(RoundedCornerShape(8.dp)), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(12.dp) + ) { + val context = LocalContext.current + Text( + modifier = Modifier.fillMaxWidth(), + text = "License Acknowledgements", + style = MaterialTheme.typography.headlineSmall, + textAlign = TextAlign.Center + + ) + OutlinedButton(onClick = { + val intent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://github.com/showdownjs/showdown/blob/master/LICENSE") + ) + context.startActivity(intent) + }) { + Text(text = "Showdown") + } + OutlinedButton(onClick = { + val intent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://github.com/highlightjs/highlight.js/blob/main/LICENSE") + ) + context.startActivity(intent) + }) { + Text(text = "Highlight.js") + } + } + } +} + +@Composable +private fun GithubSection() { + val context = LocalContext.current + Column( + modifier = Modifier + .fillMaxSize() + .clip(RoundedCornerShape(8.dp)) + .background(MaterialTheme.colorScheme.surfaceContainer) + .clickable { + val intent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://github.com/Esri/arcgis-maps-sdk-kotlin-samples") + ) + context.startActivity(intent) + } + .padding(start = 16.dp, top = 16.dp, bottom = 8.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Start + ) { + Text( + text = stringResource(R.string.github_issue), + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleSmall + ) + } + Column(modifier = Modifier.padding(start = 16.dp)) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Text( + modifier = Modifier.weight(1f), + text = stringResource(R.string.github_repo), + textAlign = TextAlign.Start, + style = MaterialTheme.typography.bodyMedium + ) + Box( + modifier = Modifier + .size(48.dp) + .padding(8.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.keyboard_arrow_right), + contentDescription = stringResource(R.string.forward_button) + ) + } + } + } + } +} + +@Composable +private fun ApiDetailsSection() { + val context = LocalContext.current + Column( + modifier = Modifier + .fillMaxSize() + .clip(RoundedCornerShape(8.dp)) + .background(MaterialTheme.colorScheme.surfaceContainer) + .clickable { + val intent = Intent( + Intent.ACTION_VIEW, + Uri.parse("https://developers.arcgis.com/kotlin/api-reference/") + ) + context.startActivity(intent) + } + .padding(start = 16.dp, top = 16.dp, bottom = 8.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Start + ) { + Text( + text = stringResource(R.string.API_details), + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleSmall + ) + } + Column(modifier = Modifier.padding(start = 16.dp)) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.fillMaxWidth() + ) { + Text( + modifier = Modifier.weight(1f), + text = stringResource(R.string.API_ref), + textAlign = TextAlign.Start, + style = MaterialTheme.typography.bodyMedium + ) + Box( + modifier = Modifier + .size(48.dp) + .padding(8.dp) + ) { + Icon( + painter = painterResource(id = R.drawable.keyboard_arrow_right), + contentDescription = stringResource(R.string.forward_button) + ) + } + } + } + } +} + +@Preview(showBackground = true) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true) +@Composable +fun PreviewAboutScreen() { + SampleAppTheme { AboutScreen {} } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/codePager/SampleInfoScreen.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/codePager/SampleInfoScreen.kt new file mode 100644 index 000000000..a4e319876 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/codePager/SampleInfoScreen.kt @@ -0,0 +1,214 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.codePager + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.ArrowDropDown +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import coil3.compose.AsyncImage +import com.esri.arcgismaps.kotlin.sampleviewer.R +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample +import com.esri.arcgismaps.kotlin.sampleviewer.ui.components.CodeView +import com.esri.arcgismaps.kotlin.sampleviewer.ui.components.ReadmeView +import com.esri.arcgismaps.kotlin.sampleviewer.ui.components.SampleViewerTopAppBar +import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme + +/** + * Shows both README and Code for each sample. + */ +@Composable +fun SampleInfoScreen( + sample: Sample, + optionPosition: Int, + onBackPressed: () -> Unit +) { + val codePagerTitles = mutableListOf() + codePagerTitles.add("README.md") + sample.codeFiles.forEach { + codePagerTitles.add(it.name) + } + Scaffold( + topBar = { SampleViewerTopAppBar(title = sample.name, onBackPressed) }, + containerColor = MaterialTheme.colorScheme.background, + contentColor = MaterialTheme.colorScheme.onBackground, + modifier = Modifier + .fillMaxSize(), + ) { innerPadding -> + Surface( + modifier = Modifier + .fillMaxSize() + .clip(shape = MaterialTheme.shapes.extraLarge) + .padding(innerPadding) + ) { + CodePageView(codePagerTitles, sample, optionPosition) + } + } +} + +@Composable +fun CodePagerBar(selectedFileIndex: Int, fileList: List, onFileClicked: (Int) -> Unit) { + var expanded by rememberSaveable { mutableStateOf(false) } + Box(modifier = Modifier + .clickable { expanded = true } + .fillMaxWidth()) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(12.dp), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + CodePageRow( + title = fileList[selectedFileIndex], + iconId = getIconId(fileList[selectedFileIndex]) + ) + Icon( + imageVector = Icons.Outlined.ArrowDropDown, + contentDescription = "Dropdown icon", + tint = MaterialTheme.colorScheme.onSurface + ) + } + DropdownMenu( + modifier = Modifier.background(MaterialTheme.colorScheme.surface), + expanded = expanded, + onDismissRequest = { expanded = false }) { + fileList.forEachIndexed { index, file -> + DropdownMenuItem(modifier = Modifier.background(MaterialTheme.colorScheme.surface), + text = { + CodePageRow(title = file, iconId = getIconId(file)) + }, onClick = { + onFileClicked(index) + expanded = false + }) + } + } + } +} + +@Composable +fun CodePageRow(title: String, iconId: Int) { + Row( + modifier = Modifier.padding(horizontal = 8.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Start + ) { + Icon( + painter = painterResource(id = iconId), + contentDescription = "File icon", + tint = MaterialTheme.colorScheme.onSurface + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = title, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + } +} + +@Composable +private fun CodePageView( + codePagerTitles: List, + sample: Sample, + optionPosition: Int +) { + var selectedFileIndex by remember { mutableIntStateOf(optionPosition) } + Column { + CodePagerBar(selectedFileIndex, codePagerTitles, onFileClicked = { + selectedFileIndex = it + }) + if (codePagerTitles[selectedFileIndex].contains(".md")) { + Column( + modifier = Modifier + .verticalScroll(rememberScrollState()), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + val markdownText by remember { mutableStateOf(sample.readMe) } + val screenshotURL by remember { mutableStateOf(sample.screenshotURL) } + AsyncImage( + modifier = Modifier + .height(200.dp) + .width(350.dp) + .padding(8.dp), + model = screenshotURL, + contentDescription = "Sample screenshot" + ) + ReadmeView(markdownText = markdownText) + } + } else { + CodeView( + code = sample.codeFiles + .find { it.name == codePagerTitles[selectedFileIndex] }?.code ?: "" + ) + } + } +} + +@Composable +@Preview(showBackground = true) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true) +fun PreviewSampleInfoScreen() { + SampleAppTheme { + SampleInfoScreen( + sample = Sample.PREVIEW_INSTANCE, + optionPosition = 0, + onBackPressed = {} + ) + } +} + +fun getIconId(selectedFile: String): Int { + return when (selectedFile.lowercase().contains(".kt")) { + true -> R.drawable.ic_kotlin + else -> R.drawable.ic_readme + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/home/HomeCategoryScreen.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/home/HomeCategoryScreen.kt new file mode 100644 index 000000000..7587b586d --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/home/HomeCategoryScreen.kt @@ -0,0 +1,207 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.home + +import android.content.res.Configuration +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.staggeredgrid.LazyVerticalStaggeredGrid +import androidx.compose.foundation.lazy.staggeredgrid.StaggeredGridCells +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FabPosition +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.input.nestedscroll.NestedScrollConnection +import androidx.compose.ui.input.nestedscroll.NestedScrollSource +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.times +import com.esri.arcgismaps.kotlin.sampleviewer.R +import com.esri.arcgismaps.kotlin.sampleviewer.model.Category +import com.esri.arcgismaps.kotlin.sampleviewer.model.SampleCategory +import com.esri.arcgismaps.kotlin.sampleviewer.ui.components.CategoryCard +import com.esri.arcgismaps.sample.sampleslib.components.MessageDialog +import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme +import com.esri.arcgismaps.sample.stylegraphicswithsymbols.BuildConfig + +/** + * The main SampleViewer app screen which showcases the list all sample categories, + * saved favorites, and an app wide searching interface. + */ +@Composable +fun HomeCategoryScreen( + onNavigateToAbout: () -> Unit, + onNavigateToSearch: () -> Unit, + onNavigateToCategory: (SampleCategory) -> Unit, +) { + val config = LocalConfiguration.current + val layoutSpacing by remember { mutableStateOf(0.03f * config.screenWidthDp.dp) } + val isVisible = rememberSaveable { mutableStateOf(true) } + val nestedScrollConnection = remember { + object : NestedScrollConnection { + override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { + // Hide FAB + if (available.y < -1) { + isVisible.value = false + } + // Show FAB + if (available.y > 1) { + isVisible.value = true + } + return Offset.Zero + } + } + } + Scaffold( + modifier = Modifier.fillMaxSize(), + topBar = { HomeCategoryTopAppBar(onNavigateToAbout) }, + floatingActionButton = { SearchFloatingActionButton(isVisible, onNavigateToSearch) }, + floatingActionButtonPosition = FabPosition.End, + containerColor = MaterialTheme.colorScheme.background, + contentColor = MaterialTheme.colorScheme.onBackground + ) { innerPadding -> + Box( + modifier = Modifier + .padding(innerPadding) + .nestedScroll(nestedScrollConnection) + ) { + LazyVerticalStaggeredGrid( + modifier = Modifier + .fillMaxSize() + .padding(layoutSpacing), + columns = StaggeredGridCells.Adaptive(150.dp), + horizontalArrangement = Arrangement.spacedBy(layoutSpacing), + verticalItemSpacing = layoutSpacing + ) { + items(Category.SAMPLE_CATEGORIES.size) { index -> + val category = Category.SAMPLE_CATEGORIES[index] + CategoryCard(category) { onNavigateToCategory(category.title) } + } + } + CheckAccessToken() + } + } +} + +/** + * Display a dialog if the default access token placeholder is still set. + * This is required for samples to access Esri location services, including basemaps, routing, + * and geocoding, requires authentication using either an API Key or an ArcGIS identity. + * + * @see Accessing Esri location services + * + */ +@Composable +fun CheckAccessToken() { + var isDialogDisplayed by remember { + mutableStateOf(BuildConfig.ACCESS_TOKEN == "DEFAULT_ACCESS_TOKEN") + } + if (isDialogDisplayed) { + MessageDialog( + title = "Access token", + description = "Add an ACCESS_TOKEN to the project's local.properties", + onDismissRequest = { isDialogDisplayed = false } + ) + } +} + +@Composable +private fun SearchFloatingActionButton( + isVisible: MutableState, + navigateToSearch: () -> Unit +) { + AnimatedVisibility( + visible = isVisible.value, + enter = slideInVertically(initialOffsetY = { it * 2 }), + exit = slideOutVertically(targetOffsetY = { it * 2 }), + ) { + FloatingActionButton( + onClick = navigateToSearch, + shape = CircleShape, + containerColor = MaterialTheme.colorScheme.secondaryContainer, + contentColor = MaterialTheme.colorScheme.onSecondaryContainer + ) { + Icon( + imageVector = Icons.Filled.Search, + contentDescription = stringResource(R.string.search) + ) + } + } +} + +@Composable +@OptIn(ExperimentalMaterial3Api::class) +private fun HomeCategoryTopAppBar(navigateToAboutScreen: () -> Unit) { + TopAppBar( + title = { + Text(text = stringResource(R.string.home_screen_title)) + }, + colors = TopAppBarDefaults.topAppBarColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + titleContentColor = MaterialTheme.colorScheme.onPrimaryContainer, + navigationIconContentColor = MaterialTheme.colorScheme.onPrimaryContainer + ), + actions = { + IconButton(onClick = navigateToAboutScreen) { + Icon( + imageVector = Icons.Outlined.Info, + contentDescription = stringResource(R.string.about_section) + ) + } + } + ) +} + +@Composable +@Preview(showBackground = true) +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true) +fun PreviewHomeCategoryScreen() { + SampleAppTheme { + HomeCategoryScreen( + onNavigateToCategory = {}, + onNavigateToSearch = {}, + onNavigateToAbout = {} + ) + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/sampleList/SampleListScreen.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/sampleList/SampleListScreen.kt new file mode 100644 index 000000000..11e793b7d --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/sampleList/SampleListScreen.kt @@ -0,0 +1,199 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.sampleList + +import android.content.Intent +import android.net.Uri +import androidx.compose.animation.animateContentSize +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.esri.arcgismaps.kotlin.sampleviewer.R +import com.esri.arcgismaps.kotlin.sampleviewer.model.DefaultSampleInfoRepository +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample +import com.esri.arcgismaps.kotlin.sampleviewer.model.SampleCategory +import com.esri.arcgismaps.kotlin.sampleviewer.ui.components.SampleRow +import com.esri.arcgismaps.kotlin.sampleviewer.ui.components.SampleViewerTopAppBar +import com.esri.arcgismaps.kotlin.sampleviewer.viewmodels.FavoritesViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import java.util.Locale + +/** + * Shows the list of samples. + */ +@Composable +fun SampleListScreen( + categoryNavEntry: String, + onNavigateToInfo: (Int, Sample) -> Unit, + onBackPressed: () -> Unit +) { + val viewModel: FavoritesViewModel = viewModel() + val favoriteSamplesFlow = remember { viewModel.getFavorites() } + val favoriteSamples by favoriteSamplesFlow.collectAsState(initial = emptyList()) + val category = SampleCategory.toEnum(categoryNavEntry) + val samplesList = DefaultSampleInfoRepository.getSamplesInCategory(category) + + Scaffold( + topBar = { SampleViewerTopAppBar(title = category.text, onBackPressed) }, + modifier = Modifier + .fillMaxSize(), + ) { innerPadding -> + Column(modifier = Modifier.padding(innerPadding)) { + if (samplesList.isEmpty() && category != SampleCategory.FAVORITES) { + EmptySampleListScreen(stringResource(R.string.upcoming_samples_text)) + } else if (category == SampleCategory.FAVORITES) { + FavoriteItemsListScreen(favoriteSamples, onNavigateToInfo) + } else { + ListOfSamplesScreen(samplesList, onNavigateToInfo) + } + } + } +} + +@Composable +fun ListOfSamplesScreen( + samples: List, + navigateToInfo: (Int, Sample) -> Unit, +) { + val favoritesViewModel: FavoritesViewModel = viewModel() + val favoriteSamples by favoritesViewModel.getFavorites().collectAsState(initial = emptyList()) + val scope = rememberCoroutineScope() + val context = LocalContext.current + Box( + modifier = Modifier + .wrapContentSize() + .padding(16.dp) + .clip(RoundedCornerShape(16.dp)) + .background(MaterialTheme.colorScheme.surfaceContainer) + ) { + LazyColumn(modifier = Modifier.animateContentSize()) { + itemsIndexed(samples) { index, sample -> + val isFavorite = favoriteSamples.contains(sample) + val readMePosition = 0 + val codeFilePosition = 1 + + val dropdownSampleItems = listOf( + DropdownItemData( + title = "README", + icon = R.drawable.ic_readme, + onClick = { navigateToInfo(readMePosition, sample) } + ), + DropdownItemData( + title = "Code", + icon = R.drawable.ic_kotlin, + onClick = { navigateToInfo(codeFilePosition, sample) } + ), + DropdownItemData( + title = "Website", + icon = R.drawable.ic_link, + onClick = { + val url = "https://developers.arcgis.com/kotlin/sample-code/" + + sample.metadata.title + .replace(" ", "-") + .lowercase(Locale.getDefault()) + val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) + context.startActivity(intent) + } + ), + DropdownItemData( + title = if (isFavorite) "Unfavorite" else "Favorite", + icon = if (isFavorite) R.drawable.ic_favorite_selected else R.drawable.ic_favorite_unselected, + onClick = { + scope.launch(Dispatchers.IO) { + if (isFavorite) favoritesViewModel.removeFavorite(sample) + else favoritesViewModel.addFavorite(sample) + } + } + ) + ) + + SampleRow( + sample = sample, + dropdownSampleItems = dropdownSampleItems + ) + + // Add divider if not the last item + if (index < samples.size - 1) { + HorizontalDivider() + } + } + } + } +} + +@Composable +private fun EmptySampleListScreen(emptyMessage: String) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxSize() + ) { + Text( + text = emptyMessage, + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center + ) + } +} + +@Composable +private fun FavoriteItemsListScreen( + favoriteSamples: List, + navigateToInfo: (Int, Sample) -> Unit +) { + if (favoriteSamples.isNotEmpty()) { + ListOfSamplesScreen( + samples = favoriteSamples, + navigateToInfo = navigateToInfo + ) + } else { + EmptySampleListScreen(stringResource(R.string.no_favorites_text)) + } +} + +data class DropdownItemData( + val title: String, + val icon: Int, + val onClick: () -> Unit +) diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/search/SearchResultsScreen.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/search/SearchResultsScreen.kt new file mode 100644 index 000000000..d50be1588 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/search/SearchResultsScreen.kt @@ -0,0 +1,56 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.search + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Scaffold +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.lifecycle.viewmodel.compose.viewModel +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample +import com.esri.arcgismaps.kotlin.sampleviewer.ui.components.SampleViewerTopAppBar +import com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.sampleList.ListOfSamplesScreen +import com.esri.arcgismaps.kotlin.sampleviewer.viewmodels.SampleSearchViewModel + +/** + * Shows search results based on valid query searches. + */ +@Composable +fun SearchResults( + searchQuery: String, + navigateToInfo: (Int, Sample) -> Unit, + onBackPressed: () -> Unit +) { + val searchViewModel: SampleSearchViewModel = viewModel() + searchViewModel.rankedSearch(searchQuery) + Scaffold( + topBar = { SampleViewerTopAppBar(title = searchQuery, onBackPressed) }) { innerPadding -> + Column( + modifier = Modifier.padding(innerPadding) + ) { + // List of samples results ranked with using the searchQuery + val rankedSearchResults by searchViewModel.rankedSearchResults.collectAsState() + ListOfSamplesScreen( + samples = rankedSearchResults, + navigateToInfo = navigateToInfo + ) + } + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/search/SearchSuggestionsScreen.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/search/SearchSuggestionsScreen.kt new file mode 100644 index 000000000..960dccbbb --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/ui/screens/search/SearchSuggestionsScreen.kt @@ -0,0 +1,320 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.ui.screens.search + +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.animateContentSize +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.ArrowBack +import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight +import androidx.compose.material.icons.filled.Clear +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.ListItem +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.runtime.snapshotFlow +import androidx.compose.ui.Alignment +import androidx.compose.ui.BiasAlignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalFocusManager +import androidx.compose.ui.platform.LocalSoftwareKeyboardController +import androidx.compose.ui.platform.LocalWindowInfo +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.esri.arcgismaps.kotlin.sampleviewer.R +import com.esri.arcgismaps.kotlin.sampleviewer.model.DefaultSampleInfoRepository +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample +import com.esri.arcgismaps.kotlin.sampleviewer.model.start +import com.esri.arcgismaps.kotlin.sampleviewer.viewmodels.SampleSearchViewModel +import kotlinx.coroutines.launch + +/** + * Allows functionality to search samples to get two types of categories: Samples and Relevant APIs attached to Sample Readmes + */ +@Composable +fun SearchScreen(onNavigateToSearchResults: (String) -> Unit, onBackPressed: () -> Unit) { + val context = LocalContext.current + val focusManager = LocalFocusManager.current + val scope = rememberCoroutineScope() + val viewModel: SampleSearchViewModel = viewModel() + var searchQuery by remember { mutableStateOf("") } + val keyboardController = LocalSoftwareKeyboardController.current + // Get the ordered search suggestions of samples or relevantAPIs + val searchSuggestions: List> by viewModel.searchSuggestions.collectAsState() + + Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> + Column(modifier = Modifier.padding(innerPadding)) { + SampleViewerSearchBar( + searchQuery = searchQuery, + onValueChange = { + searchQuery = it + viewModel.suggestionSearch(searchQuery) + }, + onClear = { + searchQuery = "" + focusManager.clearFocus() + }, + onExit = { + keyboardController?.hide() + onBackPressed() + }, + onSearch = { + if (searchQuery.trim().isNotEmpty()) { + keyboardController?.hide() + // Open results screen with list view. + onNavigateToSearchResults(searchQuery) + } + + } + ) + SearchSuggestionsList( + searchQuery = searchQuery, + searchSuggestions = searchSuggestions, + onSampleSelected = { + scope.launch { + it.start(context) + } + }, + onRelevantAPISelected = onNavigateToSearchResults + ) + } + } +} + +@Composable +fun SearchSuggestionsList( + searchQuery: String, + searchSuggestions: List>, + onSampleSelected: (Sample) -> Unit, + onRelevantAPISelected: (String) -> Unit + +) { + Column( + modifier = Modifier + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + + AnimatedVisibility( + visible = searchQuery.isEmpty(), + enter = fadeIn(), exit = fadeOut(), + ) { + EmptySearchQueryMessage() + } + + AnimatedVisibility( + visible = searchQuery.isNotEmpty(), + enter = fadeIn(), exit = fadeOut() + ) { + // Show dynamic search results as search query changes + LazyColumn( + Modifier + .fillMaxSize() + .animateContentSize() + ) { + items( + items = searchSuggestions, + key = { suggestion -> suggestion } + ) { suggestion -> + if (suggestion.second) { // Sample Suggestion + val sample = DefaultSampleInfoRepository.getSampleByName(suggestion.first) + Row( + modifier = Modifier + .animateItem() + .clickable { onSampleSelected(sample) } + ) { + SampleListItem(sample.name) + } + } else { // RelevantAPI Suggestion + val relevantApi = suggestion.first + Row( + modifier = Modifier + .animateItem() + .clickable { onRelevantAPISelected(relevantApi) } + ) { + RelevantAPIListItem(relevantApi) + } + } + } + } + } + } +} + +@Composable +fun SampleViewerSearchBar( + searchQuery: String, + onValueChange: (String) -> Unit, + onExit: () -> Unit, + onClear: () -> Unit, + onSearch: () -> Unit +) { + val windowInfo = LocalWindowInfo.current + val focusRequester = remember { FocusRequester() } + // Opens keyboard and focuses on search when the screen comes in focus + LaunchedEffect(windowInfo) { + snapshotFlow { windowInfo.isWindowFocused }.collect { isWindowFocused -> + if (isWindowFocused) { + focusRequester.requestFocus() + } + } + } + + OutlinedTextField( + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 24.dp, horizontal = 12.dp) + .focusRequester(focusRequester), + value = searchQuery, + onValueChange = onValueChange, + maxLines = 1, + singleLine = true, + shape = RoundedCornerShape(50.dp), + colors = OutlinedTextFieldDefaults.colors( + unfocusedBorderColor = MaterialTheme.colorScheme.outlineVariant, + focusedBorderColor = MaterialTheme.colorScheme.secondary, + focusedContainerColor = MaterialTheme.colorScheme.background, + unfocusedContainerColor = MaterialTheme.colorScheme.background, + ), + placeholder = { + Text( + text = "Search...", + color = MaterialTheme.colorScheme.onSurfaceVariant + ) + }, + leadingIcon = { + IconButton(onClick = { onExit() }) { + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = stringResource(id = R.string.backButton), + tint = MaterialTheme.colorScheme.primary + ) + } + }, + trailingIcon = { + IconButton(onClick = { onClear() }) { + Icon( + imageVector = Icons.Default.Clear, + contentDescription = stringResource(id = R.string.clearButton), + tint = MaterialTheme.colorScheme.onSurface + ) + } + }, + keyboardOptions = KeyboardOptions( + imeAction = androidx.compose.ui.text.input.ImeAction.Search, + keyboardType = KeyboardType.Text + ), + keyboardActions = KeyboardActions( + onSearch = { onSearch() } + ) + ) +} + +@Composable +private fun RelevantAPIListItem(relevantApi: String) { + ListItem( + leadingContent = { + Icon( + imageVector = Icons.Default.Search, + contentDescription = stringResource(id = R.string.search), + modifier = Modifier.size(32.dp) + ) + }, + headlineContent = { + Text( + text = relevantApi, + fontSize = MaterialTheme.typography.titleSmall.fontSize, + ) + }, + ) +} + +@Composable +private fun SampleListItem(sampleName: String) { + ListItem( + leadingContent = { + Image( + painter = painterResource(id = com.esri.arcgismaps.sample.sampleslib.R.drawable.arcgis_maps_sdks_64), + contentDescription = stringResource(id = R.string.sdk_sample_icon_description), + modifier = Modifier.size(32.dp) + ) + }, + headlineContent = { + Text( + text = sampleName, + fontSize = MaterialTheme.typography.titleSmall.fontSize, + ) + }, + trailingContent = { + Icon( + Icons.AutoMirrored.Filled.KeyboardArrowRight, + contentDescription = stringResource(id = R.string.forward_button), + tint = MaterialTheme.colorScheme.primary + ) + } + ) +} + +@Composable +private fun EmptySearchQueryMessage() { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = BiasAlignment(0f, -0.5f) + ) { + Text( + text = "Search for sample name, feature or an API", + textAlign = TextAlign.Center, + color = MaterialTheme.colorScheme.onSurface, + ) + } +} diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/viewmodels/FavoritesViewModel.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/viewmodels/FavoritesViewModel.kt new file mode 100644 index 000000000..bd39cb10f --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/viewmodels/FavoritesViewModel.kt @@ -0,0 +1,89 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.viewmodels + +import android.app.Application +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.stringPreferencesKey +import androidx.datastore.preferences.preferencesDataStore +import androidx.lifecycle.AndroidViewModel +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.map +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json + +/** + * ViewModel to handle list of favorite samples + */ +class FavoritesViewModel(private val application: Application) : AndroidViewModel(application) { + private val json = Json { ignoreUnknownKeys = true } + + /** + * Retrieve list of favorite Samples using Flow to allow UI to update reactively on change + */ + fun getFavorites(): Flow> = application.applicationContext.dataStore.data + .map { preferences -> + val jsonString = preferences[FAVORITES_KEY] ?: "[]" + // Convert JSON string into list of Sample objects + json.decodeFromString(jsonString) + } + + /** + * Save list of favorite Samples + */ + private suspend fun saveFavorite(favorites: List) { + // Convert list of Sample objects into JSON string + val jsonString = json.encodeToString(favorites) + application.applicationContext.dataStore.edit { preferences -> + // Store JSON string to DataStore using FAVORITES KEY + preferences[FAVORITES_KEY] = jsonString + } + } + + /** + * Add a new favorite sample to the list of favorite samples + */ + suspend fun addFavorite(favorite: Sample) { + val currentFavorites = getFavorites().first() + val updatedFavorites = currentFavorites.toMutableList().apply { + add(favorite) + } + saveFavorite(updatedFavorites) + } + + /** + * Remove an existing favorite sample from the list of favorite samples + */ + suspend fun removeFavorite(favorite: Sample) { + val currentFavorites = getFavorites().first() + val updatedFavorites = currentFavorites.toMutableList().apply { + remove(favorite) + } + saveFavorite(updatedFavorites) + } + + companion object { + private const val PREFS_NAME = "favorite_samples_pref" + private val FAVORITES_KEY = stringPreferencesKey("favorite_samples_key") + private val Context.dataStore: DataStore by preferencesDataStore(name = PREFS_NAME) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/viewmodels/SampleSearchViewModel.kt b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/viewmodels/SampleSearchViewModel.kt new file mode 100644 index 000000000..08a42cda2 --- /dev/null +++ b/app/src/main/java/com/esri/arcgismaps/kotlin/sampleviewer/viewmodels/SampleSearchViewModel.kt @@ -0,0 +1,123 @@ +/* Copyright 2024 Esri + * + * 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. + * + */ + +package com.esri.arcgismaps.kotlin.sampleviewer.viewmodels + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.viewModelScope +import com.esri.arcgismaps.kotlin.sampleviewer.model.DefaultSampleInfoRepository +import com.esri.arcgismaps.kotlin.sampleviewer.model.Sample +import com.esri.arcgismaps.kotlin.sampleviewer.model.room.AppDatabase +import com.esri.arcgismaps.kotlin.sampleviewer.model.room.OkapiBM25 +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancelAndJoin +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.launch +import java.nio.ByteBuffer +import java.nio.ByteOrder + +/** + * Viewmodel to handle search logic such as finding relevant API keywords and samples + */ +class SampleSearchViewModel(private val application: Application) : AndroidViewModel(application) { + + var rankedSearchResults = MutableStateFlow>(mutableListOf()) + private set + + var searchSuggestions = MutableStateFlow>>(emptyList()) + private set + + // Keep track of the scope where DB is queried, so it can be cancelled + // on subsequent searchQuery. + private var databaseQueryJob: Job? = null + + /** + * Used to search through samples and list relevant Samples and API searches + */ + fun suggestionSearch(searchQuery: String) { + viewModelScope.launch { + val database = AppDatabase.getDatabase(application).sampleDao() + // If the dao is querying, cancel and query on a new scope. + databaseQueryJob?.cancelAndJoin() + databaseQueryJob = launch(Dispatchers.IO) { + val filteredSamples = database.getFilteredSamples(searchQuery) + val filteredAPIs = database.getFilteredRelevantAPIs(searchQuery).flatMap { sample -> + sample.sampleRelevantApi.filter { apiName -> + apiName.lowercase().contains(searchQuery.lowercase()) + } + }.distinct() + // Combine filtered samples and APIs into pairs + searchSuggestions.value = (filteredSamples.map { sample -> + // true indicates it's a filtered sample + Pair(sample.sampleName, true) + } + filteredAPIs.map { apiName -> + // false indicates it's a filtered API + Pair(apiName, false) + }).sortedBy { it.first } + } + } + } + + /** + * Performs a ranked search on the given [searchQuery] + */ + fun rankedSearch(searchQuery: String) { + viewModelScope.launch(Dispatchers.IO) { + val database = AppDatabase.getDatabase(application).sampleDao() + val cursor = database.matchInfoSearch(searchQuery) + + if (cursor.moveToFirst()) { + val results = mutableListOf() + do { + // Get a reference to the mapInfo blob. + val matchInfo = cursor.getBlob(4).toIntArray() + // Get the score for each column. + val totalScore = listOf( + OkapiBM25.score(matchInfo, 0), + OkapiBM25.score(matchInfo, 1), + OkapiBM25.score(matchInfo, 2), + OkapiBM25.score(matchInfo, 3) + ).average() + // Add the score to the sample. + val sample = DefaultSampleInfoRepository.getSampleByName( + sampleName = cursor.getString(0) + ).apply { + score = totalScore + } + results.add(sample) + } while (!cursor.isClosed && cursor.moveToNext()) + cursor.close() + results.sortByDescending { it.score } + + // update the ranked list with the sorted results + if (rankedSearchResults.value != results) { + rankedSearchResults.value = results + } + } + } + } +} + +fun ByteArray.toIntArray(): Array { + val intBuf = ByteBuffer.wrap(this) + .order(ByteOrder.LITTLE_ENDIAN) + .asIntBuffer() + val array = IntArray(intBuf.remaining()) + intBuf.get(array) + return array.toTypedArray() +} diff --git a/app/src/main/res/drawable/analysis_background.webp b/app/src/main/res/drawable/analysis_background.webp new file mode 100644 index 000000000..159f34864 Binary files /dev/null and b/app/src/main/res/drawable/analysis_background.webp differ diff --git a/app/src/main/res/drawable/augmented_reality_background.webp b/app/src/main/res/drawable/augmented_reality_background.webp new file mode 100644 index 000000000..ce3e52199 Binary files /dev/null and b/app/src/main/res/drawable/augmented_reality_background.webp differ diff --git a/app/src/main/res/drawable/cloud_background.webp b/app/src/main/res/drawable/cloud_background.webp new file mode 100644 index 000000000..3dc089304 Binary files /dev/null and b/app/src/main/res/drawable/cloud_background.webp differ diff --git a/app/src/main/res/drawable/ic_analysis.xml b/app/src/main/res/drawable/ic_analysis.xml new file mode 100644 index 000000000..91bd175ef --- /dev/null +++ b/app/src/main/res/drawable/ic_analysis.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_augmented_reality.xml b/app/src/main/res/drawable/ic_augmented_reality.xml new file mode 100644 index 000000000..4b160cc36 --- /dev/null +++ b/app/src/main/res/drawable/ic_augmented_reality.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_cloud.xml b/app/src/main/res/drawable/ic_cloud.xml new file mode 100644 index 000000000..373a42c45 --- /dev/null +++ b/app/src/main/res/drawable/ic_cloud.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_favorite_selected.xml b/app/src/main/res/drawable/ic_favorite_selected.xml new file mode 100644 index 000000000..d02332b5f --- /dev/null +++ b/app/src/main/res/drawable/ic_favorite_selected.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_favorite_unselected.xml b/app/src/main/res/drawable/ic_favorite_unselected.xml new file mode 100644 index 000000000..452e488e0 --- /dev/null +++ b/app/src/main/res/drawable/ic_favorite_unselected.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_kotlin.xml b/app/src/main/res/drawable/ic_kotlin.xml new file mode 100644 index 000000000..5d4df83c9 --- /dev/null +++ b/app/src/main/res/drawable/ic_kotlin.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_layers.xml b/app/src/main/res/drawable/ic_layers.xml new file mode 100644 index 000000000..fe5382108 --- /dev/null +++ b/app/src/main/res/drawable/ic_layers.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_link.xml b/app/src/main/res/drawable/ic_link.xml new file mode 100644 index 000000000..1146d4cb8 --- /dev/null +++ b/app/src/main/res/drawable/ic_link.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_manage_data.xml b/app/src/main/res/drawable/ic_manage_data.xml new file mode 100644 index 000000000..fd51e2115 --- /dev/null +++ b/app/src/main/res/drawable/ic_manage_data.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_map.xml b/app/src/main/res/drawable/ic_map.xml new file mode 100644 index 000000000..2eb37f32d --- /dev/null +++ b/app/src/main/res/drawable/ic_map.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_readme.xml b/app/src/main/res/drawable/ic_readme.xml new file mode 100644 index 000000000..302bb4af1 --- /dev/null +++ b/app/src/main/res/drawable/ic_readme.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_routing_and_logistics.xml b/app/src/main/res/drawable/ic_routing_and_logistics.xml new file mode 100644 index 000000000..d0a241b34 --- /dev/null +++ b/app/src/main/res/drawable/ic_routing_and_logistics.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_scenes.xml b/app/src/main/res/drawable/ic_scenes.xml new file mode 100644 index 000000000..8c671d288 --- /dev/null +++ b/app/src/main/res/drawable/ic_scenes.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_search_and_query.xml b/app/src/main/res/drawable/ic_search_and_query.xml new file mode 100644 index 000000000..442a45e28 --- /dev/null +++ b/app/src/main/res/drawable/ic_search_and_query.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_utility.xml b/app/src/main/res/drawable/ic_utility.xml new file mode 100644 index 000000000..1ac2e85f2 --- /dev/null +++ b/app/src/main/res/drawable/ic_utility.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_visualization.xml b/app/src/main/res/drawable/ic_visualization.xml new file mode 100644 index 000000000..5837d8fdf --- /dev/null +++ b/app/src/main/res/drawable/ic_visualization.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/keyboard_arrow_right.xml b/app/src/main/res/drawable/keyboard_arrow_right.xml new file mode 100644 index 000000000..4904368f3 --- /dev/null +++ b/app/src/main/res/drawable/keyboard_arrow_right.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/drawable/layers_background.webp b/app/src/main/res/drawable/layers_background.webp new file mode 100644 index 000000000..46f858535 Binary files /dev/null and b/app/src/main/res/drawable/layers_background.webp differ diff --git a/app/src/main/res/drawable/manage_data_background.webp b/app/src/main/res/drawable/manage_data_background.webp new file mode 100644 index 000000000..bbae2d21f Binary files /dev/null and b/app/src/main/res/drawable/manage_data_background.webp differ diff --git a/app/src/main/res/drawable/maps_and_scenes_background.webp b/app/src/main/res/drawable/maps_and_scenes_background.webp new file mode 100644 index 000000000..02585a0f8 Binary files /dev/null and b/app/src/main/res/drawable/maps_and_scenes_background.webp differ diff --git a/app/src/main/res/drawable/routing_and_logistics_background.webp b/app/src/main/res/drawable/routing_and_logistics_background.webp new file mode 100644 index 000000000..f456374f7 Binary files /dev/null and b/app/src/main/res/drawable/routing_and_logistics_background.webp differ diff --git a/app/src/main/res/drawable/scenes_background.webp b/app/src/main/res/drawable/scenes_background.webp new file mode 100644 index 000000000..8b4c62229 Binary files /dev/null and b/app/src/main/res/drawable/scenes_background.webp differ diff --git a/app/src/main/res/drawable/search_and_query_background.webp b/app/src/main/res/drawable/search_and_query_background.webp new file mode 100644 index 000000000..228cafdd1 Binary files /dev/null and b/app/src/main/res/drawable/search_and_query_background.webp differ diff --git a/app/src/main/res/drawable/utility_background.webp b/app/src/main/res/drawable/utility_background.webp new file mode 100644 index 000000000..4bc9f74a9 Binary files /dev/null and b/app/src/main/res/drawable/utility_background.webp differ diff --git a/app/src/main/res/drawable/visualization_background.webp b/app/src/main/res/drawable/visualization_background.webp new file mode 100644 index 000000000..8a565f271 Binary files /dev/null and b/app/src/main/res/drawable/visualization_background.webp differ diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 000000000..1d6dc5d2d --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,26 @@ + + ArcGIS Maps Kotlin Samples + Search + About + App Version + SDK Version + Copyright © 2015–2024 Esri.\nAll Rights Reserved. + ArcGIS Maps SDK Sample Viewer + Powered By + ArcGIS Maps SDK Toolkit for Kotlin + ArcGIS Maps SDK for Kotlin + Forward button + Browse and discuss in the Esri Community + Esri Community + Log an issue in the Github repository + Github Repository + View details about the API + API Reference + Samples in this category will be added in a future release + No favorite samples added yet! + Back button + Clear button + Cancel + SDK sample icon + Sample Categories + diff --git a/app/src/main/res/xml/backup_rules.xml b/app/src/main/res/xml/backup_rules.xml new file mode 100644 index 000000000..fa0f996d2 --- /dev/null +++ b/app/src/main/res/xml/backup_rules.xml @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/xml/data_extraction_rules.xml b/app/src/main/res/xml/data_extraction_rules.xml new file mode 100644 index 000000000..9ee9997b0 --- /dev/null +++ b/app/src/main/res/xml/data_extraction_rules.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/apply-dictionary-renderer-to-feature-layer/build.gradle.kts b/apply-dictionary-renderer-to-feature-layer/build.gradle.kts deleted file mode 100644 index a37785d83..000000000 --- a/apply-dictionary-renderer-to-feature-layer/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.applydictionaryrenderertofeaturelayer" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.applydictionaryrenderertofeaturelayer" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/apply-dictionary-renderer-to-feature-layer/proguard-rules.pro b/apply-dictionary-renderer-to-feature-layer/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/apply-dictionary-renderer-to-feature-layer/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/AndroidManifest.xml b/apply-dictionary-renderer-to-feature-layer/src/main/AndroidManifest.xml deleted file mode 100644 index 264aa518e..000000000 --- a/apply-dictionary-renderer-to-feature-layer/src/main/AndroidManifest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/java/com/esri/arcgismaps/sample/applydictionaryrenderertofeaturelayer/DownloadActivity.kt b/apply-dictionary-renderer-to-feature-layer/src/main/java/com/esri/arcgismaps/sample/applydictionaryrenderertofeaturelayer/DownloadActivity.kt deleted file mode 100644 index cbc6b58ec..000000000 --- a/apply-dictionary-renderer-to-feature-layer/src/main/java/com/esri/arcgismaps/sample/applydictionaryrenderertofeaturelayer/DownloadActivity.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.esri.arcgismaps.sample.applydictionaryrenderertofeaturelayer - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // A stylx file that incorporates the MIL-STD-2525D symbol dictionary - "https://www.arcgis.com/home/item.html?id=c78b149a1d52414682c86a5feeb13d30", - // A mobile geodatabase created from the ArcGIS for Defense Military Overlay template - "https://www.arcgis.com/home/item.html?id=e0d41b4b409a49a5a7ba11939d8535dc" - ) - ) - } -} diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/java/com/esri/arcgismaps/sample/applydictionaryrenderertofeaturelayer/MainActivity.kt b/apply-dictionary-renderer-to-feature-layer/src/main/java/com/esri/arcgismaps/sample/applydictionaryrenderertofeaturelayer/MainActivity.kt deleted file mode 100644 index 6c0b8d2d4..000000000 --- a/apply-dictionary-renderer-to-feature-layer/src/main/java/com/esri/arcgismaps/sample/applydictionaryrenderertofeaturelayer/MainActivity.kt +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.applydictionaryrenderertofeaturelayer - -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.data.Geodatabase -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.layers.FeatureLayer -import com.arcgismaps.mapping.symbology.DictionaryRenderer -import com.arcgismaps.mapping.symbology.DictionarySymbolStyle -import com.esri.arcgismaps.sample.applydictionaryrenderertofeaturelayer.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // create and add a map with a navigation night basemap style - val map = ArcGISMap(BasemapStyle.ArcGISTopographic) - mapView.map = map - - // locate the .stylx file in the device - val styleFile = File(provisionPath, getString(R.string.mil2525d_stylx)) - // instantiate the dictionarySymbolStyle using the file path - val dictionarySymbolStyle = DictionarySymbolStyle.createFromFile(styleFile.absolutePath) - - // locate the .geodatabase file in the device - val geodatabaseFile = File(provisionPath, getString(R.string.militaryoverlay_geodatabase)) - // instantiate the geodatabase with the file path - val geodatabase = Geodatabase(geodatabaseFile.path) - - lifecycleScope.launch { - // load the dictionary symbol style - dictionarySymbolStyle.load().getOrElse { - return@launch showError("Error loading DictionarySymbolStyle: ${it.message}") - } - - // load the geodatabase - geodatabase.load().getOrElse { - showError("Error loading Geodatabase: ${it.message}") - } - - geodatabase.featureTables.forEach { geodatabaseFeatureTable -> - // load each geodatabaseFeatureTable and create featureLayer from it - geodatabaseFeatureTable.load().getOrElse { - return@launch showError("Error loading GeodatabaseFeatureTable: ${it.message}") - } - val featureLayer = FeatureLayer.createWithFeatureTable(geodatabaseFeatureTable) - featureLayer.load().getOrElse { - return@launch showError("Error loading FeatureLayer: ${it.message}") - } - // add featureLayer to the map's operational layer - mapView.map?.operationalLayers?.add(featureLayer) - - // create dictionaryRenderer using the dictionarySymbolStyle and apply it to the featureLayer's renderer - val dictionaryRenderer = DictionaryRenderer(dictionarySymbolStyle) - featureLayer.renderer = dictionaryRenderer - // get the featureLayer's envelope to set the map viewpoint - val extent = featureLayer.fullExtent - ?: return@launch showError("Error retrieving extent of the feature layer") - mapView.setViewpoint(Viewpoint(extent)) - } - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} - - diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml b/apply-dictionary-renderer-to-feature-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/apply-dictionary-renderer-to-feature-layer/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/drawable/ic_launcher_background.xml b/apply-dictionary-renderer-to-feature-layer/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/apply-dictionary-renderer-to-feature-layer/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-hdpi/ic_launcher.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-mdpi/ic_launcher.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xhdpi/ic_launcher.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/apply-dictionary-renderer-to-feature-layer/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-dictionary-renderer-to-feature-layer/src/main/res/values/strings.xml b/apply-dictionary-renderer-to-feature-layer/src/main/res/values/strings.xml deleted file mode 100644 index 6458b63ef..000000000 --- a/apply-dictionary-renderer-to-feature-layer/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Apply dictionary renderer to feature layer - /militaryoverlay.geodatabase - /mil2525d.stylx - diff --git a/apply-function-to-raster-from-service/.gitignore b/apply-function-to-raster-from-service/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/apply-function-to-raster-from-service/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/apply-function-to-raster-from-service/build.gradle.kts b/apply-function-to-raster-from-service/build.gradle.kts deleted file mode 100644 index 9d2c890ce..000000000 --- a/apply-function-to-raster-from-service/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.applyfunctiontorasterfromservice" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.applyfunctiontorasterfromservice" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/apply-function-to-raster-from-service/proguard-rules.pro b/apply-function-to-raster-from-service/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/apply-function-to-raster-from-service/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/apply-function-to-raster-from-service/src/main/AndroidManifest.xml b/apply-function-to-raster-from-service/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/apply-function-to-raster-from-service/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/apply-function-to-raster-from-service/src/main/java/com/esri/arcgismaps/sample/applyfunctiontorasterfromservice/MainActivity.kt b/apply-function-to-raster-from-service/src/main/java/com/esri/arcgismaps/sample/applyfunctiontorasterfromservice/MainActivity.kt deleted file mode 100644 index 56bc6c5ce..000000000 --- a/apply-function-to-raster-from-service/src/main/java/com/esri/arcgismaps/sample/applyfunctiontorasterfromservice/MainActivity.kt +++ /dev/null @@ -1,146 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.applyfunctiontorasterfromservice - -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.LoadStatus -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.layers.RasterLayer -import com.arcgismaps.raster.ImageServiceRaster -import com.arcgismaps.raster.Raster -import com.arcgismaps.raster.RasterFunction -import com.esri.arcgismaps.sample.applyfunctiontorasterfromservice.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val imageServiceRaster: ImageServiceRaster by lazy { - ImageServiceRaster(getString(R.string.image_service_raster_url)) - } - - private val imageRasterLayer: RasterLayer by lazy { - RasterLayer(imageServiceRaster) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // create and add a map with a dark gray basemap style - val map = ArcGISMap(BasemapStyle.ArcGISDarkGray) - mapView.map = map - - // add the imageRasterLayer to the map - addImageRasterLayer() - - activityMainBinding.apply { - rasterButton.setOnClickListener { - // update the raster with simplified hillshade - applyRasterFunction() - resetButton.isEnabled = true - rasterButton.isEnabled = false - } - resetButton.setOnClickListener { - // reset map to back to the RasterLayer - addImageRasterLayer() - resetButton.isEnabled = false - rasterButton.isEnabled = true - } - } - } - - /** - * Adds the image raster layer to the map and set's the viewpoint - * to the image server raster's bounding geometry - */ - private fun addImageRasterLayer() { - // clear and add the imageRasterLayer to the map - mapView.map?.operationalLayers?.apply { - clear() - add(imageRasterLayer) - } - - // collect the load status of the RasterLayer - lifecycleScope.launch { - imageRasterLayer.loadStatus.collect { loadStatus -> - if (loadStatus == LoadStatus.Loaded) { - // get the center point of the image service raster - val extentEnvelope = imageServiceRaster.serviceInfo?.fullExtent - ?: return@collect showError("Error retrieving the ArcGISImageServiceInfo") - // set the viewpoint of the map to the envelope - mapView.setViewpointGeometry(extentEnvelope) - } else if (loadStatus is LoadStatus.FailedToLoad) { - showError("Error loading image raster layer: ${loadStatus.error.message}") - } - } - } - } - - /** - * Create a hillshade layer using a custom JSON raster function. - */ - private fun applyRasterFunction() { - // create raster function from json string - val rasterFunction = RasterFunction.fromJsonOrNull(getString(R.string.hillshade_simplified)) - ?: return showError("Error creating a raster function object from JSON") - - // get parameter name value pairs used by hillside - val rasterFunctionArguments = rasterFunction.arguments - ?: return showError("Raster function arguments is null") - - // get a list of raster names associated with the raster function - val rasterNames = rasterFunctionArguments.rasterNames - // check if raster function arguments contains raster variable names - if(rasterNames.isNotEmpty()){ - // using the first raster variable name - rasterFunctionArguments.setRaster(rasterNames[0], imageServiceRaster) - // create raster as raster layer - val hillshadeRaster = Raster.createWithRasterFunction(rasterFunction) - val hillshadeLayer = RasterLayer(hillshadeRaster) - // clear and add the layer to the map - mapView.map?.operationalLayers?.add(hillshadeLayer) - } else{ - showError("Raster function arguments does not contain raster variable names") - } - - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/apply-function-to-raster-from-service/src/main/res/drawable-v24/ic_launcher_foreground.xml b/apply-function-to-raster-from-service/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/apply-function-to-raster-from-service/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/apply-function-to-raster-from-service/src/main/res/drawable/ic_launcher_background.xml b/apply-function-to-raster-from-service/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/apply-function-to-raster-from-service/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/apply-function-to-raster-from-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/apply-function-to-raster-from-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/apply-function-to-raster-from-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/apply-function-to-raster-from-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-hdpi/ic_launcher.png b/apply-function-to-raster-from-service/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-hdpi/ic_launcher_round.png b/apply-function-to-raster-from-service/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-mdpi/ic_launcher.png b/apply-function-to-raster-from-service/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-mdpi/ic_launcher_round.png b/apply-function-to-raster-from-service/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-xhdpi/ic_launcher.png b/apply-function-to-raster-from-service/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/apply-function-to-raster-from-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-xxhdpi/ic_launcher.png b/apply-function-to-raster-from-service/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/apply-function-to-raster-from-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/apply-function-to-raster-from-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/apply-function-to-raster-from-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/apply-function-to-raster-from-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/apply-function-to-raster-from-service/src/main/res/values/strings.xml b/apply-function-to-raster-from-service/src/main/res/values/strings.xml deleted file mode 100644 index 772070487..000000000 --- a/apply-function-to-raster-from-service/src/main/res/values/strings.xml +++ /dev/null @@ -1,22 +0,0 @@ - - Apply function to raster from service - https://sampleserver6.arcgisonline.com/arcgis/rest/services/NLCDLandCover2001/ImageServer - - { - \"raster_function_arguments\": - { - \"z_factor\":{\"double\":25.0,\"type\":\"Raster_function_variable\"}, - \"slope_type\":{\"raster_slope_type\":\"none\",\"type\":\"Raster_function_variable\"}, - \"azimuth\":{\"double\":315,\"type\":\"Raster_function_variable\"}, - \"altitude\":{\"double\":45,\"type\":\"Raster_function_variable\"}, - \"type\":\"Raster_function_arguments\", - \"raster\":{\"name\":\"raster\",\"is_raster\":true,\"type\":\"Raster_function_variable\"}, - \"nbits\":{\"int\":8,\"type\":\"Raster_function_variable\"} - }, - \"raster_function\":{\"type\":\"Hillshade_function\"}, - \"type\":\"Raster_function_template\" - } - - Apply Layer - Reset - diff --git a/authenticate-with-oauth/.gitignore b/authenticate-with-oauth/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/authenticate-with-oauth/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/authenticate-with-oauth/build.gradle.kts b/authenticate-with-oauth/build.gradle.kts deleted file mode 100644 index bf36a62a4..000000000 --- a/authenticate-with-oauth/build.gradle.kts +++ /dev/null @@ -1,55 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.authenticatewithoauth" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.authenticatewithoauth" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) - implementation(libs.arcgis.maps.kotlin.toolkit.authentication) -} diff --git a/authenticate-with-oauth/proguard-rules.pro b/authenticate-with-oauth/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/authenticate-with-oauth/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/authenticate-with-oauth/src/main/AndroidManifest.xml b/authenticate-with-oauth/src/main/AndroidManifest.xml deleted file mode 100644 index 83e5566cb..000000000 --- a/authenticate-with-oauth/src/main/AndroidManifest.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/authenticate-with-oauth/src/main/java/com/esri/arcgismaps/sample/authenticatewithoauth/MainActivity.kt b/authenticate-with-oauth/src/main/java/com/esri/arcgismaps/sample/authenticatewithoauth/MainActivity.kt deleted file mode 100644 index 784fceabb..000000000 --- a/authenticate-with-oauth/src/main/java/com/esri/arcgismaps/sample/authenticatewithoauth/MainActivity.kt +++ /dev/null @@ -1,65 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.authenticatewithoauth - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import androidx.lifecycle.viewmodel.compose.viewModel -import com.arcgismaps.toolkit.authentication.DialogAuthenticator -import com.esri.arcgismaps.sample.authenticatewithoauth.components.MapViewModel -import com.esri.arcgismaps.sample.authenticatewithoauth.screens.MainScreen -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContent { - SampleAppTheme { - AuthenticateWithOAuthApp() - } - } - } - - @Composable - private fun AuthenticateWithOAuthApp() { - - // create a ViewModel to handle interactions - val mapViewModel: MapViewModel = viewModel() - - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - // Displays appropriate Authentication UI when an authentication challenge is issued. - // Because the authenticatorState has an oAuthUserConfiguration set, authentication - // challenges will happen via OAuth. - // Call the DialogAuthenticator composable function at the top level of your view - // hierarchy, for example at the same level as MainScreen(). This ensures that - // authentication handling is set up before any components of the ArcGIS Maps SDK that - // may require authentication are used. - DialogAuthenticator(authenticatorState = mapViewModel.authenticatorState) - } - } -} diff --git a/authenticate-with-oauth/src/main/res/drawable-v24/ic_launcher_foreground.xml b/authenticate-with-oauth/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/authenticate-with-oauth/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/authenticate-with-oauth/src/main/res/drawable/ic_launcher_background.xml b/authenticate-with-oauth/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/authenticate-with-oauth/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/authenticate-with-oauth/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/authenticate-with-oauth/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/authenticate-with-oauth/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/authenticate-with-oauth/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/authenticate-with-oauth/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/authenticate-with-oauth/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/authenticate-with-oauth/src/main/res/mipmap-hdpi/ic_launcher.png b/authenticate-with-oauth/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-hdpi/ic_launcher_round.png b/authenticate-with-oauth/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-mdpi/ic_launcher.png b/authenticate-with-oauth/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-mdpi/ic_launcher_round.png b/authenticate-with-oauth/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-xhdpi/ic_launcher.png b/authenticate-with-oauth/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/authenticate-with-oauth/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-xxhdpi/ic_launcher.png b/authenticate-with-oauth/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/authenticate-with-oauth/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/authenticate-with-oauth/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/authenticate-with-oauth/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/authenticate-with-oauth/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/authenticate-with-oauth/src/main/res/values/strings.xml b/authenticate-with-oauth/src/main/res/values/strings.xml deleted file mode 100644 index cc50e7c7d..000000000 --- a/authenticate-with-oauth/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Authenticate with OAuth - diff --git a/browse-building-floors/.gitignore b/browse-building-floors/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/browse-building-floors/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/browse-building-floors/build.gradle.kts b/browse-building-floors/build.gradle.kts deleted file mode 100644 index 970e24e42..000000000 --- a/browse-building-floors/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.browsebuildingfloors" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.browsebuildingfloors" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/browse-building-floors/proguard-rules.pro b/browse-building-floors/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/browse-building-floors/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/browse-building-floors/src/main/AndroidManifest.xml b/browse-building-floors/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/browse-building-floors/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/browse-building-floors/src/main/java/com/esri/arcgismaps/sample/browsebuildingfloors/MainActivity.kt b/browse-building-floors/src/main/java/com/esri/arcgismaps/sample/browsebuildingfloors/MainActivity.kt deleted file mode 100644 index 66f296731..000000000 --- a/browse-building-floors/src/main/java/com/esri/arcgismaps/sample/browsebuildingfloors/MainActivity.kt +++ /dev/null @@ -1,186 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.browsebuildingfloors - -import android.content.Context -import android.os.Bundle -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.AdapterView -import android.widget.ArrayAdapter -import android.widget.TextView -import androidx.annotation.LayoutRes -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.PortalItem -import com.arcgismaps.mapping.floor.FloorLevel -import com.arcgismaps.mapping.floor.FloorManager -import com.arcgismaps.portal.Portal -import com.esri.arcgismaps.sample.browsebuildingfloors.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val currentFloorTV by lazy { - activityMainBinding.selectedFloorTV - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // load the portal and create a map from the portal item - val portalItem = PortalItem( - Portal("https://www.arcgis.com/"), - "f133a698536f44c8884ad81f80b6cfc7" - ) - - // set the map to be displayed in the layout's MapView - val map = ArcGISMap(portalItem) - mapView.map = map - - lifecycleScope.launch { - //load the portal item on the map - map.load().getOrElse { - showError("Error loading map" + it.message.toString()) - return@launch - } - - // load the web map's floor manager - val floorManager = - map.floorManager ?: return@launch showError("Map is not floor-aware") - floorManager.load().getOrElse { - showError("Error loading floor manager" + it.message.toString()) - return@launch - } - - // set up dropdown and initial floor level to ground floor - initializeFloorDropdown(floorManager) - } - } - - /** - * Set and update the floor dropdown. Shows the currently selected floor - * and hides the other floors using [floorManager]. - */ - private fun initializeFloorDropdown(floorManager: FloorManager) { - // enable the dropdown view - activityMainBinding.dropdownMenu.isEnabled = true - - // Select the ground floor using `verticalOrder`. - // The floor at index 0 might not have a vertical order of 0 if, - // for example, the building starts with basements. - // To select the ground floor, we can search for a level with a - // `verticalOrder` of 0. You can also use level ID, number or name - // to locate a floor. - val firstFloorIndex = floorManager.levels.indexOf( - floorManager.levels.first { it.verticalOrder == 0 } - ) - - currentFloorTV.apply { - // set the displayed floor to the first floor - setSelection(firstFloorIndex) - - // set the name of the first floor - setText(floorManager.levels[firstFloorIndex].longName) - - // set the dropdown adapter for the floor selection - setAdapter( - FloorsAdapter( - this@MainActivity, - android.R.layout.simple_list_item_1, - floorManager.levels - ) - ) - - // handle on dropdown item selected - onItemClickListener = - AdapterView.OnItemClickListener { _, _, position, _ -> - // set all the floors to invisible to reset the floorManager - floorManager.levels.forEach { floorLevel -> - floorLevel.isVisible = false - } - - // set the currently selected floor to be visible - floorManager.levels[position].isVisible = true - - // set the floor name - currentFloorTV.setText(floorManager.levels[position].longName) - } - } - } - - /** - * Adapter to display a list [floorLevels] - */ - private class FloorsAdapter( - context: Context, - @LayoutRes private val layoutResourceId: Int, - private val floorLevels: List - ) : ArrayAdapter(context, layoutResourceId, floorLevels) { - - private val mLayoutInflater: LayoutInflater = - context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater - - override fun getCount(): Int { - return floorLevels.size - } - - override fun getItem(position: Int): FloorLevel { - return floorLevels[position] - } - - override fun getItemId(position: Int): Long { - return position.toLong() - } - - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - // bind the view to the layout inflater - val view = convertView ?: mLayoutInflater.inflate(layoutResourceId, parent, false) - val dropdownItemTV = view.findViewById(android.R.id.text1) - - // bind the long name of the floor to it's respective text view - dropdownItemTV.text = floorLevels[position].longName - return view - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/browse-building-floors/src/main/res/drawable-v24/ic_launcher_foreground.xml b/browse-building-floors/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/browse-building-floors/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/browse-building-floors/src/main/res/drawable/ic_launcher_background.xml b/browse-building-floors/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/browse-building-floors/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/browse-building-floors/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/browse-building-floors/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/browse-building-floors/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/browse-building-floors/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/browse-building-floors/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/browse-building-floors/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/browse-building-floors/src/main/res/mipmap-hdpi/ic_launcher.png b/browse-building-floors/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-hdpi/ic_launcher_round.png b/browse-building-floors/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-mdpi/ic_launcher.png b/browse-building-floors/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-mdpi/ic_launcher_round.png b/browse-building-floors/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-xhdpi/ic_launcher.png b/browse-building-floors/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/browse-building-floors/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-xxhdpi/ic_launcher.png b/browse-building-floors/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/browse-building-floors/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/browse-building-floors/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/browse-building-floors/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/browse-building-floors/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/browse-building-floors/src/main/res/values/strings.xml b/browse-building-floors/src/main/res/values/strings.xml deleted file mode 100644 index 70d0c6f2f..000000000 --- a/browse-building-floors/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Browse building floors - Select the floor to display - diff --git a/build-logic/.gitignore b/build-logic/.gitignore new file mode 100644 index 000000000..00fd4dddb --- /dev/null +++ b/build-logic/.gitignore @@ -0,0 +1,2 @@ +/build +/.gradle \ No newline at end of file diff --git a/add-3d-tiles-layer/.gitignore b/build-logic/convention/.gitignore similarity index 100% rename from add-3d-tiles-layer/.gitignore rename to build-logic/convention/.gitignore diff --git a/build-logic/convention/build.gradle.kts b/build-logic/convention/build.gradle.kts new file mode 100644 index 000000000..5934b0c57 --- /dev/null +++ b/build-logic/convention/build.gradle.kts @@ -0,0 +1,57 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +plugins { + `kotlin-dsl` +} + +group = "com.esri.arcgismaps.kotlin.build_logic.convention" + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +tasks.withType().configureEach { + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } +} + +dependencies { + compileOnly(libs.android.gradlePlugin) + compileOnly(libs.android.tools.common) + compileOnly(libs.kotlin.gradlePlugin) + compileOnly(libs.ksp.gradlePlugin) +} + +tasks { + validatePlugins { + enableStricterValidation = true + failOnWarning = true + } +} + +gradlePlugin { + plugins { + register("androidApplicationComposing") { + id = "arcgismaps.android.application.compose" + implementationClass = "AndroidApplicationComposeConventionPlugin" + } + register("androidApplication") { + id = "arcgismaps.android.application" + implementationClass = "AndroidApplicationConventionPlugin" + } + register("androidLibraryCompose") { + id = "arcgismaps.android.library.compose" + implementationClass = "AndroidLibraryComposeConventionPlugin" + } + register("androidLibrary") { + id = "arcgismaps.android.library" + implementationClass = "AndroidLibraryConventionPlugin" + } + register("arcgismapsKotlinSample") { + id = "arcgismaps.kotlin.sample" + implementationClass = "ArcGISMapsKotlinSampleConventionPlugin" + } + } +} diff --git a/build-logic/convention/src/main/AndroidManifest.xml b/build-logic/convention/src/main/AndroidManifest.xml new file mode 100644 index 000000000..a5918e68a --- /dev/null +++ b/build-logic/convention/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/build-logic/convention/src/main/java/AndroidApplicationComposeConventionPlugin.kt b/build-logic/convention/src/main/java/AndroidApplicationComposeConventionPlugin.kt new file mode 100644 index 000000000..06dc52b38 --- /dev/null +++ b/build-logic/convention/src/main/java/AndroidApplicationComposeConventionPlugin.kt @@ -0,0 +1,19 @@ +import com.android.build.api.dsl.ApplicationExtension +import com.esri.arcgismaps.kotlin.build_logic.convention.configureAndroidCompose +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +class AndroidApplicationComposeConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.application") + apply("org.jetbrains.kotlin.android") + apply("org.jetbrains.kotlin.plugin.compose") + } + val extension = extensions.getByType() + configureAndroidCompose(extension) + } + } +} diff --git a/build-logic/convention/src/main/java/AndroidApplicationConventionPlugin.kt b/build-logic/convention/src/main/java/AndroidApplicationConventionPlugin.kt new file mode 100644 index 000000000..67049682e --- /dev/null +++ b/build-logic/convention/src/main/java/AndroidApplicationConventionPlugin.kt @@ -0,0 +1,53 @@ +import com.android.build.api.dsl.ApplicationExtension +import com.esri.arcgismaps.kotlin.build_logic.convention.configureKotlinAndroid +import com.esri.arcgismaps.kotlin.build_logic.convention.libs +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.get + +class AndroidApplicationConventionPlugin: Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.application") + apply("org.jetbrains.kotlin.android") + } + + extensions.configure { + configureKotlinAndroid(this) + compileSdk = 35 + defaultConfig { + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + minSdk = libs.findVersion("minSdk").get().toString().toInt() + targetSdk = libs.findVersion("targetSdk").get().toString().toInt() + versionCode = libs.findVersion("versionCode").get().toString().toInt() + versionName = libs.findVersion("versionName").get().toString() + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } + + // Add the custom assets directory to the app module's assets build. + sourceSets["main"].assets.srcDirs(layout.buildDirectory.dir("sampleAssets/")) + } + } + } +} diff --git a/build-logic/convention/src/main/java/AndroidLibraryComposeConventionPlugin.kt b/build-logic/convention/src/main/java/AndroidLibraryComposeConventionPlugin.kt new file mode 100644 index 000000000..c20d05e75 --- /dev/null +++ b/build-logic/convention/src/main/java/AndroidLibraryComposeConventionPlugin.kt @@ -0,0 +1,19 @@ +import com.android.build.api.dsl.LibraryExtension +import com.esri.arcgismaps.kotlin.build_logic.convention.configureAndroidCompose +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +class AndroidLibraryComposeConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.library") + apply("org.jetbrains.kotlin.android") + apply("org.jetbrains.kotlin.plugin.compose") + } + val extension = extensions.getByType() + configureAndroidCompose(extension) + } + } +} diff --git a/build-logic/convention/src/main/java/AndroidLibraryConventionPlugin.kt b/build-logic/convention/src/main/java/AndroidLibraryConventionPlugin.kt new file mode 100644 index 000000000..53d5fc774 --- /dev/null +++ b/build-logic/convention/src/main/java/AndroidLibraryConventionPlugin.kt @@ -0,0 +1,58 @@ +import com.android.build.gradle.LibraryExtension +import com.esri.arcgismaps.kotlin.build_logic.convention.configureKotlinAndroid +import com.esri.arcgismaps.kotlin.build_logic.convention.implementation +import com.esri.arcgismaps.kotlin.build_logic.convention.libs +import com.esri.arcgismaps.kotlin.build_logic.convention.testImplementation +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.configure +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.kotlin + +class AndroidLibraryConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + with(pluginManager) { + apply("com.android.library") + apply("org.jetbrains.kotlin.android") + } + + extensions.configure { + configureKotlinAndroid(this) + compileSdk = 35 + defaultConfig { + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + minSdk = libs.findVersion("minSdk").get().toString().toInt() + lint.targetSdk = libs.findVersion("targetSdk").get().toString().toInt() + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } + } + + dependencies { + testImplementation(kotlin("test")) + // External libraries + implementation(libs.findLibrary("androidx-constraintlayout").get()) + implementation(libs.findLibrary("androidx-appcompat").get()) + implementation(libs.findLibrary("android-material").get()) + } + } + } +} diff --git a/build-logic/convention/src/main/java/ArcGISMapsKotlinSampleConventionPlugin.kt b/build-logic/convention/src/main/java/ArcGISMapsKotlinSampleConventionPlugin.kt new file mode 100644 index 000000000..1307ca462 --- /dev/null +++ b/build-logic/convention/src/main/java/ArcGISMapsKotlinSampleConventionPlugin.kt @@ -0,0 +1,23 @@ +import com.esri.arcgismaps.kotlin.build_logic.convention.implementation +import com.esri.arcgismaps.kotlin.build_logic.convention.libs +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies +import org.gradle.kotlin.dsl.project + +class ArcGISMapsKotlinSampleConventionPlugin : Plugin { + override fun apply(target: Project) { + with(target) { + dependencies { + // ArcGIS Maps SDK for Kotlin + implementation(libs.findLibrary("arcgis-maps-kotlin").get()) + // Get the Toolkit BOM + implementation(platform(libs.findLibrary("arcgis-maps-kotlin-toolkit-bom").get())) + // ArcGIS Maps SDK Toolkit GeoView Compose + implementation(libs.findLibrary("arcgis-maps-kotlin-toolkit-geoview-compose").get()) + // Local project common samples library + implementation(project(":samples-lib")) + } + } + } +} diff --git a/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/AndroidCompose.kt b/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/AndroidCompose.kt new file mode 100644 index 000000000..feef379ec --- /dev/null +++ b/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/AndroidCompose.kt @@ -0,0 +1,37 @@ +package com.esri.arcgismaps.kotlin.build_logic.convention + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.Project +import org.gradle.kotlin.dsl.dependencies + +/** + * Extension to use compose configurations and dependencies + */ +internal fun Project.configureAndroidCompose( + commonExtension: CommonExtension<*, *, *, *, *, *>, +) { + commonExtension.apply { + buildFeatures { + compose = true + } + + composeOptions { + kotlinCompilerExtensionVersion = libs.findVersion("kotlinCompilerExt").get().toString() + } + + dependencies { + val composeBom = libs.findLibrary("androidx-compose-bom").get() + implementation(platform(composeBom)) + androidTestImplementation(platform(composeBom)) + implementation(libs.findLibrary("androidx-activity-compose").get()) + implementation(libs.findLibrary("androidx-compose-material3").get()) + implementation(libs.findLibrary("androidx-lifecycle-viewmodel-compose").get()) + implementation(libs.findLibrary("androidx-compose-ui-tooling-preview").get()) + debugImplementation(libs.findLibrary("androidx-compose-ui-tooling").get()) + debugImplementation(libs.findLibrary("androidx-compose-ui-test-manifest").get()) + androidTestImplementation(libs.findLibrary("androidx-compose-ui-test").get()) + androidTestImplementation(libs.findLibrary("androidx-compose-ui-test-junit4").get()) + + } + } +} diff --git a/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/KotlinAndroid.kt b/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/KotlinAndroid.kt new file mode 100644 index 000000000..1e6d69482 --- /dev/null +++ b/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/KotlinAndroid.kt @@ -0,0 +1,56 @@ +package com.esri.arcgismaps.kotlin.build_logic.convention + +import com.android.build.api.dsl.CommonExtension +import org.gradle.api.JavaVersion +import org.gradle.api.Project +import org.gradle.kotlin.dsl.provideDelegate +import org.gradle.kotlin.dsl.withType +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +/** + * Extension to use Android Kotlin configurations and dependencies + */ +internal fun Project.configureKotlinAndroid( + commonExtension: CommonExtension<*, *, *, *, *, *>, +) { + commonExtension.apply { + compileSdk = libs.findVersion("targetSdk").get().toString().toInt() + + defaultConfig { + buildConfigField("String", "ACCESS_TOKEN", project.properties["ACCESS_TOKEN"].toString()) + minSdk = libs.findVersion("minSdk").get().toString().toInt() + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + } + + configureKotlin() +} + +/** + * Configure base Kotlin options + */ +private fun Project.configureKotlin() { + tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_17) + // Treat all Kotlin warnings as errors (disabled by default) + // Override by setting warningsAsErrors=true in your ~/.gradle/gradle.properties + val warningsAsErrors: String? by project + allWarningsAsErrors.set(warningsAsErrors.toBoolean()) + freeCompilerArgs.set( + listOf( + "-opt-in=kotlin.RequiresOptIn", + // Enable experimental coroutines APIs, including Flow + "-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi", + "-opt-in=kotlinx.coroutines.FlowPreview", + "-Xcontext-receivers", + ) + ) + } + } +} diff --git a/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/ProjectExtensions.kt b/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/ProjectExtensions.kt new file mode 100644 index 000000000..26af71d39 --- /dev/null +++ b/build-logic/convention/src/main/java/com/esri/arcgismaps/kotlin/build_logic/convention/ProjectExtensions.kt @@ -0,0 +1,28 @@ +package com.esri.arcgismaps.kotlin.build_logic.convention + +import org.gradle.api.Project +import org.gradle.api.artifacts.Dependency +import org.gradle.api.artifacts.VersionCatalog +import org.gradle.api.artifacts.VersionCatalogsExtension +import org.gradle.api.artifacts.dsl.DependencyHandler +import org.gradle.kotlin.dsl.getByType + +fun DependencyHandler.testImplementation(dependencyNotation: Any): Dependency? = + add("testImplementation", dependencyNotation) + +fun DependencyHandler.testRuntimeOnly(dependencyNotation: Any): Dependency? = + add("testRuntimeOnly", dependencyNotation) + +fun DependencyHandler.implementation(dependencyNotation: Any): Dependency? = + add("implementation", dependencyNotation) + +fun DependencyHandler.androidTestImplementation(dependencyNotation: Any): Dependency? = + add("androidTestImplementation", dependencyNotation) + +fun DependencyHandler.debugImplementation(dependencyNotation: Any): Dependency? = + add("debugImplementation", dependencyNotation) + +val Project.libs + get(): VersionCatalog = extensions + .getByType() + .named("libs") diff --git a/build-logic/gradle.properties b/build-logic/gradle.properties new file mode 100644 index 000000000..6977b7191 --- /dev/null +++ b/build-logic/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configureondemand=true \ No newline at end of file diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts new file mode 100644 index 000000000..2907fbfb8 --- /dev/null +++ b/build-logic/settings.gradle.kts @@ -0,0 +1,14 @@ +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} + +rootProject.name = "build-logic" +include(":convention") diff --git a/build.gradle.kts b/build.gradle.kts index dabae1534..7f92fb744 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,61 +1,27 @@ -import com.android.build.gradle.BaseExtension -import java.net.URL - -buildscript { - repositories { - google() - mavenCentral() - } - dependencies { - classpath("com.android.tools.build:gradle:${libs.versions.gradleVersion.get()}") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${libs.versions.kotlinVersion.get()}") - } +// Top-level build file where you can add configuration options common to all sub-projects/modules. +plugins { + alias(libs.plugins.android.application) apply false + alias(libs.plugins.jetbrains.kotlin.android) apply false + alias(libs.plugins.android.library) apply false + alias(libs.plugins.compose.compiler) apply false + alias(libs.plugins.gradle.secrets) apply false + alias(libs.plugins.ksp) apply false + alias(libs.plugins.kotlin.serialization) apply false } -subprojects { - afterEvaluate { - if (hasProperty("dependencies")) { - dependencies { - val implementation by configurations - implementation(libs.androidx.appcompat) - implementation(libs.stdlib.jdk8) - implementation(libs.arcgis.maps.kotlin) - implementation(libs.androidx.multidex) - } - } - - extensions.findByType(BaseExtension::class)?.let { android -> - android.compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - android.defaultConfig { - multiDexEnabled = true - } - android.packagingOptions { - resources { - excludes.add("META-INF/DEPENDENCIES") - } - } - } - - tasks.withType { - kotlinOptions { - jvmTarget = "17" - } +buildscript { + // if a "build" property is set from the command line like: "-D build=100.X.X-XXXX" + if (System.getProperty("build") != null) { + // override versions in libs.versions.toml file + rootProject.extra.apply { + set("arcgisMapsKotlinVersion", System.getProperty("build")) + set("arcgisToolkitVersion", System.getProperty("build")) + set("versionName", System.getProperty("build")) } - - } -} - -tasks.register("apiKey") { - doLast { - val apiKeyFile = File("${System.getProperty("user.home")}/.gradle/gradle.properties") - if (!apiKeyFile.exists()) { - print("Go to the ${URL("https://links.esri.com/create-an-api-key")} to obtain a new API key access token. Ensure the following privileges are enabled: Basemaps, Geocoding, and Routing.") - print("Add your API Key to ${System.getProperty("user.home")}\\.gradle\\gradle.properties.") - val apiKeyFileContents = "API_KEY = " - apiKeyFile.writeText(apiKeyFileContents) + } else { + // use versions in libs.versions.toml file + rootProject.extra.apply { + set("arcgisMapsKotlinVersion", libs.versions.arcgisMapsKotlinVersion.get()) } } -} +} \ No newline at end of file diff --git a/change-camera-controller/.gitignore b/change-camera-controller/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/change-camera-controller/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/change-camera-controller/build.gradle.kts b/change-camera-controller/build.gradle.kts deleted file mode 100644 index 3f1d4ea30..000000000 --- a/change-camera-controller/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.changecameracontroller" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.changecameracontroller" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/change-camera-controller/proguard-rules.pro b/change-camera-controller/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/change-camera-controller/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/change-camera-controller/src/main/AndroidManifest.xml b/change-camera-controller/src/main/AndroidManifest.xml deleted file mode 100644 index 1bf01ae77..000000000 --- a/change-camera-controller/src/main/AndroidManifest.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/change-camera-controller/src/main/java/com/esri/arcgismaps/sample/changecameracontroller/MainActivity.kt b/change-camera-controller/src/main/java/com/esri/arcgismaps/sample/changecameracontroller/MainActivity.kt deleted file mode 100644 index 8a028d9c3..000000000 --- a/change-camera-controller/src/main/java/com/esri/arcgismaps/sample/changecameracontroller/MainActivity.kt +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2023 Esri - * - * 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. - * - */ -package com.esri.arcgismaps.sample.changecameracontroller - -import android.os.Bundle -import android.util.Log -import android.widget.ArrayAdapter -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISScene -import com.arcgismaps.mapping.ArcGISTiledElevationSource -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.symbology.ModelSceneSymbol -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.SurfacePlacement -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.OrbitLocationCameraController -import com.arcgismaps.mapping.view.OrbitGeoElementCameraController -import com.arcgismaps.mapping.view.GlobeCameraController -import com.arcgismaps.mapping.view.Camera -import com.esri.arcgismaps.sample.changecameracontroller.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.withContext -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.ensureActive -import java.io.File -import java.io.FileOutputStream - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val sceneView by lazy { - activityMainBinding.sceneView - } - - // options dropdown view for the camera controller types - private val cameraControllerOptionsView by lazy { - // create an array adapter data source using the list of camera controller modes - val arrayAdapter = ArrayAdapter( - this, - com.esri.arcgismaps.sample.sampleslib.R.layout.custom_dropdown_item, - CameraControllerMode.getValuesByDisplayName() - ) - activityMainBinding.bottomListItems.apply { - setAdapter(arrayAdapter) - } - } - - // list of available asset files - private val assetFiles by lazy { - resources.getStringArray(R.array.asset_files).toList() - } - - // the graphic representing the airplane 3d model - private val airplane3DGraphic by lazy { - // location for the target graphic - val point = Point(-109.937516, 38.456714, 5000.0, SpatialReference.wgs84()) - // create the graphic with the target location - Graphic(point) - } - - // camera controller which orbits the plane graphic - private val orbitPlaneCameraController by lazy { - // instantiate a new camera controller with a distance from airplane graphic - OrbitGeoElementCameraController(airplane3DGraphic, 100.0).apply { - // set a relative pitch to the target - setCameraPitchOffset(3.0) - // set a relative heading to the target - setCameraHeadingOffset(150.0) - } - } - - // camera controller which orbits a target location - private val orbitLocationCameraController by lazy { - // target location for the camera controller - val point = Point(-109.929589, 38.437304, 1700.0, SpatialReference.wgs84()) - // instantiate a new camera controller with a distance from the target - OrbitLocationCameraController(point, 5000.0).apply { - // set a relative pitch to the target - setCameraPitchOffset(3.0) - // set a relative heading to the target - setCameraHeadingOffset(150.0) - } - } - - // camera controller for free roam navigation - private val globeCameraController = GlobeCameraController() - - // camera looking at the Upheaval Dome crater in Utah - private val defaultCamera = Camera( - latitude = 38.459291, - longitude = -109.937576, - altitude = 5500.0, - heading = 150.0, - pitch = 20.0, - roll = 0.0 - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(sceneView) - - // create and add a scene with an imagery basemap style - val terrainScene = ArcGISScene(BasemapStyle.ArcGISImagery).apply { - // add an elevation data source to the base surface - baseSurface.elevationSources.add( - ArcGISTiledElevationSource(getString(R.string.elevation_service_url)) - ) - } - - // graphics overlay for the scene to draw the 3d graphics on - val graphicsOverlay = GraphicsOverlay().apply { - // set the altitude values in the scene to be absolute - sceneProperties.surfacePlacement = SurfacePlacement.Absolute - // add the airplane 3d graphic to the graphics overlay - graphics.add(airplane3DGraphic) - } - - sceneView.apply { - // set the scene to the SceneView - scene = terrainScene - // add the graphics overlay to the SceneView - graphicsOverlays.add(graphicsOverlay) - } - - lifecycleScope.launch { - // if the map load failed show an error and return - terrainScene.load().onFailure { - showError("Failed to load the scene: ${it.message}") - return@launch - } - // set the sceneView viewpoint to the default camera - sceneView.setViewpointCamera(defaultCamera) - // copy the airplane model assets to the cache directory if needed - copyAssetsToCache(assetFiles, cacheDir, false) - // load the airplane model file and update the the airplane3DGraphic - loadModel(getString(R.string.bristol_model_file), airplane3DGraphic) - } - - // set the click listener for the options dropdown view - cameraControllerOptionsView.setOnItemClickListener { parent, _, position, _ -> - // get the selected camera mode item - val selectedItem = parent.getItemAtPosition(position) as String - // get the CameraControllerMode from the selected item - val mode = CameraControllerMode.getValue(selectedItem) - // update the camera controller - setCameraControllerMode(mode) - } - } - - /** - * Loads a [ModelSceneSymbol] from the [filename] in [getCacheDir] and updates the [graphic]. - */ - private suspend fun loadModel(filename: String, graphic: Graphic) { - val modelFile = File(cacheDir, filename) - if (modelFile.exists()) { - // create a new ModelSceneSymbol with the file - val modelSceneSymbol = ModelSceneSymbol(modelFile.path).apply { - heading = 45f - } - // if the symbol load failed show and error and return - modelSceneSymbol.load().onFailure { - return showError("Error loading airplane model: ${it.message}") - } - // update the graphic's symbol - graphic.symbol = modelSceneSymbol - } else { - showError("Error loading airplane model: file does not exist.") - } - } - - /** - * Updates the SceneView's camera controller based on the [mode] specified. - */ - private fun setCameraControllerMode(mode: CameraControllerMode) { - sceneView.cameraController = when (mode) { - CameraControllerMode.OrbitPlane -> orbitPlaneCameraController - CameraControllerMode.OrbitLocation -> orbitLocationCameraController - CameraControllerMode.Globe -> globeCameraController - } - } - - /** - * Copies the list of [assets] files from the assets folder to a given [cache] directory. This - * suspending function runs on the [Dispatchers.IO] context. If [overwrite] is true, any assets - * already in the [cache] directory are overwritten, otherwise copy is skipped. - */ - private suspend fun copyAssetsToCache( - assets: List, - cache: File, - overwrite: Boolean - ) = withContext(Dispatchers.IO) { - // get the AssetManager - val assetManager = applicationContext.assets ?: return@withContext - assets.forEach { assetName -> - // check for cancellation before reading/writing the asset files - ensureActive() - try { - // create an output file in the cache directory - val outFile = File(cache, assetName) - // if the output file doesn't exist or overwrite is enabled - if (!outFile.exists() || overwrite) { - // create an input stream to the asset - assetManager.open(assetName).use { inputStream -> - // create an file output stream to the output file - FileOutputStream(outFile).use { outputStream -> - // copy the input file stream to the output file stream - inputStream.copyTo(outputStream) - } - Log.i(localClassName, "$assetName copied to cache.") - } - } else { - Log.i(localClassName, "$assetName already in cache, skipping copy.") - } - } catch (exception: Exception) { - showError("Error caching asset :${exception.message}") - } - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(sceneView, message, Snackbar.LENGTH_SHORT).show() - } -} - -// enum to keep track of the selected camera controller mode set for the SceneView -enum class CameraControllerMode(val displayName: String) { - OrbitPlane("Orbit camera around a plane model"), - OrbitLocation("Orbit camera around a crater"), - Globe("Free pan around the globe"); - - companion object { - /** - * Returns a List containing the [displayName] property of this enum type. - * */ - fun getValuesByDisplayName(): List { - return entries.map { cameraControllerMode -> - cameraControllerMode.displayName - } - } - - /** - * Returns the enum constant of this type with the specified [displayName] property. - */ - fun getValue(displayName: String): CameraControllerMode { - return entries.first { - it.displayName == displayName - } - } - } -} diff --git a/change-camera-controller/src/main/res/drawable-v24/ic_launcher_foreground.xml b/change-camera-controller/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/change-camera-controller/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/change-camera-controller/src/main/res/drawable/ic_launcher_background.xml b/change-camera-controller/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/change-camera-controller/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/change-camera-controller/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/change-camera-controller/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/change-camera-controller/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/change-camera-controller/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/change-camera-controller/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/change-camera-controller/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/change-camera-controller/src/main/res/mipmap-hdpi/ic_launcher.png b/change-camera-controller/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-hdpi/ic_launcher_round.png b/change-camera-controller/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-mdpi/ic_launcher.png b/change-camera-controller/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-mdpi/ic_launcher_round.png b/change-camera-controller/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-xhdpi/ic_launcher.png b/change-camera-controller/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/change-camera-controller/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-xxhdpi/ic_launcher.png b/change-camera-controller/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/change-camera-controller/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/change-camera-controller/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/change-camera-controller/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/change-camera-controller/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-camera-controller/src/main/res/values/strings.xml b/change-camera-controller/src/main/res/values/strings.xml deleted file mode 100644 index 226b15171..000000000 --- a/change-camera-controller/src/main/res/values/strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - Change camera controller - https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer - - Bristol.dae - Bristol.png - Select camera controller - - - @string/bristol_model_file - @string/bristol_skin_file - - diff --git a/change-viewpoint/.gitignore b/change-viewpoint/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/change-viewpoint/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/change-viewpoint/build.gradle.kts b/change-viewpoint/build.gradle.kts deleted file mode 100644 index f269a21dd..000000000 --- a/change-viewpoint/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.changeviewpoint" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.changeviewpoint" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/change-viewpoint/proguard-rules.pro b/change-viewpoint/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/change-viewpoint/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/change-viewpoint/src/main/AndroidManifest.xml b/change-viewpoint/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/change-viewpoint/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/change-viewpoint/src/main/java/com/esri/arcgismaps/sample/changeviewpoint/MainActivity.kt b/change-viewpoint/src/main/java/com/esri/arcgismaps/sample/changeviewpoint/MainActivity.kt deleted file mode 100644 index 977a1b517..000000000 --- a/change-viewpoint/src/main/java/com/esri/arcgismaps/sample/changeviewpoint/MainActivity.kt +++ /dev/null @@ -1,99 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.changeviewpoint - -import android.os.Bundle -import android.view.View -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.PolylineBuilder -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.esri.arcgismaps.sample.changeviewpoint.databinding.ActivityMainBinding -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - private val viewpointScale = 5000.0 - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - // add the MapView to the lifecycle - lifecycle.addObserver(mapView) - // create and add a map with a imagery basemap style - mapView.map = ArcGISMap(BasemapStyle.ArcGISImagery) - // set the start point of the ViewPoint - val startPoint = Point(-14093.0, 6711377.0, SpatialReference.webMercator()) - lifecycleScope.launch { - // set viewpoint of map view to starting point and scale - mapView.setViewpointCenter(startPoint, viewpointScale) - } - } - - fun onGeometryClicked(view: View) { - // create a collection of points around Westminster - val westminsterPolylineBuilder = PolylineBuilder(SpatialReference.webMercator()) { - addPoint(Point(-13823.0, 6710390.0)) - addPoint(Point(-13823.0, 6710150.0)) - addPoint(Point(-14680.0, 6710390.0)) - addPoint(Point(-14680.0, 6710150.0)) - } - val geometry = westminsterPolylineBuilder.toGeometry() - // set the map view's viewpoint to Westminster - lifecycleScope.launch { - mapView.setViewpointGeometry(geometry) - } - } - - fun onCenterClicked(view: View) { - // create the Waterloo location point - val waterlooPoint = Point(-12153.0, 6710527.0, SpatialReference.webMercator()) - // set the map view's viewpoint centered on Waterloo and scaled - lifecycleScope.launch { - mapView.setViewpointCenter(waterlooPoint, viewpointScale) - } - } - - fun onAnimateClicked(view: View) { - // create the London location point - val londonPoint = Point(-14093.0, 6711377.0, SpatialReference.webMercator()) - // create the viewpoint with the London point and scale - val viewpoint = Viewpoint(londonPoint, viewpointScale) - // set the map view's viewpoint to London with a seven second animation duration - lifecycleScope.launch { - mapView.setViewpointAnimated(viewpoint, 7f) - } - } -} diff --git a/change-viewpoint/src/main/res/drawable-v24/ic_launcher_foreground.xml b/change-viewpoint/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/change-viewpoint/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/change-viewpoint/src/main/res/drawable/ic_launcher_background.xml b/change-viewpoint/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/change-viewpoint/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/change-viewpoint/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/change-viewpoint/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/change-viewpoint/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/change-viewpoint/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/change-viewpoint/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/change-viewpoint/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/change-viewpoint/src/main/res/mipmap-hdpi/ic_launcher.png b/change-viewpoint/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-hdpi/ic_launcher_round.png b/change-viewpoint/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-mdpi/ic_launcher.png b/change-viewpoint/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-mdpi/ic_launcher_round.png b/change-viewpoint/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-xhdpi/ic_launcher.png b/change-viewpoint/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/change-viewpoint/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-xxhdpi/ic_launcher.png b/change-viewpoint/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/change-viewpoint/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/change-viewpoint/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/change-viewpoint/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/change-viewpoint/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/change-viewpoint/src/main/res/values/strings.xml b/change-viewpoint/src/main/res/values/strings.xml deleted file mode 100644 index da035a932..000000000 --- a/change-viewpoint/src/main/res/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Change viewpoint - Animate - Center - Geometry - diff --git a/clip-geometry/.gitignore b/clip-geometry/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/clip-geometry/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/clip-geometry/build.gradle.kts b/clip-geometry/build.gradle.kts deleted file mode 100644 index 85a5f8e8e..000000000 --- a/clip-geometry/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.clipgeometry" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.clipgeometry" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/clip-geometry/proguard-rules.pro b/clip-geometry/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/clip-geometry/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/clip-geometry/src/main/AndroidManifest.xml b/clip-geometry/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/clip-geometry/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/clip-geometry/src/main/java/com/esri/arcgismaps/sample/clipgeometry/MainActivity.kt b/clip-geometry/src/main/java/com/esri/arcgismaps/sample/clipgeometry/MainActivity.kt deleted file mode 100644 index b1e808551..000000000 --- a/clip-geometry/src/main/java/com/esri/arcgismaps/sample/clipgeometry/MainActivity.kt +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.clipgeometry - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.Envelope -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.symbology.SimpleFillSymbol -import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.esri.arcgismaps.sample.clipgeometry.databinding.ActivityMainBinding - -class MainActivity : AppCompatActivity() { - - // graphics overlay along the Colorado state border - private val coloradoOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } - - // graphics overlay to contain the clipping envelopes - private val envelopesOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - // set up data binding for the activity - val activityMainBinding: ActivityMainBinding = - DataBindingUtil.setContentView(this, R.layout.activity_main) - // get the MapView instance from the data binding - val mapView = activityMainBinding.mapView - lifecycle.addObserver(mapView) - - // create buttons to perform the clip and reset operations on the geometry - val clipButton = activityMainBinding.clipButton - val resetButton = activityMainBinding.resetButton - - // create and add a map with a topographic basemap style - mapView.map = ArcGISMap(BasemapStyle.ArcGISTopographic) - // set the viewpoint of the MapView - mapView.setViewpoint(Viewpoint(40.0, -106.0, 10000000.0)) - - // create a graphics overlay to contain the geometry to clip - mapView.graphicsOverlays.add(coloradoOverlay) - val (coloradoGraphic, fillSymbol) = createGraphics(coloradoOverlay) - - // create a graphics overlay to contain the clipping envelopes - mapView.graphicsOverlays.add(envelopesOverlay) - createEnvelope(envelopesOverlay) - - // create a graphics overlay to contain the clipped areas - val clipAreasOverlay = GraphicsOverlay() - mapView.graphicsOverlays.add(clipAreasOverlay) - - clipButton.setOnClickListener { - // disable button - clipButton.isEnabled = false - resetButton.isEnabled = true - // for each envelope, clip the Colorado geometry and show the result, - // replacing the original Colorado graphic - coloradoGraphic.isVisible = false - for (graphic in envelopesOverlay.graphics) { - val geometry = - coloradoGraphic.geometry?.let { coloradoGeometry -> - GeometryEngine.clipOrNull(coloradoGeometry, graphic.geometry as Envelope) - } - val clippedGraphic = Graphic(geometry, fillSymbol) - clipAreasOverlay.graphics.add(clippedGraphic) - } - } - - resetButton.setOnClickListener { - // clear clipped graphic - clipAreasOverlay.graphics.clear() - - // set the visibility of the colorado graphic to true - coloradoGraphic.isVisible = true - - clipButton.isEnabled = true - resetButton.isEnabled = false - } - } - - /** - * Create colorado graphic. - */ - private fun createGraphics( - coloradoOverlay: GraphicsOverlay, - ) : Pair{ - // create a blue graphic of Colorado - val colorado = Envelope( - Point(-11362327.128340, 5012861.290274), - Point(-12138232.018408, 4441198.773776) - ) - val fillSymbol = SimpleFillSymbol( - SimpleFillSymbolStyle.Solid, - Color(R.color.transparentDarkBlue), - SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.green, 2f) - ) - val coloradoGraphic = Graphic(colorado, fillSymbol) - coloradoOverlay.graphics.add(coloradoGraphic) - return Pair(coloradoGraphic, fillSymbol) - } - - /** - * Create three envelopes, outside, inside and intersecting colorado graphic. - */ - private fun createEnvelope( - envelopesOverlay: GraphicsOverlay, - ) { - // create a dotted red outline symbol - val redOutline = SimpleLineSymbol(SimpleLineSymbolStyle.Dot, Color.red, 3f) - - // create a envelope outside Colorado - val outsideEnvelope = Envelope( - Point(-11858344.321294, 5147942.225174), - Point(-12201990.219681, 5297071.577304) - ) - val outside = Graphic(outsideEnvelope, redOutline) - envelopesOverlay.graphics.add(outside) - - // create a envelope intersecting Colorado - val intersectingEnvelope = Envelope( - Point(-11962086.479298, 4566553.881363), - Point(-12260345.183558, 4332053.378376) - ) - val intersecting = Graphic(intersectingEnvelope, redOutline) - envelopesOverlay.graphics.add(intersecting) - - // create a envelope inside Colorado - val containedEnvelope = Envelope( - Point(-11655182.595204, 4741618.772994), - Point(-11431488.567009, 4593570.068343) - ) - val contained = Graphic(containedEnvelope, redOutline) - envelopesOverlay.graphics.add(contained) - } -} diff --git a/clip-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml b/clip-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/clip-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/clip-geometry/src/main/res/drawable/ic_launcher_background.xml b/clip-geometry/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/clip-geometry/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/clip-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/clip-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/clip-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/clip-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/clip-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/clip-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/clip-geometry/src/main/res/mipmap-hdpi/ic_launcher.png b/clip-geometry/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/clip-geometry/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png b/clip-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/clip-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-mdpi/ic_launcher.png b/clip-geometry/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/clip-geometry/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png b/clip-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/clip-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png b/clip-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/clip-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/clip-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/clip-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png b/clip-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/clip-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/clip-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/clip-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/clip-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/clip-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/clip-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/clip-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/clip-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/clip-geometry/src/main/res/values/strings.xml b/clip-geometry/src/main/res/values/strings.xml deleted file mode 100644 index 31bbf2876..000000000 --- a/clip-geometry/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Clip geometry - Clip geometry - Reset - diff --git a/configure-basemap-style-parameters/.gitignore b/configure-basemap-style-parameters/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/configure-basemap-style-parameters/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/configure-basemap-style-parameters/build.gradle.kts b/configure-basemap-style-parameters/build.gradle.kts deleted file mode 100644 index 579eb3b3c..000000000 --- a/configure-basemap-style-parameters/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.configurebasemapstyleparameters" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.configurebasemapstyleparameters" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/configure-basemap-style-parameters/proguard-rules.pro b/configure-basemap-style-parameters/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/configure-basemap-style-parameters/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/configure-basemap-style-parameters/src/main/AndroidManifest.xml b/configure-basemap-style-parameters/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/configure-basemap-style-parameters/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/configure-basemap-style-parameters/src/main/java/com/esri/arcgismaps/sample/configurebasemapstyleparameters/MainActivity.kt b/configure-basemap-style-parameters/src/main/java/com/esri/arcgismaps/sample/configurebasemapstyleparameters/MainActivity.kt deleted file mode 100644 index 6d7d93b34..000000000 --- a/configure-basemap-style-parameters/src/main/java/com/esri/arcgismaps/sample/configurebasemapstyleparameters/MainActivity.kt +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.configurebasemapstyleparameters - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.configurebasemapstyleparameters.screens.MainScreen -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - setContent { - SampleAppTheme { - SampleApp() - } - } - } - - @Composable - private fun SampleApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/configure-basemap-style-parameters/src/main/res/drawable-v24/ic_launcher_foreground.xml b/configure-basemap-style-parameters/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/configure-basemap-style-parameters/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/configure-basemap-style-parameters/src/main/res/drawable/ic_launcher_background.xml b/configure-basemap-style-parameters/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/configure-basemap-style-parameters/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/configure-basemap-style-parameters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/configure-basemap-style-parameters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/configure-basemap-style-parameters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/configure-basemap-style-parameters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-hdpi/ic_launcher.png b/configure-basemap-style-parameters/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-hdpi/ic_launcher_round.png b/configure-basemap-style-parameters/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-mdpi/ic_launcher.png b/configure-basemap-style-parameters/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-mdpi/ic_launcher_round.png b/configure-basemap-style-parameters/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-xhdpi/ic_launcher.png b/configure-basemap-style-parameters/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/configure-basemap-style-parameters/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-xxhdpi/ic_launcher.png b/configure-basemap-style-parameters/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/configure-basemap-style-parameters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/configure-basemap-style-parameters/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/configure-basemap-style-parameters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/configure-basemap-style-parameters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-basemap-style-parameters/src/main/res/values/strings.xml b/configure-basemap-style-parameters/src/main/res/values/strings.xml deleted file mode 100644 index 47ffbeb8a..000000000 --- a/configure-basemap-style-parameters/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Configure basemap style parameters - diff --git a/configure-clusters/.gitignore b/configure-clusters/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/configure-clusters/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/configure-clusters/build.gradle.kts b/configure-clusters/build.gradle.kts deleted file mode 100644 index adc8e1d61..000000000 --- a/configure-clusters/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.configureclusters" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.configureclusters" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/configure-clusters/proguard-rules.pro b/configure-clusters/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/configure-clusters/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/configure-clusters/src/main/AndroidManifest.xml b/configure-clusters/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/configure-clusters/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/configure-clusters/src/main/java/com/esri/arcgismaps/sample/configureclusters/MainActivity.kt b/configure-clusters/src/main/java/com/esri/arcgismaps/sample/configureclusters/MainActivity.kt deleted file mode 100644 index 72577553c..000000000 --- a/configure-clusters/src/main/java/com/esri/arcgismaps/sample/configureclusters/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.configureclusters - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.configureclusters.screens.MainScreen -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - ConfigureClustersApp() - } - } - } - - @Composable - private fun ConfigureClustersApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/configure-clusters/src/main/java/com/esri/arcgismaps/sample/configureclusters/screens/MainScreen.kt b/configure-clusters/src/main/java/com/esri/arcgismaps/sample/configureclusters/screens/MainScreen.kt deleted file mode 100644 index 356c60036..000000000 --- a/configure-clusters/src/main/java/com/esri/arcgismaps/sample/configureclusters/screens/MainScreen.kt +++ /dev/null @@ -1,394 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.configureclusters.screens - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Settings -import androidx.compose.material.icons.rounded.Close -import androidx.compose.material3.DropdownMenuItem -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ExposedDropdownMenuBox -import androidx.compose.material3.ExposedDropdownMenuDefaults -import androidx.compose.material3.FloatingActionButton -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.Scaffold -import androidx.compose.material3.SheetState -import androidx.compose.material3.Switch -import androidx.compose.material3.Text -import androidx.compose.material3.TextField -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import androidx.lifecycle.viewmodel.compose.viewModel -import com.arcgismaps.toolkit.geoviewcompose.MapView -import com.esri.arcgismaps.sample.configureclusters.components.MapViewModel -import com.esri.arcgismaps.sample.sampleslib.components.BottomSheet -import com.esri.arcgismaps.sample.sampleslib.components.SampleTopAppBar -import com.esri.arcgismaps.sample.sampleslib.theme.SampleTypography -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import kotlin.math.roundToInt - -/** - * Main screen layout for the sample app - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun MainScreen(sampleName: String) { - // create a ViewModel to handle MapView interactions - val mapViewModel: MapViewModel = viewModel() - - val composableScope = rememberCoroutineScope() - - Scaffold( - topBar = { SampleTopAppBar(title = sampleName) }, - content = { - Box( - modifier = Modifier - .fillMaxSize() - .padding(it), - contentAlignment = Alignment.Center - ) { - var mapScale by remember { mutableIntStateOf(0) } - MapView( - modifier = Modifier - .fillMaxSize(), - mapViewProxy = mapViewModel.mapViewProxy, - // identify on single tap - onSingleTapConfirmed = { singleTapConfirmedEvent -> - mapViewModel.identify(singleTapConfirmedEvent) - }, - arcGISMap = mapViewModel.arcGISMap, - // update the map scale in the UI on map scale change - onMapScaleChanged = { currentMapScale -> - if (!currentMapScale.isNaN()) { - mapScale = currentMapScale.roundToInt() - } - }, - ) - - val controlsBottomSheetState = - rememberModalBottomSheetState(skipPartiallyExpanded = true) - // show the "Show controls" button only when the bottom sheet is not visible - if (!controlsBottomSheetState.isVisible) { - FloatingActionButton( - modifier = Modifier - .align(Alignment.BottomEnd) - .padding(bottom = 36.dp, end = 24.dp), - onClick = { - composableScope.launch { - controlsBottomSheetState.show() - } - }, - ) { - Icon(Icons.Filled.Settings, contentDescription = "Show controls") - } - } - if (controlsBottomSheetState.isVisible) { - ClusterControlsBottomSheet( - composableScope = composableScope, - controlsBottomSheetState = controlsBottomSheetState, - showClusterLabels = mapViewModel.showClusterLabels, - updateClusterLabelState = mapViewModel::updateShowClusterLabelState, - clusterRadiusOptions = mapViewModel.clusterRadiusOptions, - clusterRadius = mapViewModel.clusterRadius, - updateClusterRadiusState = mapViewModel::updateClusterRadiusState, - clusterMaxScaleOptions = mapViewModel.clusterMaxScaleOptions, - clusterMaxScale = mapViewModel.clusterMaxScale, - updateClusterMaxScaleState = mapViewModel::updateClusterMaxScaleState, - mapScale = mapScale - ) - } - } - - // display a bottom sheet to show popup details - BottomSheet( - isVisible = mapViewModel.showPopUpContent, - bottomSheetContent = { - ClusterInfoContent( - popUpTitle = mapViewModel.popUpTitle, - popUpInfo = mapViewModel.popUpInfo, - onDismiss = { mapViewModel.updateShowPopUpContentState(false) } - ) - }) - - } - ) -} - -/** - * Composable function to display the cluster controls bottom sheet. - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun ClusterControlsBottomSheet( - composableScope: CoroutineScope, - controlsBottomSheetState: SheetState, - showClusterLabels: Boolean, - updateClusterLabelState: (Boolean) -> Unit, - clusterRadiusOptions: List, - clusterRadius: Int, - updateClusterRadiusState: (Int) -> Unit, - clusterMaxScaleOptions: List, - clusterMaxScale: Int, - updateClusterMaxScaleState: (Int) -> Unit, - mapScale: Int, -) { - ModalBottomSheet( - modifier = Modifier.wrapContentHeight(), - sheetState = controlsBottomSheetState, - onDismissRequest = { - composableScope.launch { - controlsBottomSheetState.hide() - } - }) { - Column( - Modifier - .padding(12.dp) - .navigationBarsPadding()) { - Text( - "Cluster labels visibility:", - style = MaterialTheme.typography.titleMedium - ) - Spacer(Modifier.size(8.dp)) - Row( - Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text("Show labels") - Switch( - checked = showClusterLabels, - onCheckedChange = { showClusterLabels -> - updateClusterLabelState( - showClusterLabels - ) - } - ) - } - Spacer(Modifier.size(8.dp)) - Row( - Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text("Current map scale:") - Text("1:$mapScale") - } - HorizontalDivider(Modifier.padding(vertical = 12.dp, horizontal = 8.dp)) - Text( - "Clustering properties:", - style = MaterialTheme.typography.titleMedium - ) - Spacer(Modifier.size(8.dp)) - ClusterRadiusControls( - clusterRadiusOptions, - clusterRadius, - updateClusterRadiusState - ) - Spacer(Modifier.size(8.dp)) - ClusterMaxScaleControls( - clusterMaxScaleOptions, - clusterMaxScale, - updateClusterMaxScaleState - ) - } - } -} - -/** - * Composable function to display the cluster radius controls within the cluster controls bottom - * sheet. - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun ClusterRadiusControls( - clusterRadiusOptions: List, - clusterRadius: Int, - updateClusterRadius: (Int) -> Unit -) { - Row( - Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - "Cluster radius", - modifier = Modifier.padding(8.dp) - ) - var expanded by rememberSaveable { mutableStateOf(false) } - ExposedDropdownMenuBox( - modifier = Modifier.width(150.dp), - expanded = expanded, - onExpandedChange = { expanded = !expanded } - ) { - TextField( - value = clusterRadius.toString(), - onValueChange = {}, - readOnly = true, - trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, - modifier = Modifier.menuAnchor() - ) - ExposedDropdownMenu( - expanded = expanded, - onDismissRequest = { expanded = false } - ) { - clusterRadiusOptions.forEachIndexed { index, clusterRadius -> - DropdownMenuItem( - text = { Text(clusterRadius.toString()) }, - onClick = { - updateClusterRadius(index) - expanded = false - }) - // show a divider between dropdown menu options - if (index < clusterRadiusOptions.lastIndex) { - HorizontalDivider() - } - } - } - } - } -} - -/** - * Composable function to display the cluster max scale controls within the cluster controls bottom - * sheet. - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -private fun ClusterMaxScaleControls( - clusterMaxScaleOptions: List, - clusterMaxScale: Int, - updateClusterMaxScale: (Int) -> Unit -) { - Row( - Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - "Cluster max scale", - modifier = Modifier.padding(8.dp) - ) - var expanded by rememberSaveable { mutableStateOf(false) } - ExposedDropdownMenuBox( - modifier = Modifier.width(150.dp), - expanded = expanded, - onExpandedChange = { expanded = !expanded } - ) { - TextField( - value = clusterMaxScale.toString(), - onValueChange = {}, - readOnly = true, - trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) }, - modifier = Modifier.menuAnchor() - ) - ExposedDropdownMenu( - expanded = expanded, - onDismissRequest = { expanded = false } - ) { - clusterMaxScaleOptions.forEachIndexed { index, clusterRadius -> - DropdownMenuItem( - text = { Text(clusterRadius.toString()) }, - onClick = { - updateClusterMaxScale(index) - expanded = false - }) - // show a divider between dropdown menu options - if (index < clusterMaxScaleOptions.lastIndex) { - HorizontalDivider() - } - } - } - } - } -} - -/** - * Composable function to display the cluster info content from the pop up within a bottom sheet. - */ -@Composable -private fun ClusterInfoContent( - popUpTitle: String, - popUpInfo: Map, - onDismiss: () -> Unit -) { - Column(Modifier.background(MaterialTheme.colorScheme.background)) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 30.dp, vertical = 12.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Text( - text = popUpTitle.ifEmpty { "Cluster Info:" }, - style = SampleTypography.headlineSmall - ) - IconButton( - onClick = onDismiss - ) { - Icon( - imageVector = Icons.Rounded.Close, - contentDescription = "Close button" - ) - } - } - popUpInfo.forEach { - Row( - Modifier - .fillMaxWidth() - .padding( - horizontal = 30.dp, - vertical = 8.dp - ), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - Text(text = "${it.key}:", style = MaterialTheme.typography.labelMedium) - Text(text = "${it.value}") - } - } - Spacer(modifier = Modifier.size(24.dp)) - } -} diff --git a/configure-clusters/src/main/res/drawable-v24/ic_launcher_foreground.xml b/configure-clusters/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/configure-clusters/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/configure-clusters/src/main/res/drawable/ic_launcher_background.xml b/configure-clusters/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/configure-clusters/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/configure-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/configure-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/configure-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/configure-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/configure-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/configure-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/configure-clusters/src/main/res/mipmap-hdpi/ic_launcher.png b/configure-clusters/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/configure-clusters/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-hdpi/ic_launcher_round.png b/configure-clusters/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/configure-clusters/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-mdpi/ic_launcher.png b/configure-clusters/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/configure-clusters/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-mdpi/ic_launcher_round.png b/configure-clusters/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/configure-clusters/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-xhdpi/ic_launcher.png b/configure-clusters/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/configure-clusters/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/configure-clusters/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/configure-clusters/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-xxhdpi/ic_launcher.png b/configure-clusters/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/configure-clusters/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/configure-clusters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/configure-clusters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/configure-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/configure-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/configure-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/configure-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/configure-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/configure-clusters/src/main/res/values/strings.xml b/configure-clusters/src/main/res/values/strings.xml deleted file mode 100644 index 11b17f645..000000000 --- a/configure-clusters/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Configure clusters - diff --git a/create-convex-hull-around-points/.gitignore b/create-convex-hull-around-points/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/create-convex-hull-around-points/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/create-convex-hull-around-points/build.gradle.kts b/create-convex-hull-around-points/build.gradle.kts deleted file mode 100644 index a8be150df..000000000 --- a/create-convex-hull-around-points/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.createconvexhullaroundpoints" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.createconvexhullaroundpoints" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/create-convex-hull-around-points/proguard-rules.pro b/create-convex-hull-around-points/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/create-convex-hull-around-points/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/create-convex-hull-around-points/src/main/AndroidManifest.xml b/create-convex-hull-around-points/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/create-convex-hull-around-points/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/create-convex-hull-around-points/src/main/java/com/esri/arcgismaps/sample/createconvexhullaroundpoints/MainActivity.kt b/create-convex-hull-around-points/src/main/java/com/esri/arcgismaps/sample/createconvexhullaroundpoints/MainActivity.kt deleted file mode 100644 index 7065e18fb..000000000 --- a/create-convex-hull-around-points/src/main/java/com/esri/arcgismaps/sample/createconvexhullaroundpoints/MainActivity.kt +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.createconvexhullaroundpoints - -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.Geometry -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.Multipoint -import com.arcgismaps.geometry.Polyline -import com.arcgismaps.geometry.Polygon -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol -import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleFillSymbol -import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.esri.arcgismaps.sample.createconvexhullaroundpoints.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - // setup binding for the MapView - private val mapView by lazy { - activityMainBinding.mapView - } - - // action button that creates the canvas hull - private val createButton by lazy { - activityMainBinding.createButton - } - - // action button to reset the map - private val resetButton by lazy { - activityMainBinding.resetButton - } - - // a red marker symbol for points - private val pointSymbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.red, 10f) - - // a blue line symbol - private val lineSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.blue, 3f) - - // a fill symbol with an empty fill for polygons - private val fillSymbol = SimpleFillSymbol(SimpleFillSymbolStyle.Null, Color.red, lineSymbol) - - // set up the point graphic with point symbol - private val pointGraphic = Graphic(symbol = pointSymbol) - - // init the convex hull graphic - private val convexHullGraphic = Graphic() - - // create a graphics overlay to draw all graphics - private val graphicsOverlay = GraphicsOverlay() - - // list to store the selected map points - private val inputPoints = mutableListOf() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // add point and convex hull graphics to the graphics overlay - graphicsOverlay.graphics.addAll(listOf(pointGraphic, convexHullGraphic)) - - // create and add a map with topographic basemap style - val map = ArcGISMap(BasemapStyle.ArcGISTopographic).apply { - // set a default initial point and scale - initialViewpoint = Viewpoint(Point(34.77, -10.24), 20e7) - } - - // configure map view assignments - mapView.apply { - this.map = map - // add the graphics overlay to the mapview - graphicsOverlays.add(graphicsOverlay) - } - - lifecycleScope.launch { - // if the map load fails show the error and return - map.load().onFailure { - return@launch showError("Error loading map") - } - // capture and collect when the user taps on the screen - mapView.onSingleTapConfirmed.collect { event -> - event.mapPoint?.let { point -> - addMapPoint(point) - } - } - } - - // add a click listener to create a convex hull - createButton.setOnClickListener { - // check if the pointGraphic's geometry is not null - pointGraphic.geometry?.let { geometry -> - createConvexHull(geometry) - } - } - - // add a click listener to reset the map - resetButton.setOnClickListener { - resetMap() - } - } - - /** - * Adds the [point] to the map drawn as a Multipoint geometry - */ - private fun addMapPoint(point: Point) { - // add the new point to the points list - inputPoints.add(point) - // recreate the graphics geometry representing the input points - pointGraphic.geometry = Multipoint(inputPoints) - // enable all the action buttons, since we have at least one point drawn - createButton.isEnabled = true - resetButton.isEnabled = true - } - - /** - * Creates and draws a convex hull graphic on the map using [pointGeometry] points - */ - private fun createConvexHull(pointGeometry: Geometry) { - // normalize the geometry for panning beyond the meridian - // and proceed if the resulting geometry is not null - val normalizedPointGeometry = GeometryEngine.normalizeCentralMeridian(pointGeometry) - ?: return showError("Error normalizing point geometry") - - // create a convex hull from the points and proceed if it's not null - val convexHullGeometry = GeometryEngine.convexHullOrNull(normalizedPointGeometry) - - // the convex hull's geometry may be a point or polyline if the number of - // points is less than 3, set its symbol accordingly - convexHullGraphic.symbol = when (convexHullGeometry) { - is Point -> { - // set symbol to use the pointSymbol - pointSymbol - } - is Polyline -> { - // set symbol to use the lineSymbol - lineSymbol - } - is Polygon -> { - // set symbol to use the fillSymbol - fillSymbol - } - else -> { - showError("Unknown geometry for convex hull") - null - } - } - // update the convex hull graphics geometry - convexHullGraphic.geometry = convexHullGeometry - // disable the create button until new input points are created - createButton.isEnabled = false - } - - - /** - * Resets the map by clearing any drawn points, graphics and disables all buttons - */ - private fun resetMap() { - // remove all the selected points - inputPoints.clear() - // remove the geometry for the point graphic and convex hull graphics - pointGraphic.geometry = null - convexHullGraphic.geometry = null - // disable the buttons - resetButton.isEnabled = false - createButton.isEnabled = false - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} - -/** - * Simple extension property that represents a blue color - */ -private val Color.Companion.blue - get() = fromRgba(0, 0, 255) diff --git a/create-convex-hull-around-points/src/main/res/drawable-v24/ic_launcher_foreground.xml b/create-convex-hull-around-points/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/create-convex-hull-around-points/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/create-convex-hull-around-points/src/main/res/drawable/ic_launcher_background.xml b/create-convex-hull-around-points/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/create-convex-hull-around-points/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/create-convex-hull-around-points/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/create-convex-hull-around-points/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/create-convex-hull-around-points/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/create-convex-hull-around-points/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/create-convex-hull-around-points/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/create-convex-hull-around-points/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/create-convex-hull-around-points/src/main/res/mipmap-hdpi/ic_launcher.png b/create-convex-hull-around-points/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-hdpi/ic_launcher_round.png b/create-convex-hull-around-points/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-mdpi/ic_launcher.png b/create-convex-hull-around-points/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-mdpi/ic_launcher_round.png b/create-convex-hull-around-points/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-xhdpi/ic_launcher.png b/create-convex-hull-around-points/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/create-convex-hull-around-points/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-xxhdpi/ic_launcher.png b/create-convex-hull-around-points/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/create-convex-hull-around-points/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/create-convex-hull-around-points/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/create-convex-hull-around-points/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/create-convex-hull-around-points/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-convex-hull-around-points/src/main/res/values/strings.xml b/create-convex-hull-around-points/src/main/res/values/strings.xml deleted file mode 100644 index 1b2408f57..000000000 --- a/create-convex-hull-around-points/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Create convex hull around points - Create Convex Hull - Reset - diff --git a/create-mobile-geodatabase/.gitignore b/create-mobile-geodatabase/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/create-mobile-geodatabase/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/create-mobile-geodatabase/build.gradle.kts b/create-mobile-geodatabase/build.gradle.kts deleted file mode 100644 index 9024d10be..000000000 --- a/create-mobile-geodatabase/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.createmobilegeodatabase" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.createmobilegeodatabase" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/create-mobile-geodatabase/proguard-rules.pro b/create-mobile-geodatabase/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/create-mobile-geodatabase/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/create-mobile-geodatabase/src/main/AndroidManifest.xml b/create-mobile-geodatabase/src/main/AndroidManifest.xml deleted file mode 100644 index 643b2bcc9..000000000 --- a/create-mobile-geodatabase/src/main/AndroidManifest.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/create-mobile-geodatabase/src/main/java/com/esri/arcgismaps/sample/createmobilegeodatabase/MainActivity.kt b/create-mobile-geodatabase/src/main/java/com/esri/arcgismaps/sample/createmobilegeodatabase/MainActivity.kt deleted file mode 100644 index 4610a1c55..000000000 --- a/create-mobile-geodatabase/src/main/java/com/esri/arcgismaps/sample/createmobilegeodatabase/MainActivity.kt +++ /dev/null @@ -1,297 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.createmobilegeodatabase - -import android.app.Dialog -import android.content.Intent -import android.os.Bundle -import android.util.Log -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.FileProvider -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.LoadStatus -import com.arcgismaps.data.FieldDescription -import com.arcgismaps.data.FieldType -import com.arcgismaps.data.Geodatabase -import com.arcgismaps.data.GeodatabaseFeatureTable -import com.arcgismaps.data.QueryParameters -import com.arcgismaps.data.TableDescription -import com.arcgismaps.geometry.GeometryType -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.layers.FeatureLayer -import com.esri.arcgismaps.sample.createmobilegeodatabase.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.createmobilegeodatabase.databinding.TableLayoutBinding -import com.esri.arcgismaps.sample.createmobilegeodatabase.databinding.TableRowBinding -import com.google.android.material.button.MaterialButton -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File -import java.time.Instant - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val createButton: MaterialButton by lazy { - activityMainBinding.createButton - } - - private val viewTableButton: MaterialButton by lazy { - activityMainBinding.viewTableButton - } - - private val featureCountTextView: TextView by lazy { - activityMainBinding.featureCount - } - - // feature table created using mobile geodatabase and added to the MapView - private var featureTable: GeodatabaseFeatureTable? = null - - // mobile geodatabase used to create and store - // the feature attributes (LocationHistory.geodatabase) - private var geodatabase: Geodatabase? = null - - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - lifecycleScope.launch { - mapView.onSingleTapConfirmed.collect { tapConfirmedEvent -> - tapConfirmedEvent.mapPoint?.let { - // create a feature on where the user clicked - addFeature(it) - } - } - } - - // displays a dialog to show the attributes of each feature in a feature table - viewTableButton.setOnClickListener { - lifecycleScope.launch { - displayTable() - } - } - - // opens a share-sheet with the "LocationHistory.geodatabase" file - createButton.setOnClickListener { - // close the mobile geodatabase before sharing - geodatabase?.close() - - // get the URI of the geodatabase file using FileProvider - val geodatabaseURI = FileProvider.getUriForFile( - this, - getString(R.string.provider_authority), - File(geodatabase?.path.toString()) - ) - - // set up the sharing intent with the geodatabase URI - val geodatabaseIntent = Intent(Intent.ACTION_SEND).apply { - type = "*/*" - putExtra(Intent.EXTRA_STREAM, geodatabaseURI) - } - - // open the Android share sheet - startActivity(geodatabaseIntent) - } - } - - - /** - * Create and load a new geodatabase file with TableDescription fields - */ - private fun createGeodatabase() { - // define the path and name of the geodatabase file - // note: the path defined must be non-empty, available, - // allow read/write access, and end in ".geodatabase" - val file = File(getExternalFilesDir(null)?.path, "/LocationHistory.geodatabase") - if (file.exists()) { - file.delete() - } - // close the existing geodatabase - geodatabase?.close() - lifecycleScope.launch { - // create a geodatabase file at the file path - Geodatabase.create(file.path).onSuccess { geodatabase -> - // keep the instance of the new geodatabase for sharing - this@MainActivity.geodatabase = geodatabase - createGeodatabaseFeatureTable() - }.onFailure { - showError(it.message.toString()) - } - - } - } - - /** - * Create a new [featureTable] using a custom table description - * and add the feature layer to the MapView. - */ - private suspend fun createGeodatabaseFeatureTable() { - // construct a table description which stores features as points on map - val tableDescription = - TableDescription( - "LocationHistory", - SpatialReference.wgs84(), - GeometryType.Point - ) - // set up the fields to the table, - // Field.Type.OID is the primary key of the SQLite table - // Field.Type.DATE is a date column used to store a Calendar date - // FieldDescriptions can be a SHORT, INTEGER, GUID, FLOAT, DOUBLE, DATE, TEXT, OID, GLOBALID, BLOB, GEOMETRY, RASTER, or XML. - tableDescription.fieldDescriptions.addAll( - listOf( - FieldDescription("oid", FieldType.Oid), - FieldDescription("collection_timestamp", FieldType.Date) - ) - ) - - // set any properties not needed to false - tableDescription.apply { - hasAttachments = false - hasM = false - hasZ = false - } - - // add a new table to the geodatabase by creating one from the tableDescription - geodatabase?.createTable(tableDescription)?.onSuccess { featureTable -> - // get the result of the loaded "LocationHistory" table - this.featureTable = featureTable - // create a feature layer for the map using the GeodatabaseFeatureTable - val featureLayer = FeatureLayer.createWithFeatureTable(featureTable) - mapView.map?.operationalLayers?.add(featureLayer) - // display the current count of features in the FeatureTable - featureCountTextView.text = - "Number of features added: ${featureTable.numberOfFeatures}" - }?.onFailure { - showError(it.message.toString()) - } - } - - /** - * Create a feature with attributes on map click and add it to the [featureTable] - * Also, updates the TotalFeatureCount on the screen - */ - private fun addFeature(mapPoint: Point) { - // set up the feature attributes - val featureAttributes = mutableMapOf() - featureAttributes["collection_timestamp"] = Instant.now() - - // create a new feature at the mapPoint - val feature = featureTable?.createFeature(featureAttributes, mapPoint) - ?: return showError("Error creating feature using attributes") - - lifecycleScope.launch { - // add the feature to the feature table - featureTable?.addFeature(feature)?.onSuccess { - // feature added successfully, update count - featureCountTextView.text = - "Number of features added: ${featureTable?.numberOfFeatures}" - // enable table button since at least 1 feature loaded on the GeodatabaseFeatureTable - viewTableButton.isEnabled = true - }?.onFailure { - showError(it.message.toString()) - } - } - } - - /** - * Displays a dialog with the table of features - * added to the GeodatabaseFeatureTable [featureTable] - */ - private suspend fun displayTable() { - // query all the features loaded to the table - featureTable?.queryFeatures(QueryParameters())?.onSuccess { queryResults -> - // inflate the table layout - val tableLayoutBinding = TableLayoutBinding.inflate(layoutInflater) - // set up a dialog to be displayed - Dialog(this).apply { - setContentView(tableLayoutBinding.root) - setCancelable(true) - // grab the instance of the TableLayout - val table = tableLayoutBinding.tableLayout - // iterate through each feature to add to the TableLayout - queryResults.forEach { feature -> - // prepare the table row - val tableRowBinding = TableRowBinding.inflate(layoutInflater).apply { - oid.text = feature.attributes["oid"].toString() - collectionTimestamp.text = - (feature.attributes["collection_timestamp"] as Instant).toString() - } - // add the row to the TableLayout - table.addView(tableRowBinding.root) - } - }.show() - }?.onFailure { - showError(it.message.toString()) - } - } - - /** - * Called on app launch or when Android share sheet is closed - */ - private fun setMapView() { - // create and add a map with a navigation night basemap style - mapView.map = ArcGISMap(BasemapStyle.ArcGISTopographic) - mapView.setViewpoint(Viewpoint(41.5, -100.0, 100_000_000.0)) - - lifecycleScope.launch { - mapView.map?.loadStatus?.collect { loadStatus -> - if (loadStatus == LoadStatus.Loaded) { - // clear any feature layers displayed on the map - mapView.map?.operationalLayers?.clear() - // disable the button since no features are displayed - viewTableButton.isEnabled = false - // create a new geodatabase file to add features into the feature table - createGeodatabase() - } else if (loadStatus is LoadStatus.FailedToLoad) { - showError("Error loading MapView: ${loadStatus.error.message}") - } - } - } - } - - override fun onResume() { - super.onResume() - // set up map view and create new geodatabase file - // on every app launch or on share sheet close - setMapView() - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/create-mobile-geodatabase/src/main/res/drawable-v24/ic_launcher_foreground.xml b/create-mobile-geodatabase/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/create-mobile-geodatabase/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/create-mobile-geodatabase/src/main/res/drawable/ic_launcher_background.xml b/create-mobile-geodatabase/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/create-mobile-geodatabase/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/create-mobile-geodatabase/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/create-mobile-geodatabase/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/create-mobile-geodatabase/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/create-mobile-geodatabase/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/create-mobile-geodatabase/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/create-mobile-geodatabase/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/create-mobile-geodatabase/src/main/res/mipmap-hdpi/ic_launcher.png b/create-mobile-geodatabase/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-hdpi/ic_launcher_round.png b/create-mobile-geodatabase/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-mdpi/ic_launcher.png b/create-mobile-geodatabase/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-mdpi/ic_launcher_round.png b/create-mobile-geodatabase/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-xhdpi/ic_launcher.png b/create-mobile-geodatabase/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/create-mobile-geodatabase/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-xxhdpi/ic_launcher.png b/create-mobile-geodatabase/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/create-mobile-geodatabase/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/create-mobile-geodatabase/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/create-mobile-geodatabase/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/create-mobile-geodatabase/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-mobile-geodatabase/src/main/res/values/strings.xml b/create-mobile-geodatabase/src/main/res/values/strings.xml deleted file mode 100644 index db270ed92..000000000 --- a/create-mobile-geodatabase/src/main/res/values/strings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - Create mobile geodatabase - Number of features added: - Create and share mobile geodatabase - View table - Attribute table loaded from the mobile geodatabase file. File can be loaded on ArcGIS Pro or ArcGIS Runtime - OID - Collection Timestamp - com.esri.arcgismaps.sample.createmobilegeodatabase.provider - diff --git a/create-planar-and-geodetic-buffers/.gitignore b/create-planar-and-geodetic-buffers/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/create-planar-and-geodetic-buffers/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/create-planar-and-geodetic-buffers/build.gradle.kts b/create-planar-and-geodetic-buffers/build.gradle.kts deleted file mode 100644 index c9038f54c..000000000 --- a/create-planar-and-geodetic-buffers/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.createplanarandgeodeticbuffers" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.createplanarandgeodeticbuffers" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/create-planar-and-geodetic-buffers/proguard-rules.pro b/create-planar-and-geodetic-buffers/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/create-planar-and-geodetic-buffers/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/create-planar-and-geodetic-buffers/src/main/AndroidManifest.xml b/create-planar-and-geodetic-buffers/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/create-planar-and-geodetic-buffers/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/create-planar-and-geodetic-buffers/src/main/java/com/esri/arcgismaps/sample/createplanarandgeodeticbuffers/MainActivity.kt b/create-planar-and-geodetic-buffers/src/main/java/com/esri/arcgismaps/sample/createplanarandgeodeticbuffers/MainActivity.kt deleted file mode 100644 index 3950526b9..000000000 --- a/create-planar-and-geodetic-buffers/src/main/java/com/esri/arcgismaps/sample/createplanarandgeodeticbuffers/MainActivity.kt +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.createplanarandgeodeticbuffers - -import android.os.Bundle -import android.view.View -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.GeodeticCurveType -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.LinearUnit -import com.arcgismaps.geometry.LinearUnitId -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.symbology.SimpleFillSymbol -import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol -import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleRenderer -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.esri.arcgismaps.sample.createplanarandgeodeticbuffers.databinding.ActivityMainBinding -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.slider.Slider -import kotlinx.coroutines.launch -import java.util.Locale - -class MainActivity : AppCompatActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - // set up data binding for the activity - val activityMainBinding: ActivityMainBinding = - DataBindingUtil.setContentView(this, R.layout.activity_main) - - // get the views from the layout - val mapView = activityMainBinding.mapView - val optionsButton = activityMainBinding.optionsButton - val clearButton = activityMainBinding.clearButton - // add mapview to the lifecycle - lifecycle.addObserver(mapView) - - // create a map with a topographic basemap - mapView.map = ArcGISMap(BasemapStyle.ArcGISTopographic) - - // create a fill symbol for geodesic buffer polygons - val geodesicOutlineSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.black, 2F) - val geodesicBufferFillSymbol = SimpleFillSymbol( - SimpleFillSymbolStyle.Solid, Color.green, - geodesicOutlineSymbol - ) - - // create a graphics overlay to display geodesic polygons and set its renderer - val geodesicGraphicsOverlay = GraphicsOverlay().apply { - renderer = SimpleRenderer(geodesicBufferFillSymbol) - opacity = 0.5f - } - - // create a fill symbol for planar buffer polygons - val planarOutlineSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.black, 2F) - val planarBufferFillSymbol = SimpleFillSymbol( - SimpleFillSymbolStyle.Solid, Color.red, - planarOutlineSymbol - ) - - // create a graphics overlay to display planar polygons and set its renderer - val planarGraphicsOverlay = GraphicsOverlay().apply { - renderer = SimpleRenderer(planarBufferFillSymbol) - opacity = 0.5f - } - - // create a marker symbol for tap locations - val tapSymbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Cross, Color.white, 14F) - - // create a graphics overlay to display tap locations for buffers and set its renderer - val tapLocationsOverlay = GraphicsOverlay().apply { - renderer = SimpleRenderer(tapSymbol) - } - - // add overlays to the mapView - mapView.graphicsOverlays.addAll( - listOf( - geodesicGraphicsOverlay, - planarGraphicsOverlay, - tapLocationsOverlay - ) - ) - - // set the default buffer distance in miles - var bufferInMiles = 500f - - // create a buffer around the clicked location - lifecycleScope.launch { - mapView.onSingleTapConfirmed.collect { event -> - // get map point tapped, return if null - val mapPoint = event.mapPoint ?: return@collect - - // convert the input distance to meters, 1609.34 meters in one mile - val bufferInMeters = bufferInMiles * 1609.34 - - // create a planar buffer graphic around the input location at the specified distance - val bufferGeometryPlanar = GeometryEngine.bufferOrNull(mapPoint, bufferInMeters) - val planarBufferGraphic = Graphic(bufferGeometryPlanar) - - // create a geodesic buffer graphic using the same location and distance - val bufferGeometryGeodesic = - GeometryEngine.bufferGeodeticOrNull( - mapPoint, bufferInMeters, - LinearUnit(LinearUnitId.Meters), Double.NaN, GeodeticCurveType.Geodesic - ) - val geodesicBufferGraphic = Graphic(bufferGeometryGeodesic) - - // create a graphic for the user tap location - val locationGraphic = Graphic(mapPoint) - - // add the buffer polygons and tap location graphics to the appropriate graphic overlays - planarGraphicsOverlay.graphics.add(planarBufferGraphic) - geodesicGraphicsOverlay.graphics.add(geodesicBufferGraphic) - tapLocationsOverlay.graphics.add(locationGraphic) - - // set button interaction - clearButton.isEnabled = true - - } - } - // open the option dialog - optionsButton.setOnClickListener { - val optionsDialog: View = layoutInflater.inflate(R.layout.buffer_options_dialog, null) - // set up the dialog builder and the title - val dialogBuilder = MaterialAlertDialogBuilder(this) - .setView(optionsDialog) - .setPositiveButton("Set buffer", null) - - dialogBuilder.setTitle("Set buffer radius") - // set up the dialog views - val bufferValue = optionsDialog.findViewById(R.id.bufferValue) - val bufferSlider = optionsDialog.findViewById(R.id.bufferInput) - bufferSlider.value = bufferInMiles - - // set initial buffer text - bufferValue.text = String.format(Locale.getDefault(),"%d miles", bufferSlider.value.toInt()) - bufferSlider.addOnChangeListener { _, value, _ -> - // update buffer text value on slider change - bufferValue.text = String.format(Locale.getDefault(),"%d miles", value.toInt()) - bufferInMiles = value - } - - // display the dialog - dialogBuilder.show() - } - - // clear the graphics from the graphics overlays - clearButton.setOnClickListener { - planarGraphicsOverlay.graphics.clear() - geodesicGraphicsOverlay.graphics.clear() - tapLocationsOverlay.graphics.clear() - // set button interaction - clearButton.isEnabled = false - } - } -} diff --git a/create-planar-and-geodetic-buffers/src/main/res/drawable-v24/ic_launcher_foreground.xml b/create-planar-and-geodetic-buffers/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/create-planar-and-geodetic-buffers/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/create-planar-and-geodetic-buffers/src/main/res/drawable/ic_launcher_background.xml b/create-planar-and-geodetic-buffers/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/create-planar-and-geodetic-buffers/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/create-planar-and-geodetic-buffers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/create-planar-and-geodetic-buffers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/create-planar-and-geodetic-buffers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/create-planar-and-geodetic-buffers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-hdpi/ic_launcher.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-hdpi/ic_launcher_round.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-mdpi/ic_launcher.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-mdpi/ic_launcher_round.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xhdpi/ic_launcher.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxhdpi/ic_launcher.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/create-planar-and-geodetic-buffers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/create-planar-and-geodetic-buffers/src/main/res/values/strings.xml b/create-planar-and-geodetic-buffers/src/main/res/values/strings.xml deleted file mode 100644 index 18f848bf8..000000000 --- a/create-planar-and-geodetic-buffers/src/main/res/values/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - Create planar and geodetic buffers - Specify the buffer in miles then tap on map - Geodesic Buffer - Planar Buffer - 2000 - Clear all - miles - diff --git a/cut-geometry/.gitignore b/cut-geometry/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/cut-geometry/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/cut-geometry/build.gradle.kts b/cut-geometry/build.gradle.kts deleted file mode 100644 index 14ff2d0ac..000000000 --- a/cut-geometry/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.cutgeometry" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.cutgeometry" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/cut-geometry/proguard-rules.pro b/cut-geometry/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/cut-geometry/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/cut-geometry/src/main/AndroidManifest.xml b/cut-geometry/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/cut-geometry/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/cut-geometry/src/main/java/com/esri/arcgismaps/sample/cutgeometry/MainActivity.kt b/cut-geometry/src/main/java/com/esri/arcgismaps/sample/cutgeometry/MainActivity.kt deleted file mode 100644 index 55fede4fb..000000000 --- a/cut-geometry/src/main/java/com/esri/arcgismaps/sample/cutgeometry/MainActivity.kt +++ /dev/null @@ -1,203 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.cutgeometry - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.PolygonBuilder -import com.arcgismaps.geometry.Polyline -import com.arcgismaps.geometry.PolylineBuilder -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.symbology.SimpleFillSymbol -import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.MapView -import com.esri.arcgismaps.sample.cutgeometry.databinding.ActivityMainBinding - -class MainActivity : AppCompatActivity() { - - private val lakeSuperiorPolygon by lazy { - PolygonBuilder(SpatialReference.webMercator()) { - addPoint(Point(-10254374.668616, 5908345.076380)) - addPoint(Point(-10178382.525314, 5971402.386779)) - addPoint(Point(-10118558.923141, 6034459.697178)) - addPoint(Point(-9993252.729399, 6093474.872295)) - addPoint(Point(-9882498.222673, 6209888.368416)) - addPoint(Point(-9821057.766387, 6274562.532928)) - addPoint(Point(-9690092.583250, 6241417.023616)) - addPoint(Point(-9605207.742329, 6206654.660191)) - addPoint(Point(-9564786.389509, 6108834.986367)) - addPoint(Point(-9449989.747500, 6095091.726408)) - addPoint(Point(-9462116.153346, 6044160.821855)) - addPoint(Point(-9417652.665244, 5985145.646738)) - addPoint(Point(-9438671.768711, 5946341.148031)) - addPoint(Point(-9398250.415891, 5922088.336339)) - addPoint(Point(-9419269.519357, 5855797.317714)) - addPoint(Point(-9467775.142741, 5858222.598884)) - addPoint(Point(-9462924.580403, 5902686.086985)) - addPoint(Point(-9598740.325877, 5884092.264688)) - addPoint(Point(-9643203.813979, 5845287.765981)) - addPoint(Point(-9739406.633691, 5879241.702350)) - addPoint(Point(-9783061.694736, 5922896.763395)) - addPoint(Point(-9844502.151022, 5936640.023354)) - addPoint(Point(-9773360.570059, 6019099.583107)) - addPoint(Point(-9883306.649729, 5968977.105610)) - addPoint(Point(-9957681.938918, 5912387.211662)) - addPoint(Point(-10055501.612742, 5871965.858842)) - addPoint(Point(-10116942.069028, 5884092.264688)) - addPoint(Point(-10111283.079633, 5933406.315128)) - addPoint(Point(-10214761.742852, 5888134.399970)) - addPoint(Point(-10254374.668616, 5901877.659929)) - }.toGeometry() - } - - private val borderPolyline by lazy { - PolylineBuilder(SpatialReference.webMercator()) { - addPoint(Point(-9981328.687124, 6111053.281447)) - addPoint(Point(-9946518.044066, 6102350.620682)) - addPoint(Point(-9872545.427566, 6152390.920079)) - addPoint(Point(-9838822.617103, 6157830.083057)) - addPoint(Point(-9446115.050097, 5927209.572793)) - addPoint(Point(-9430885.393759, 5876081.440801)) - addPoint(Point(-9415655.737420, 5860851.784463)) - }.toGeometry() - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - // set up data binding for the activity - val activityMainBinding: ActivityMainBinding = - DataBindingUtil.setContentView(this, R.layout.activity_main) - val mapView = activityMainBinding.mapView - lifecycle.addObserver(mapView) - val cutButton = activityMainBinding.cutButton - val resetButton = activityMainBinding.resetButton - - // set the map to be displayed in this view - mapView.map = ArcGISMap(BasemapStyle.ArcGISTopographic) - - // create a graphic overlay - val graphicsOverlay = GraphicsOverlay() - mapView.graphicsOverlays.add(graphicsOverlay) - - val (polygonGraphic, polylineGraphic) = createGraphics(graphicsOverlay, mapView) - - cutButton.setOnClickListener { - // cut the graphic along the polyline to create 2 graphic parts - polygonGraphic.geometry?.let { graphicGeometry -> - val parts = GeometryEngine.tryCut( - graphicGeometry, - polylineGraphic.geometry as Polyline - ) - - // create graphics for the US and Canada sides - val canadaSide = Graphic( - parts[0], SimpleFillSymbol( - SimpleFillSymbolStyle.BackwardDiagonal, - Color.green, SimpleLineSymbol(SimpleLineSymbolStyle.Null, Color.blue, 0F) - ) - ) - val usSide = Graphic( - parts[1], SimpleFillSymbol( - SimpleFillSymbolStyle.ForwardDiagonal, - Color.yellow, SimpleLineSymbol(SimpleLineSymbolStyle.Null, Color.blue, 0F) - ) - ) - // add the graphics to the graphics overlay - graphicsOverlay.graphics.addAll(listOf(canadaSide, usSide)) - - // swap button state - cutButton.isEnabled = false - resetButton.isEnabled = true - } - } - - resetButton.setOnClickListener { - // clear existing graphics - graphicsOverlay.graphics.clear() - - // recreate original graphics - createGraphics(graphicsOverlay, mapView) - - // swap button state - cutButton.isEnabled = true - resetButton.isEnabled = false - } - - } - - /** - * Create polygon and polyline graphics. - * - * @return polygon and polyline graphics - */ - private fun createGraphics( - graphicsOverlay: GraphicsOverlay, - mapView: MapView - ): Pair { - // create a blue polygon graphic to cut - val polygonGraphic = Graphic( - lakeSuperiorPolygon, - SimpleFillSymbol( - SimpleFillSymbolStyle.Solid, Color(R.color.transparentBlue), - SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.blue, 2F) - ) - ) - graphicsOverlay.graphics.add(polygonGraphic) - - // create a red polyline graphic to cut the polygon - val polylineGraphic = Graphic( - borderPolyline, SimpleLineSymbol( - SimpleLineSymbolStyle.Dot, - Color.red, 3F - ) - ) - graphicsOverlay.graphics.add(polylineGraphic) - // zoom to show the polygon graphic - polygonGraphic.geometry?.let { graphicGeometry -> - mapView.setViewpoint(Viewpoint(graphicGeometry)) - } - return Pair(polygonGraphic, polylineGraphic) - } - - private val Color.Companion.blue: Color - get() { - return fromRgba(0, 0, 255, 255) - } - - private val Color.Companion.yellow: Color - get() { - return fromRgba(255, 255, 0, 255) - } -} diff --git a/cut-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml b/cut-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/cut-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/cut-geometry/src/main/res/drawable/ic_launcher_background.xml b/cut-geometry/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/cut-geometry/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/cut-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/cut-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/cut-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/cut-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/cut-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/cut-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/cut-geometry/src/main/res/mipmap-hdpi/ic_launcher.png b/cut-geometry/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/cut-geometry/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png b/cut-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/cut-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-mdpi/ic_launcher.png b/cut-geometry/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/cut-geometry/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png b/cut-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/cut-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png b/cut-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/cut-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/cut-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/cut-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png b/cut-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/cut-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/cut-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/cut-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/cut-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/cut-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/cut-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/cut-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/cut-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/cut-geometry/src/main/res/values/strings.xml b/cut-geometry/src/main/res/values/strings.xml deleted file mode 100644 index 93f6c7659..000000000 --- a/cut-geometry/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Cut geometry - Cut geometry - Reset - diff --git a/display-clusters/.gitignore b/display-clusters/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/display-clusters/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/display-clusters/build.gradle.kts b/display-clusters/build.gradle.kts deleted file mode 100644 index ef83b8376..000000000 --- a/display-clusters/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.displayclusters" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.displayclusters" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/display-clusters/proguard-rules.pro b/display-clusters/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/display-clusters/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/display-clusters/src/main/AndroidManifest.xml b/display-clusters/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/display-clusters/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/display-clusters/src/main/java/com/esri/arcgismaps/sample/displayclusters/MainActivity.kt b/display-clusters/src/main/java/com/esri/arcgismaps/sample/displayclusters/MainActivity.kt deleted file mode 100644 index 1d507ca55..000000000 --- a/display-clusters/src/main/java/com/esri/arcgismaps/sample/displayclusters/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displayclusters - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.displayclusters.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - FeatureReductionApp() - } - } - } - - @Composable - private fun FeatureReductionApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/display-clusters/src/main/res/drawable-v24/ic_launcher_foreground.xml b/display-clusters/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/display-clusters/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/display-clusters/src/main/res/drawable/ic_launcher_background.xml b/display-clusters/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/display-clusters/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/display-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/display-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-clusters/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-clusters/src/main/res/mipmap-hdpi/ic_launcher.png b/display-clusters/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/display-clusters/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-hdpi/ic_launcher_round.png b/display-clusters/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/display-clusters/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-mdpi/ic_launcher.png b/display-clusters/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/display-clusters/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-mdpi/ic_launcher_round.png b/display-clusters/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/display-clusters/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-xhdpi/ic_launcher.png b/display-clusters/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/display-clusters/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/display-clusters/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/display-clusters/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-xxhdpi/ic_launcher.png b/display-clusters/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/display-clusters/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/display-clusters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/display-clusters/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/display-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/display-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/display-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/display-clusters/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-clusters/src/main/res/values/strings.xml b/display-clusters/src/main/res/values/strings.xml deleted file mode 100644 index d0352fc1e..000000000 --- a/display-clusters/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Display clusters - https://www.arcgis.com/ - diff --git a/display-composable-mapview/.gitignore b/display-composable-mapview/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/display-composable-mapview/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/display-composable-mapview/build.gradle.kts b/display-composable-mapview/build.gradle.kts deleted file mode 100644 index 4a3921c15..000000000 --- a/display-composable-mapview/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.displaycomposablemapview" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.displaycomposablemapview" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/display-composable-mapview/proguard-rules.pro b/display-composable-mapview/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/display-composable-mapview/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/display-composable-mapview/src/main/AndroidManifest.xml b/display-composable-mapview/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/display-composable-mapview/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/display-composable-mapview/src/main/java/com/esri/arcgismaps/sample/displaycomposablemapview/MainActivity.kt b/display-composable-mapview/src/main/java/com/esri/arcgismaps/sample/displaycomposablemapview/MainActivity.kt deleted file mode 100644 index 7e214d9f6..000000000 --- a/display-composable-mapview/src/main/java/com/esri/arcgismaps/sample/displaycomposablemapview/MainActivity.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displaycomposablemapview - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.ui.Modifier -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.toolkit.geoviewcompose.MapView -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - // create a map with a navigation night basemap style - val map = ArcGISMap(BasemapStyle.ArcGISNavigationNight) - MapView( - modifier = Modifier.fillMaxSize(), - arcGISMap = map - ) - } - } - } -} diff --git a/display-composable-mapview/src/main/res/drawable-v24/ic_launcher_foreground.xml b/display-composable-mapview/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/display-composable-mapview/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/display-composable-mapview/src/main/res/drawable/ic_launcher_background.xml b/display-composable-mapview/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/display-composable-mapview/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-composable-mapview/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/display-composable-mapview/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-composable-mapview/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-composable-mapview/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/display-composable-mapview/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-composable-mapview/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-composable-mapview/src/main/res/mipmap-hdpi/ic_launcher.png b/display-composable-mapview/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-hdpi/ic_launcher_round.png b/display-composable-mapview/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-mdpi/ic_launcher.png b/display-composable-mapview/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-mdpi/ic_launcher_round.png b/display-composable-mapview/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-xhdpi/ic_launcher.png b/display-composable-mapview/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/display-composable-mapview/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-xxhdpi/ic_launcher.png b/display-composable-mapview/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/display-composable-mapview/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/display-composable-mapview/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/display-composable-mapview/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/display-composable-mapview/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-composable-mapview/src/main/res/values/strings.xml b/display-composable-mapview/src/main/res/values/strings.xml deleted file mode 100644 index cddd6bc7b..000000000 --- a/display-composable-mapview/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Display composable mapView - diff --git a/display-device-location-with-nmea-data-sources/.gitignore b/display-device-location-with-nmea-data-sources/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/display-device-location-with-nmea-data-sources/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/display-device-location-with-nmea-data-sources/build.gradle.kts b/display-device-location-with-nmea-data-sources/build.gradle.kts deleted file mode 100644 index 1c8d60d70..000000000 --- a/display-device-location-with-nmea-data-sources/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.displaydevicelocationwithnmeadatasources" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.displaydevicelocationwithnmeadatasources" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(libs.androidx.appcompat) - implementation(project(":samples-lib")) -} diff --git a/display-device-location-with-nmea-data-sources/proguard-rules.pro b/display-device-location-with-nmea-data-sources/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/display-device-location-with-nmea-data-sources/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/display-device-location-with-nmea-data-sources/src/main/AndroidManifest.xml b/display-device-location-with-nmea-data-sources/src/main/AndroidManifest.xml deleted file mode 100644 index 07ff67411..000000000 --- a/display-device-location-with-nmea-data-sources/src/main/AndroidManifest.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-device-location-with-nmea-data-sources/src/main/java/com/esri/arcgismaps/sample/displaydevicelocationwithnmeadatasources/DownloadActivity.kt b/display-device-location-with-nmea-data-sources/src/main/java/com/esri/arcgismaps/sample/displaydevicelocationwithnmeadatasources/DownloadActivity.kt deleted file mode 100644 index c63dc3b5f..000000000 --- a/display-device-location-with-nmea-data-sources/src/main/java/com/esri/arcgismaps/sample/displaydevicelocationwithnmeadatasources/DownloadActivity.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.esri.arcgismaps.sample.displaydevicelocationwithnmeadatasources - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // ArcGIS Portal item containing the Redlands.nmea - // which features a vehicle driving around southern Redlands, CA. - "https://www.arcgis.com/home/item.html?id=d5bad9f4fee9483791e405880fb466da" - ) - - ) - } -} diff --git a/display-device-location-with-nmea-data-sources/src/main/java/com/esri/arcgismaps/sample/displaydevicelocationwithnmeadatasources/MainActivity.kt b/display-device-location-with-nmea-data-sources/src/main/java/com/esri/arcgismaps/sample/displaydevicelocationwithnmeadatasources/MainActivity.kt deleted file mode 100644 index 2d8bfa7b2..000000000 --- a/display-device-location-with-nmea-data-sources/src/main/java/com/esri/arcgismaps/sample/displaydevicelocationwithnmeadatasources/MainActivity.kt +++ /dev/null @@ -1,277 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displaydevicelocationwithnmeadatasources - -import android.os.Bundle -import android.util.Log -import android.view.View -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.content.res.AppCompatResources -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.location.LocationDataSourceStatus -import com.arcgismaps.location.LocationDisplayAutoPanMode -import com.arcgismaps.location.NmeaGnssSystem -import com.arcgismaps.location.NmeaLocationDataSource -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.esri.arcgismaps.sample.displaydevicelocationwithnmeadatasources.databinding.ActivityMainBinding -import com.google.android.material.floatingactionbutton.FloatingActionButton -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File -import java.nio.charset.StandardCharsets -import java.util.* -import kotlin.concurrent.timerTask - -class MainActivity : AppCompatActivity() { - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - // create a new NMEA location data source - private val nmeaLocationDataSource: NmeaLocationDataSource = - NmeaLocationDataSource(SpatialReference.wgs84()) - - // create a timer to simulate a stream of NMEA data - private var timer = Timer() - - // list of nmea location sentences - private var nmeaSentences: List? = emptyList() - - // index of nmea location sentence - private var locationIndex = 0 - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val accuracyTV: TextView by lazy { - activityMainBinding.accuracyTV - } - - private val satelliteCountTV: TextView by lazy { - activityMainBinding.satelliteCountTV - } - - private val satelliteIDsTV: TextView by lazy { - activityMainBinding.satelliteIDsTV - } - - private val systemTypeTV: TextView by lazy { - activityMainBinding.systemTypeTV - } - - private val playPauseFAB: FloatingActionButton by lazy { - activityMainBinding.playPauseFAB - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // create and add a map with a navigation night basemap style - val map = ArcGISMap(BasemapStyle.ArcGISNavigationNight) - mapView.map = map - - // set a viewpoint on the map view centered on Redlands, California - mapView.setViewpoint( - Viewpoint( - Point(-117.191, 34.0306, SpatialReference.wgs84()), 100000.0 - ) - ) - - mapView.locationDisplay.apply { - // set the map view's location display to use the nmea location data source - dataSource = nmeaLocationDataSource - // set the map view to recenter on location changed events - setAutoPanMode(LocationDisplayAutoPanMode.Recenter) - } - - // disable map view interaction, the location display will automatically center on the mock device location - mapView.interactionOptions.apply { - isPanEnabled = false - isZoomEnabled = false - isRotateEnabled = false - } - - // read nmea location sentences from file - nmeaSentences = getNMEASentenceList() - // collects the accuracy for each location change - collectLocationChanges() - // collects satellite changes and display satellite information - collectSatelliteChanges() - } - - /** - * Reads NMEA location sentences from the .nmea file and - * returns it as a [MutableList] - */ - private fun getNMEASentenceList(): List? { - val simulatedNmeaDataFile = File("$provisionPath/Redlands.nmea") - if (!simulatedNmeaDataFile.exists()) { - showError("NMEA file does not exist") - return null - } - // create list of nmea location sentences - var nmeaSentences: List = emptyList() - // create a buffered reader using the .nmea file - val bufferedReader = File(simulatedNmeaDataFile.path).bufferedReader() - // read the nmea file contents using a buffered reader and store the mock data sentences in a list - bufferedReader.useLines { bufferReaderLines -> - // add carriage return for nmea location data source parser - nmeaSentences = bufferReaderLines.map { it + "\n" }.toList() - } - return nmeaSentences - } - - /** - * Control the start/stop status of the NMEA location data source - */ - fun playPauseClick(view: View) = lifecycleScope.launch { - if (nmeaLocationDataSource.status.value != LocationDataSourceStatus.Started) { - // initialize the location data source and prepare to begin receiving location updates when data is pushed - // as updates are received, they will be displayed on the map - nmeaLocationDataSource.start().onFailure { - showError("NmeaLocationDataSource failed to start: ${it.message}") - return@launch - } - // starts the NMEA mock data sentences - nmeaSentences?.let { startNMEAMockData(it) } - setButtonStatus(true) - } else { - // stop receiving and displaying location data - nmeaLocationDataSource.stop() - // cancel up the timer task - timer.cancel() - setButtonStatus(false) - clearUI() - } - } - - /** - * Initializes the location data source, reads the mock data NMEA sentences, and displays location updates from that file - * on the location display. Data is pushed to the data source using a timeline to simulate live updates, as they would - * appear if using real-time data from a GPS dongle - */ - - /** - * Push the mock data NMEA sentences into the data source every 250 ms - */ - private fun startNMEAMockData(nmeaSentences: List) { - timer = Timer() - timer.schedule(timerTask { - // only push data when started - if (nmeaLocationDataSource.status.value == LocationDataSourceStatus.Started) - nmeaLocationDataSource.pushData( - nmeaSentences[locationIndex++].toByteArray(StandardCharsets.UTF_8) - ) - // reset the location index after the last data point is reached - if (locationIndex == nmeaSentences.size) locationIndex = 0 - }, 250, 250) - } - - /** - * Sets the FAB button to "Start"/"Stop" based on [isShowingLocation] - */ - private fun setButtonStatus(isShowingLocation: Boolean) = if (isShowingLocation) { - playPauseFAB.setImageDrawable( - AppCompatResources.getDrawable( - this, R.drawable.ic_round_pause_24 - ) - ) - } else { - playPauseFAB.setImageDrawable( - AppCompatResources.getDrawable( - this, R.drawable.ic_round_play_arrow_24 - ) - ) - } - - /** - * Collects location changes of the NMEA location data source, - * and displays the location accuracy - */ - private fun collectLocationChanges() = lifecycleScope.launch { - nmeaLocationDataSource.locationChanged.collect { nmeaLocation -> - // convert from meters to foot - val horizontalAccuracy = nmeaLocation.horizontalAccuracy * 3.28084 - val verticalAccuracy = nmeaLocation.verticalAccuracy * 3.28084 - accuracyTV.text = - getString(R.string.accuracy) + "Horizontal-%.1fft, Vertical-%.1fft".format( - horizontalAccuracy, verticalAccuracy - ) - } - } - - /** - * Obtains NMEA satellite information from the NMEA location data source, - * and displays satellite information on the app - */ - private fun collectSatelliteChanges() = lifecycleScope.launch { - nmeaLocationDataSource.satellitesChanged.collect { nmeaSatelliteInfoList -> - // set the text of the satellite count label - satelliteCountTV.text = getString(R.string.satellite_count) + nmeaSatelliteInfoList.size - // get the system of the first satellite - val satelliteSystems = when (nmeaSatelliteInfoList.first().system) { - NmeaGnssSystem.Bds -> "BDS" - NmeaGnssSystem.Galileo -> "Galileo" - NmeaGnssSystem.Glonass -> "Glonass" - NmeaGnssSystem.Gps -> "GPS" - NmeaGnssSystem.NavIc -> "NavIc" - NmeaGnssSystem.Qzss -> "Qzss" - NmeaGnssSystem.Unknown -> "Unknown" - } - // get the satellite IDs from the info list - val uniqueSatelliteIDs = nmeaSatelliteInfoList.map { it.id } - // display the satellite system and id information - systemTypeTV.text = getString(R.string.system) + satelliteSystems - satelliteIDsTV.text = getString(R.string.satellite_ids) + uniqueSatelliteIDs - } - } - - /** - * Clears out the info messages when LocationDataSource is paused. - */ - private fun clearUI() { - accuracyTV.text = getString(R.string.accuracy) - satelliteCountTV.text = getString(R.string.satellite_count) - satelliteIDsTV.text = getString(R.string.satellite_ids) - systemTypeTV.text = getString(R.string.system) - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/display-device-location-with-nmea-data-sources/src/main/res/drawable-v24/ic_launcher_foreground.xml b/display-device-location-with-nmea-data-sources/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/display-device-location-with-nmea-data-sources/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/display-device-location-with-nmea-data-sources/src/main/res/drawable/ic_launcher_background.xml b/display-device-location-with-nmea-data-sources/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/display-device-location-with-nmea-data-sources/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-hdpi/ic_launcher.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-hdpi/ic_launcher_round.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-mdpi/ic_launcher.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-mdpi/ic_launcher_round.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xhdpi/ic_launcher.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxhdpi/ic_launcher.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/display-device-location-with-nmea-data-sources/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-device-location-with-nmea-data-sources/src/main/res/values/strings.xml b/display-device-location-with-nmea-data-sources/src/main/res/values/strings.xml deleted file mode 100644 index a77258522..000000000 --- a/display-device-location-with-nmea-data-sources/src/main/res/values/strings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - Display device location with NMEA data sources - Start/Stop button - Accuracy: - Satellite Count: - System: - Satellite IDs: - diff --git a/display-dimensions/.gitignore b/display-dimensions/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/display-dimensions/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/display-dimensions/README.md b/display-dimensions/README.md deleted file mode 100644 index 8ec9d3164..000000000 --- a/display-dimensions/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# Display dimensions - -Display dimension features from a mobile map package. - -![Image showing the Display Dimensions sample](display-dimensions.png) - -## Use case - -Dimensions show specific lengths or distances on a map. A dimension may indicate the length of a side of a building or land parcel, or the distance between two features, such as a fire hydrant and the corner of a building. - -## How to use the sample - -When the sample loads, it will automatically display the map containing dimension features from the mobile map package. The name of the dimension layer containing the dimension features is displayed in the controls box. Control the visibility of the dimension layer with the "Dimension Settings" button, and apply a definition expression to show dimensions of greater than or equal to 450m in length using the "Definition Expression" switch. - -## How it works - -1. Create a `MobileMapPackage` specifying the path to the .mmpk file. -2. Load the mobile map package with `mobileMapPackage.load()`. -3. After it successfully loads, get the first map from the mmpk and set it to the map view: `mapView.map = mobileMapPackage.maps[0]`. -4. Loop through the map's layers to create a `DimensionLayer`. -5. Control the dimension layer's visibility with `dimensionLayer.isVisible` and set a definition expression with `dimensionLayer.definitionExpression`. - -## Relevant API - -* DimensionLayer -* MobileMapPackage - -## About the data - -This sample shows a subset of the Edinburgh, Scotland network of pylons, substations, and powerlines within an [Edinburgh Pylon Dimensions mobile map package](https://arcgis.com/home/item.html?id=f5ff6f5556a945bca87ca513b8729a1e), digitized from satellite imagery. Note the data is intended as illustrative of the network only. - -## Additional information - -Dimension layers can be taken offline from a feature service hosted on ArcGIS Enterprise 10.9 or later, using the [GeodatabaseSyncTask](https://developers.arcgis.com/java/api-reference/reference/com/esri/arcgisruntime/tasks/geodatabase/GeodatabaseSyncTask.html). Dimension layers are also supported in mobile map packages or mobile geodatabases created in ArcGIS Pro 2.9 or later. - -## Tags - -dimension, layer, mmpk, mobile map package, utility diff --git a/display-dimensions/build.gradle.kts b/display-dimensions/build.gradle.kts deleted file mode 100644 index 75ff23e82..000000000 --- a/display-dimensions/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.displaydimensions" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.displaydimensions" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(libs.androidx.appcompat) - implementation(project(":samples-lib")) -} diff --git a/display-dimensions/proguard-rules.pro b/display-dimensions/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/display-dimensions/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/display-dimensions/src/main/AndroidManifest.xml b/display-dimensions/src/main/AndroidManifest.xml deleted file mode 100644 index a524252ff..000000000 --- a/display-dimensions/src/main/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/display-dimensions/src/main/java/com/esri/arcgismaps/sample/displaydimensions/DownloadActivity.kt b/display-dimensions/src/main/java/com/esri/arcgismaps/sample/displaydimensions/DownloadActivity.kt deleted file mode 100644 index b757d083a..000000000 --- a/display-dimensions/src/main/java/com/esri/arcgismaps/sample/displaydimensions/DownloadActivity.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.esri.arcgismaps.sample.displaydimensions - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // ArcGIS Portal item containing the mmpk file which is a section of the - // high-voltage electricity transmission network around Edinburgh, Scotland. - "https://www.arcgis.com/home/item.html?id=f5ff6f5556a945bca87ca513b8729a1e" - ) - ) - } -} diff --git a/display-dimensions/src/main/java/com/esri/arcgismaps/sample/displaydimensions/MainActivity.kt b/display-dimensions/src/main/java/com/esri/arcgismaps/sample/displaydimensions/MainActivity.kt deleted file mode 100644 index dca5f1be4..000000000 --- a/display-dimensions/src/main/java/com/esri/arcgismaps/sample/displaydimensions/MainActivity.kt +++ /dev/null @@ -1,135 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displaydimensions - -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.mapping.MobileMapPackage -import com.arcgismaps.mapping.layers.DimensionLayer -import com.esri.arcgismaps.sample.displaydimensions.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.displaydimensions.databinding.DimensionsDialogLayoutBinding -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File - -class MainActivity : AppCompatActivity() { - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val optionsButton by lazy { - activityMainBinding.optionsButton - } - - // keep an instance of the MapView's dimension layer - private var dimensionLayer: DimensionLayer? = null - - // track if the layer is enabled - private var isDimensionLayerEnabled: Boolean = true - - // track if the custom definition is enabled - private var isDefinitionEnabled: Boolean = false - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // check if the .mmpk file exits - val mmpkFile = File(provisionPath, getString(R.string.file_name)) - if (!mmpkFile.exists()) return showError("Mobile map package file does not exist.") - - // create and load a mobile map package - val mobileMapPackage = MobileMapPackage(mmpkFile.path) - - lifecycleScope.launch { - // load the mobile map package - mobileMapPackage.load().getOrElse { - return@launch showError("Failed to load the mobile map package: ${it.message}") - } - // if the loaded mobile map package does not contain a map - if (mobileMapPackage.maps.isEmpty()) { - return@launch showError("Mobile map package does not contain a map") - } - - // add the map from the mobile map package to the map view, - // and set a min scale to maintain dimension readability - mapView.map = mobileMapPackage.maps[0] - mapView.map?.minScale = 35000.0 - - // set the dimension layer within the map - dimensionLayer = mapView.map?.operationalLayers?.firstOrNull { layer -> - layer is DimensionLayer - } as DimensionLayer - - } - - optionsButton.setOnClickListener { - // inflate the dialog layout and get references to each of its components - val dialogBinding = DimensionsDialogLayoutBinding.inflate(layoutInflater) - dialogBinding.dimensionLayerSwitch.apply { - isChecked = isDimensionLayerEnabled - setOnCheckedChangeListener { _, isEnabled -> - // set the visibility of the dimension layer - dimensionLayer?.isVisible = isEnabled - isDimensionLayerEnabled = isEnabled - } - } - dialogBinding.definitionSwitch.apply { - isChecked = isDefinitionEnabled - setOnCheckedChangeListener { _, isEnabled -> - // set a definition expression to show dimension lengths of - // greater than or equal to 450m when the checkbox is selected, - // or to reset the definition expression to show all - // dimension lengths when unselected - val defExpression = if (isEnabled) "DIMLENGTH >= 450" else "" - dimensionLayer?.definitionExpression = defExpression - isDefinitionEnabled = isEnabled - } - } - - // set up the dialog - MaterialAlertDialogBuilder(this).apply { - setView(dialogBinding.root) - setTitle("${getString(R.string.settings)}: ${dimensionLayer?.name}") - }.show() - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/display-dimensions/src/main/res/drawable-v24/ic_launcher_foreground.xml b/display-dimensions/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/display-dimensions/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/display-dimensions/src/main/res/drawable/ic_launcher_background.xml b/display-dimensions/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/display-dimensions/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-dimensions/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/display-dimensions/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-dimensions/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-dimensions/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/display-dimensions/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-dimensions/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-dimensions/src/main/res/mipmap-hdpi/ic_launcher.png b/display-dimensions/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/display-dimensions/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-hdpi/ic_launcher_round.png b/display-dimensions/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/display-dimensions/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-mdpi/ic_launcher.png b/display-dimensions/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/display-dimensions/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-mdpi/ic_launcher_round.png b/display-dimensions/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/display-dimensions/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-xhdpi/ic_launcher.png b/display-dimensions/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/display-dimensions/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/display-dimensions/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/display-dimensions/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-xxhdpi/ic_launcher.png b/display-dimensions/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/display-dimensions/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/display-dimensions/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/display-dimensions/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/display-dimensions/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/display-dimensions/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-dimensions/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/display-dimensions/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/display-dimensions/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-dimensions/src/main/res/values/strings.xml b/display-dimensions/src/main/res/values/strings.xml deleted file mode 100644 index 4d80e1948..000000000 --- a/display-dimensions/src/main/res/values/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - Display dimensions - Dimension settings - Dimension Layer - Definition expression: Dimensions >= 450m - Edinburgh_Pylon_Dimensions.mmpk - diff --git a/display-map-from-mobile-map-package/.gitignore b/display-map-from-mobile-map-package/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/display-map-from-mobile-map-package/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/display-map-from-mobile-map-package/build.gradle.kts b/display-map-from-mobile-map-package/build.gradle.kts deleted file mode 100644 index deee869e3..000000000 --- a/display-map-from-mobile-map-package/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.displaymapfrommobilemappackage" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.displaymapfrommobilemappackage" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/display-map-from-mobile-map-package/proguard-rules.pro b/display-map-from-mobile-map-package/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/display-map-from-mobile-map-package/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/display-map-from-mobile-map-package/src/main/AndroidManifest.xml b/display-map-from-mobile-map-package/src/main/AndroidManifest.xml deleted file mode 100644 index a524252ff..000000000 --- a/display-map-from-mobile-map-package/src/main/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/display-map-from-mobile-map-package/src/main/java/com/esri/arcgismaps/sample/displaymapfrommobilemappackage/DownloadActivity.kt b/display-map-from-mobile-map-package/src/main/java/com/esri/arcgismaps/sample/displaymapfrommobilemappackage/DownloadActivity.kt deleted file mode 100644 index fb390329c..000000000 --- a/display-map-from-mobile-map-package/src/main/java/com/esri/arcgismaps/sample/displaymapfrommobilemappackage/DownloadActivity.kt +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displaymapfrommobilemappackage - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // ArcGIS Portal item containing the .mmpk mobile map package - "https://www.arcgis.com/home/item.html?id=e1f3a7254cb845b09450f54937c16061" - ) - - ) - } -} diff --git a/display-map-from-mobile-map-package/src/main/java/com/esri/arcgismaps/sample/displaymapfrommobilemappackage/MainActivity.kt b/display-map-from-mobile-map-package/src/main/java/com/esri/arcgismaps/sample/displaymapfrommobilemappackage/MainActivity.kt deleted file mode 100644 index 0844febe7..000000000 --- a/display-map-from-mobile-map-package/src/main/java/com/esri/arcgismaps/sample/displaymapfrommobilemappackage/MainActivity.kt +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displaymapfrommobilemappackage - -import android.os.Bundle -import android.util.Log -import android.view.View -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.mapping.MobileMapPackage -import com.esri.arcgismaps.sample.displaymapfrommobilemappackage.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File - -class MainActivity : AppCompatActivity() { - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - // set up data binding for the activity - val activityMainBinding: ActivityMainBinding = - DataBindingUtil.setContentView(this, R.layout.activity_main) - // create and add the MapView to the lifecycle - val mapView = activityMainBinding.mapView - lifecycle.addObserver(mapView) - - // get the file path of the (.mmpk) file - val filePath = provisionPath + getString(R.string.yellowstone_mmpk) - - // create the mobile map package - val mapPackage = MobileMapPackage(filePath) - - lifecycleScope.launch { - // load the mobile map package - mapPackage.load().getOrElse { - showError(it.message.toString(), mapView) - } - // add the map from the mobile map package to the MapView - mapView.map = mapPackage.maps.first() - } - } - - private fun showError(message: String, view: View) { - Log.e(localClassName, message) - Snackbar.make(view, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/display-map-from-mobile-map-package/src/main/res/drawable-v24/ic_launcher_foreground.xml b/display-map-from-mobile-map-package/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/display-map-from-mobile-map-package/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/display-map-from-mobile-map-package/src/main/res/drawable/ic_launcher_background.xml b/display-map-from-mobile-map-package/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/display-map-from-mobile-map-package/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/display-map-from-mobile-map-package/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-map-from-mobile-map-package/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/display-map-from-mobile-map-package/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-map-from-mobile-map-package/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-hdpi/ic_launcher.png b/display-map-from-mobile-map-package/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-hdpi/ic_launcher_round.png b/display-map-from-mobile-map-package/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-mdpi/ic_launcher.png b/display-map-from-mobile-map-package/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-mdpi/ic_launcher_round.png b/display-map-from-mobile-map-package/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-xhdpi/ic_launcher.png b/display-map-from-mobile-map-package/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/display-map-from-mobile-map-package/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-xxhdpi/ic_launcher.png b/display-map-from-mobile-map-package/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/display-map-from-mobile-map-package/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/display-map-from-mobile-map-package/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/display-map-from-mobile-map-package/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/display-map-from-mobile-map-package/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map-from-mobile-map-package/src/main/res/values/strings.xml b/display-map-from-mobile-map-package/src/main/res/values/strings.xml deleted file mode 100644 index bbf2930a2..000000000 --- a/display-map-from-mobile-map-package/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Display map from mobile map package - /Yellowstone.mmpk - diff --git a/display-map/.gitignore b/display-map/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/display-map/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/display-map/build.gradle.kts b/display-map/build.gradle.kts deleted file mode 100644 index a9fc7d09d..000000000 --- a/display-map/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.displaymap" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.displaymap" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/display-map/proguard-rules.pro b/display-map/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/display-map/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/display-map/src/main/AndroidManifest.xml b/display-map/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/display-map/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/display-map/src/main/java/com/esri/arcgismaps/sample/displaymap/MainActivity.kt b/display-map/src/main/java/com/esri/arcgismaps/sample/displaymap/MainActivity.kt deleted file mode 100644 index a8be48198..000000000 --- a/display-map/src/main/java/com/esri/arcgismaps/sample/displaymap/MainActivity.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displaymap - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.esri.arcgismaps.sample.displaymap.databinding.ActivityMainBinding - -class MainActivity : AppCompatActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - // set up data binding for the activity - val activityMainBinding: ActivityMainBinding = - DataBindingUtil.setContentView(this, R.layout.activity_main) - lifecycle.addObserver(activityMainBinding.mapView) - - // create and add a map with a navigation night basemap style - val map = ArcGISMap(BasemapStyle.ArcGISNavigationNight) - activityMainBinding.mapView.map = map - } -} diff --git a/display-map/src/main/res/drawable-v24/ic_launcher_foreground.xml b/display-map/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/display-map/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/display-map/src/main/res/drawable/ic_launcher_background.xml b/display-map/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/display-map/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-map/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/display-map/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-map/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-map/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/display-map/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-map/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-map/src/main/res/mipmap-hdpi/ic_launcher.png b/display-map/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/display-map/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-hdpi/ic_launcher_round.png b/display-map/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/display-map/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-mdpi/ic_launcher.png b/display-map/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/display-map/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-mdpi/ic_launcher_round.png b/display-map/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/display-map/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-xhdpi/ic_launcher.png b/display-map/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/display-map/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/display-map/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/display-map/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-xxhdpi/ic_launcher.png b/display-map/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/display-map/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/display-map/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/display-map/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/display-map/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/display-map/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-map/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/display-map/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/display-map/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-map/src/main/res/values/strings.xml b/display-map/src/main/res/values/strings.xml deleted file mode 100644 index 58953e88d..000000000 --- a/display-map/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Display map - diff --git a/display-scene-from-mobile-scene-package/.gitignore b/display-scene-from-mobile-scene-package/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/display-scene-from-mobile-scene-package/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/display-scene-from-mobile-scene-package/build.gradle.kts b/display-scene-from-mobile-scene-package/build.gradle.kts deleted file mode 100644 index f9da5e2d2..000000000 --- a/display-scene-from-mobile-scene-package/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.displayscenefrommobilescenepackage" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.displayscenefrommobilescenepackage" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/display-scene-from-mobile-scene-package/proguard-rules.pro b/display-scene-from-mobile-scene-package/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/display-scene-from-mobile-scene-package/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/display-scene-from-mobile-scene-package/src/main/AndroidManifest.xml b/display-scene-from-mobile-scene-package/src/main/AndroidManifest.xml deleted file mode 100644 index a524252ff..000000000 --- a/display-scene-from-mobile-scene-package/src/main/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/DownloadActivity.kt b/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/DownloadActivity.kt deleted file mode 100644 index f1b7093f5..000000000 --- a/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/DownloadActivity.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displayscenefrommobilescenepackage - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // ArcGIS Portal item containing the .mspk mobile scene package - "https://www.arcgis.com/home/item.html?id=7dd2f97bb007466ea939160d0de96a9d" - ) - ) - } -} diff --git a/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/MainActivity.kt b/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/MainActivity.kt deleted file mode 100644 index 48a800e18..000000000 --- a/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/MainActivity.kt +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displayscenefrommobilescenepackage - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.displayscenefrommobilescenepackage.screens.MainScreen -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - DisplaySceneFromMobileScenePackageApp() - } - } - } - - @Composable - private fun DisplaySceneFromMobileScenePackageApp() { - Surface(color = MaterialTheme.colorScheme.background) { - MainScreen(sampleName = getString(R.string.app_name)) - } - } -} diff --git a/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/components/SceneViewModel.kt b/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/components/SceneViewModel.kt deleted file mode 100644 index 02d3f6c2c..000000000 --- a/display-scene-from-mobile-scene-package/src/main/java/com/esri/arcgismaps/sample/displayscenefrommobilescenepackage/components/SceneViewModel.kt +++ /dev/null @@ -1,72 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displayscenefrommobilescenepackage.components - -import android.app.Application -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.setValue -import androidx.lifecycle.AndroidViewModel -import com.arcgismaps.mapping.ArcGISScene -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.MobileScenePackage -import com.esri.arcgismaps.sample.displayscenefrommobilescenepackage.R -import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import java.io.File - -class SceneViewModel( - private val application: Application, - private val sampleCoroutineScope: CoroutineScope -) : AndroidViewModel(application) { - - // create a base scene to be used to load the mobile scene package - var scene by mutableStateOf(ArcGISScene(BasemapStyle.ArcGISStreets)) - - // create a ViewModel to handle dialog interactions - val messageDialogVM: MessageDialogViewModel = MessageDialogViewModel() - - private val provisionPath: String by lazy { - application.getExternalFilesDir(null)?.path.toString() + File.separator + application.getString( - R.string.app_name - ) - } - - init { - createMobileScenePackage() - } - - private fun createMobileScenePackage() { - // get the file path of the (.mspk) file - val filePath = provisionPath + application.getString(R.string.philadelphia_mspk) - - // create the mobile scene package - val mobileScenePackage = MobileScenePackage(filePath) - - sampleCoroutineScope.launch { - // load the mobile scene package - mobileScenePackage.load().onSuccess { - // update the mutable state holder with the first scene from the MobileScenePackage - scene = mobileScenePackage.scenes.first() - }.onFailure { error -> - // show the message dialog and pass the error message to be displayed in the dialog - messageDialogVM.showMessageDialog(error.message.toString(), error.cause.toString()) - } - } - } -} diff --git a/display-scene-from-mobile-scene-package/src/main/res/drawable-v24/ic_launcher_foreground.xml b/display-scene-from-mobile-scene-package/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/display-scene-from-mobile-scene-package/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/display-scene-from-mobile-scene-package/src/main/res/drawable/ic_launcher_background.xml b/display-scene-from-mobile-scene-package/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/display-scene-from-mobile-scene-package/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/display-scene-from-mobile-scene-package/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-scene-from-mobile-scene-package/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/display-scene-from-mobile-scene-package/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-scene-from-mobile-scene-package/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-hdpi/ic_launcher.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-hdpi/ic_launcher_round.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-mdpi/ic_launcher.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-mdpi/ic_launcher_round.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xhdpi/ic_launcher.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxhdpi/ic_launcher.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/display-scene-from-mobile-scene-package/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene-from-mobile-scene-package/src/main/res/values/strings.xml b/display-scene-from-mobile-scene-package/src/main/res/values/strings.xml deleted file mode 100644 index 108b13b8f..000000000 --- a/display-scene-from-mobile-scene-package/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Display scene from mobile scene package - /philadelphia.mspk - diff --git a/display-scene/.gitignore b/display-scene/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/display-scene/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/display-scene/build.gradle.kts b/display-scene/build.gradle.kts deleted file mode 100644 index 69367856e..000000000 --- a/display-scene/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.displayscene" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.displayscene" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/display-scene/proguard-rules.pro b/display-scene/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/display-scene/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/display-scene/src/main/AndroidManifest.xml b/display-scene/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/display-scene/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/display-scene/src/main/java/com/esri/arcgismaps/sample/displayscene/MainActivity.kt b/display-scene/src/main/java/com/esri/arcgismaps/sample/displayscene/MainActivity.kt deleted file mode 100644 index 51162a418..000000000 --- a/display-scene/src/main/java/com/esri/arcgismaps/sample/displayscene/MainActivity.kt +++ /dev/null @@ -1,76 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.displayscene - -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.mapping.ArcGISScene -import com.arcgismaps.mapping.ArcGISTiledElevationSource -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.view.Camera -import com.esri.arcgismaps.sample.displayscene.databinding.ActivityMainBinding - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val sceneView by lazy { - activityMainBinding.sceneView - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(sceneView) - - // create an elevation source, and add this to the base surface of the scene - val elevationSource = ArcGISTiledElevationSource( - resources.getString(R.string.elevation_image_service) - ) - - // create a scene with a imagery basemap style - val imageryScene = ArcGISScene(BasemapStyle.ArcGISImagery).apply { - // add the elevation source to the base surface - baseSurface.elevationSources.add(elevationSource) - } - - // add a camera and initial camera position - val camera = Camera( - latitude = 28.4, - longitude = 83.9, - altitude = 10010.0, - heading = 10.0, - pitch = 80.0, - roll = 0.0 - ) - - // apply the scene to the sceneView and set its viewpoint - sceneView.apply { - scene = imageryScene - setViewpointCamera(camera) - } - } -} diff --git a/display-scene/src/main/res/drawable-v24/ic_launcher_foreground.xml b/display-scene/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/display-scene/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/display-scene/src/main/res/drawable/ic_launcher_background.xml b/display-scene/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/display-scene/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/display-scene/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/display-scene/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-scene/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-scene/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/display-scene/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/display-scene/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/display-scene/src/main/res/mipmap-hdpi/ic_launcher.png b/display-scene/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/display-scene/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-hdpi/ic_launcher_round.png b/display-scene/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/display-scene/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-mdpi/ic_launcher.png b/display-scene/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/display-scene/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-mdpi/ic_launcher_round.png b/display-scene/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/display-scene/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-xhdpi/ic_launcher.png b/display-scene/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/display-scene/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/display-scene/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/display-scene/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-xxhdpi/ic_launcher.png b/display-scene/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/display-scene/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/display-scene/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/display-scene/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/display-scene/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/display-scene/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/display-scene/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/display-scene/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/display-scene/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/display-scene/src/main/res/values/strings.xml b/display-scene/src/main/res/values/strings.xml deleted file mode 100644 index 068b43027..000000000 --- a/display-scene/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Display scene - https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer - diff --git a/download-vector-tiles-to-local-cache/.gitignore b/download-vector-tiles-to-local-cache/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/download-vector-tiles-to-local-cache/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/download-vector-tiles-to-local-cache/build.gradle.kts b/download-vector-tiles-to-local-cache/build.gradle.kts deleted file mode 100644 index 8ae706194..000000000 --- a/download-vector-tiles-to-local-cache/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.downloadvectortilestolocalcache" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.downloadvectortilestolocalcache" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/download-vector-tiles-to-local-cache/proguard-rules.pro b/download-vector-tiles-to-local-cache/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/download-vector-tiles-to-local-cache/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/download-vector-tiles-to-local-cache/src/main/AndroidManifest.xml b/download-vector-tiles-to-local-cache/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/download-vector-tiles-to-local-cache/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/download-vector-tiles-to-local-cache/src/main/java/com/esri/arcgismaps/sample/downloadvectortilestolocalcache/MainActivity.kt b/download-vector-tiles-to-local-cache/src/main/java/com/esri/arcgismaps/sample/downloadvectortilestolocalcache/MainActivity.kt deleted file mode 100644 index 38cb42dd3..000000000 --- a/download-vector-tiles-to-local-cache/src/main/java/com/esri/arcgismaps/sample/downloadvectortilestolocalcache/MainActivity.kt +++ /dev/null @@ -1,329 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.downloadvectortilestolocalcache - -import android.os.Bundle -import android.util.Log -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.Envelope -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.Basemap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.ViewpointType -import com.arcgismaps.mapping.layers.ArcGISVectorTiledLayer -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.ScreenCoordinate -import com.arcgismaps.tasks.exportvectortiles.ExportVectorTilesJob -import com.arcgismaps.tasks.exportvectortiles.ExportVectorTilesParameters -import com.arcgismaps.tasks.exportvectortiles.ExportVectorTilesResult -import com.arcgismaps.tasks.exportvectortiles.ExportVectorTilesTask -import com.esri.arcgismaps.sample.downloadvectortilestolocalcache.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.downloadvectortilestolocalcache.databinding.ProgressDialogLayoutBinding -import com.google.android.material.button.MaterialButton -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File - -class MainActivity : AppCompatActivity() { - - private val downloadArea: Graphic = Graphic() - private var hasCurrentJobCompleted: Boolean = true - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val previewMapView by lazy { - activityMainBinding.previewMapView - } - - private val exportVectorTilesButton: MaterialButton by lazy { - activityMainBinding.exportVectorTilesButton - } - - private val closePreviewButton: MaterialButton by lazy { - activityMainBinding.closePreviewButton - } - - // inflate the progress dialog - private val dialogLayoutBinding by lazy { - ProgressDialogLayoutBinding.inflate(layoutInflater) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - // add mapView to the lifecycle - lifecycle.addObserver(mapView) - lifecycle.addObserver(previewMapView) - - // create a graphic to show a red outline square around the vector tiles to be downloaded - downloadArea.symbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.red, 2f) - - // create a graphics overlay and add the downloadArea graphic - val graphicsOverlay = GraphicsOverlay(listOf(downloadArea)) - - mapView.apply { - // set the map to BasemapType navigation night - map = ArcGISMap(BasemapStyle.ArcGISStreetsNight) - // disable rotation - interactionOptions.isRotateEnabled = false - // set the viewpoint of the sample to ESRI Redlands, CA campus - setViewpoint(Viewpoint(34.056295, -117.195800, 100000.0)) - // add the graphics overlay to the MapView - graphicsOverlays.add(graphicsOverlay) - } - - lifecycleScope.launch { - mapView.map?.load()?.onSuccess { - // enable the export tiles button - exportVectorTilesButton.isEnabled = true - // update the red square whenever the viewpoint changes - mapView.viewpointChanged.collect { - updateDownloadAreaGeometry() - } - }?.onFailure { - showMessage("Error loading map") - } - } - } - - /** - * Sets up the ExportVectorTilesTask on export button click. - * Then calls handleExportVectorTilesJob() - */ - fun exportButtonClick(view: View) { - // check that the layer from the basemap is a vector tiled layer - val vectorTiledLayer = - mapView.map?.basemap?.value?.baseLayers?.get(0) as ArcGISVectorTiledLayer - - lifecycleScope.launch { - // update the download area's geometry using the current viewpoint - updateDownloadAreaGeometry() - // create a new export vector tiles task - val exportVectorTilesTask = ExportVectorTilesTask(vectorTiledLayer.uri.toString()) - val geometry = downloadArea.geometry - if (geometry == null) { - showMessage("Error retrieving download area geometry") - return@launch - } - // set the parameters of the export vector tiles task - // using the geometry of the area to export and it's max scale - val exportVectorTilesParametersResult = exportVectorTilesTask - .createDefaultExportVectorTilesParameters( - geometry, - // set the max scale parameter to 10% of the map's scale so the - // number of tiles exported are within the vector tiled layer's max tile export limit - mapView.mapScale.value * 0.1 - ) - - // get the loaded vector tile parameters - val exportVectorTilesParameters = exportVectorTilesParametersResult.getOrElse { - showMessage(it.message.toString()) - return@launch - } - - if (hasCurrentJobCompleted) { - // create a job to export vector tiles - initiateExportTilesJob( - exportVectorTilesParameters, - exportVectorTilesTask - ) - } else { - showMessage("Previous job is cancelling asynchronously") - } - } - - } - - /** - * Start the export vector tiles job using [exportVectorTilesTask] and the - * [exportVectorTilesParameters]. The vector tile package is exported as "file.vtpk" - */ - private fun initiateExportTilesJob( - exportVectorTilesParameters: ExportVectorTilesParameters, - exportVectorTilesTask: ExportVectorTilesTask - ) { - // create a .vtpk and directory in the app's cache for saving exported tiles - val vtpkFile = File(externalCacheDir, "/StyleItemResources/myVectorTiles.vtpk") - val resDir = File(externalCacheDir, "/StyleItemResources") - resDir.deleteRecursively() - resDir.mkdir() - - // create a job with the export vector tile parameters - // and exports the vector tile package as "file.vtpk" - val exportVectorTilesJob = exportVectorTilesTask.createExportVectorTilesJob( - exportVectorTilesParameters, - vtpkFile.absolutePath, resDir.absolutePath - ).apply { - // start the export vector tile cache job - start() - } - - // display the progress dialog - val dialog = createProgressDialog(exportVectorTilesJob).show() - - // since job is now started, set to false - hasCurrentJobCompleted = false - - // set the value of the job's progress - with(lifecycleScope) { - // collect the progress of the job - launch { - exportVectorTilesJob.progress.collect { - val progress = exportVectorTilesJob.progress.value - dialogLayoutBinding.progressBar.progress = progress - dialogLayoutBinding.progressTextView.text = "$progress% completed" - } - } - // display map if job succeeds - launch { - exportVectorTilesJob.result().onSuccess { - // display the map preview using the result from the completed job - showMapPreview(it) - // set job is completed - hasCurrentJobCompleted = true - // display the path of the saved vector tiles - showMessage(it.vectorTileCache?.path.toString()) - // dismiss loading dialog - dialog.dismiss() - }.onFailure { - showMessage(it.message.toString()) - dialog.dismiss() - hasCurrentJobCompleted = true - } - } - - } - } - - /** - * Updates the [downloadArea]'s geometry when called with viewpoint change - * or when export tiles button is clicked. - */ - private fun updateDownloadAreaGeometry() { - // upper left corner of the downloaded tile cache area - val minScreenPoint = ScreenCoordinate(150.0, 175.0) - // lower right corner of the downloaded tile cache area - val maxScreenPoint = ScreenCoordinate( - mapView.width - 150.0, - mapView.height - 250.0 - ) - // convert screen points to map points - val minPoint = mapView.screenToLocation(minScreenPoint) - val maxPoint = mapView.screenToLocation(maxScreenPoint) - if (minPoint != null && maxPoint != null) { - // use the points to define and return an envelope - downloadArea.geometry = Envelope(minPoint, maxPoint) - } else { - showMessage("Error getting screen coordinate") - } - } - - /** - * Create a progress dialog to track the progress of the [exportVectorTilesJob] - */ - private fun createProgressDialog(exportVectorTilesJob: ExportVectorTilesJob): MaterialAlertDialogBuilder { - return MaterialAlertDialogBuilder(this@MainActivity).apply { - setTitle("Exporting vector tiles") - setNegativeButton("Cancel job") { _, _ -> - lifecycleScope.launch { - // cancels the export job asynchronously - exportVectorTilesJob.cancel().getOrElse { - showMessage(it.message.toString()) - } - // cancel is completed, so set to true - hasCurrentJobCompleted = true - } - } - // removes parent of the progressDialog layout, if previously assigned - dialogLayoutBinding.root.parent?.let { parent -> - (parent as ViewGroup).removeAllViews() - } - setCancelable(false) - setView(dialogLayoutBinding.root) - } - } - - /** - * Display the preview of the exported map using the - * [vectorTilesResult] from the completed job - */ - private fun showMapPreview(vectorTilesResult: ExportVectorTilesResult) { - val vectorTileCache = vectorTilesResult.vectorTileCache - if (vectorTileCache == null) { - showMessage("Cannot find tile cache") - return - } - // get the layer exported for the preview MapView - val vectorTiledLayer = ArcGISVectorTiledLayer( - vectorTileCache, - vectorTilesResult.itemResourceCache - ) - - // control UI visibility - previewMapVisibility(true) - - // set up the preview MapView - previewMapView.apply { - map = ArcGISMap(Basemap(vectorTiledLayer)) - mapView.getCurrentViewpoint(ViewpointType.CenterAndScale)?.let { setViewpoint(it) } - } - closePreviewButton.setOnClickListener { - previewMapVisibility(false) - } - - } - - /** - * Controls the visibility of the preview map and the export buttons. - */ - private fun previewMapVisibility(isVisible: Boolean) = if (isVisible) { - exportVectorTilesButton.visibility = View.INVISIBLE - closePreviewButton.visibility = View.VISIBLE - previewMapView.visibility = View.VISIBLE - } else { - exportVectorTilesButton.visibility = View.VISIBLE - closePreviewButton.visibility = View.INVISIBLE - previewMapView.visibility = View.GONE - } - - private fun showMessage(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/download-vector-tiles-to-local-cache/src/main/res/drawable-v24/ic_launcher_foreground.xml b/download-vector-tiles-to-local-cache/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/download-vector-tiles-to-local-cache/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/download-vector-tiles-to-local-cache/src/main/res/drawable/ic_launcher_background.xml b/download-vector-tiles-to-local-cache/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/download-vector-tiles-to-local-cache/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/download-vector-tiles-to-local-cache/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/download-vector-tiles-to-local-cache/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/download-vector-tiles-to-local-cache/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/download-vector-tiles-to-local-cache/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-hdpi/ic_launcher.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-hdpi/ic_launcher_round.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-mdpi/ic_launcher.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-mdpi/ic_launcher_round.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xhdpi/ic_launcher.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxhdpi/ic_launcher.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/download-vector-tiles-to-local-cache/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/download-vector-tiles-to-local-cache/src/main/res/values/strings.xml b/download-vector-tiles-to-local-cache/src/main/res/values/strings.xml deleted file mode 100644 index 4848bd0b7..000000000 --- a/download-vector-tiles-to-local-cache/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Download vector tiles to local cache - Download Vector Tiles - Close vector tile preview - diff --git a/edit-and-sync-features-with-feature-service/.gitignore b/edit-and-sync-features-with-feature-service/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/edit-and-sync-features-with-feature-service/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/edit-and-sync-features-with-feature-service/build.gradle.kts b/edit-and-sync-features-with-feature-service/build.gradle.kts deleted file mode 100644 index 6a9979dee..000000000 --- a/edit-and-sync-features-with-feature-service/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.editandsyncfeatureswithfeatureservice" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.editandsyncfeatureswithfeatureservice" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/edit-and-sync-features-with-feature-service/proguard-rules.pro b/edit-and-sync-features-with-feature-service/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/edit-and-sync-features-with-feature-service/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/edit-and-sync-features-with-feature-service/src/main/AndroidManifest.xml b/edit-and-sync-features-with-feature-service/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/edit-and-sync-features-with-feature-service/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/edit-and-sync-features-with-feature-service/src/main/java/com/esri/arcgismaps/sample/editandsyncfeatureswithfeatureservice/MainActivity.kt b/edit-and-sync-features-with-feature-service/src/main/java/com/esri/arcgismaps/sample/editandsyncfeatureswithfeatureservice/MainActivity.kt deleted file mode 100644 index a04ce5c32..000000000 --- a/edit-and-sync-features-with-feature-service/src/main/java/com/esri/arcgismaps/sample/editandsyncfeatureswithfeatureservice/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.editandsyncfeatureswithfeatureservice - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.editandsyncfeatureswithfeatureservice.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - SampleApp() - } - } - } - - @Composable - private fun SampleApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/edit-and-sync-features-with-feature-service/src/main/res/drawable-v24/ic_launcher_foreground.xml b/edit-and-sync-features-with-feature-service/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/edit-and-sync-features-with-feature-service/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/edit-and-sync-features-with-feature-service/src/main/res/drawable/ic_launcher_background.xml b/edit-and-sync-features-with-feature-service/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/edit-and-sync-features-with-feature-service/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-hdpi/ic_launcher.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-hdpi/ic_launcher_round.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-mdpi/ic_launcher.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-mdpi/ic_launcher_round.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xhdpi/ic_launcher.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/edit-and-sync-features-with-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-and-sync-features-with-feature-service/src/main/res/values/strings.xml b/edit-and-sync-features-with-feature-service/src/main/res/values/strings.xml deleted file mode 100644 index ba00bfe78..000000000 --- a/edit-and-sync-features-with-feature-service/src/main/res/values/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - Edit and Sync Features with Feature Service - https://sampleserver6.arcgisonline.com/arcgis/rest/services/Sync/WildfireSync/FeatureServer - Generate Geodatabase - Sync Geodatabase - wildfire_gdb.geodatabase - diff --git a/edit-feature-attachments/.gitignore b/edit-feature-attachments/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/edit-feature-attachments/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/edit-feature-attachments/build.gradle.kts b/edit-feature-attachments/build.gradle.kts deleted file mode 100644 index 2656a685f..000000000 --- a/edit-feature-attachments/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.editfeatureattachments" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.editfeatureattachments" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.android.material) - implementation(libs.androidx.appcompat) - implementation(libs.androidx.constraintlayout) - implementation(project(":samples-lib")) -} diff --git a/edit-feature-attachments/proguard-rules.pro b/edit-feature-attachments/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/edit-feature-attachments/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/edit-feature-attachments/src/main/AndroidManifest.xml b/edit-feature-attachments/src/main/AndroidManifest.xml deleted file mode 100644 index c192b9230..000000000 --- a/edit-feature-attachments/src/main/AndroidManifest.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/edit-feature-attachments/src/main/java/com/esri/arcgismaps/sample/editfeatureattachments/MainActivity.kt b/edit-feature-attachments/src/main/java/com/esri/arcgismaps/sample/editfeatureattachments/MainActivity.kt deleted file mode 100644 index 416ba0798..000000000 --- a/edit-feature-attachments/src/main/java/com/esri/arcgismaps/sample/editfeatureattachments/MainActivity.kt +++ /dev/null @@ -1,341 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.editfeatureattachments - -import android.content.Intent -import android.graphics.Bitmap -import android.graphics.BitmapFactory -import android.graphics.drawable.BitmapDrawable -import android.net.Uri -import android.os.Bundle -import android.provider.MediaStore -import android.util.Log -import android.view.ViewGroup -import androidx.activity.result.contract.ActivityResultContracts -import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.FileProvider -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.data.ArcGISFeature -import com.arcgismaps.data.Attachment -import com.arcgismaps.data.FeatureRequestMode -import com.arcgismaps.data.ServiceFeatureTable -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.GeoElement -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.layers.FeatureLayer -import com.arcgismaps.mapping.view.IdentifyLayerResult -import com.esri.arcgismaps.sample.editfeatureattachments.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.editfeatureattachments.databinding.AttachmentEditSheetBinding -import com.esri.arcgismaps.sample.editfeatureattachments.databinding.AttachmentLoadingDialogBinding -import com.google.android.material.bottomsheet.BottomSheetDialog -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File -import java.io.FileOutputStream - -class MainActivity : AppCompatActivity() { - - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val attachmentsSheetBinding by lazy { - AttachmentEditSheetBinding.inflate(layoutInflater) - } - - private val loadingDialogBinding by lazy { - AttachmentLoadingDialogBinding.inflate(layoutInflater) - } - - // load the Damage to Residential Buildings feature server - private val serviceFeatureTable by lazy { - ServiceFeatureTable(getString(R.string.sample_service_url)).apply { - // set the feature request mode to request from the server as they are needed - featureRequestMode = FeatureRequestMode.OnInteractionCache - } - } - - // registers the activity for an image data result from the default image picker - private val activityResultLauncher = - registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - result.data?.data?.let { imageUri -> - // add the image data as a feature attachment - addFeatureAttachment(imageUri) - } - } - - // tracks the selected ArcGISFeature and it's attachments - private var selectedArcGISFeature: ArcGISFeature? = null - - // tracks the instance of the bottom sheet - private var bottomSheet: BottomSheetDialog? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // create the feature layer using the service feature table - val featureLayer = FeatureLayer.createWithFeatureTable(serviceFeatureTable) - - // create and add a map with a streets basemap style - val streetsMap = ArcGISMap(BasemapStyle.ArcGISStreets).apply { - operationalLayers.add(featureLayer) - } - // set the map and the viewpoint to the MapView - mapView.apply { - map = streetsMap - setViewpoint(Viewpoint(40.0, -95.0, 1e8)) - } - - // identify feature selected on map tap - lifecycleScope.launch { - mapView.onSingleTapConfirmed.collect { tapConfirmedEvent -> - // clear any previous selection - featureLayer.clearSelection() - // identify tapped feature - val layerResult = mapView.identifyLayer( - layer = featureLayer, - screenCoordinate = tapConfirmedEvent.screenCoordinate, - tolerance = 5.0, - returnPopupsOnly = false, - maximumResults = 1 - ).getOrElse { exception -> - showError("Failed to select feature: ${exception.message}") - } as IdentifyLayerResult - - // get a list of identified elements - val resultGeoElements: List = layerResult.geoElements - // check if a feature was identified - if (resultGeoElements.isNotEmpty() && resultGeoElements.first() is ArcGISFeature) { - // retrieve and set the currently selected feature - val selectedFeature = resultGeoElements.first() as ArcGISFeature - // highlight the currently selected feature - featureLayer.selectFeature(selectedFeature) - - // show the bottom sheet layout - createBottomSheet(selectedFeature) - - // keep track of the selected feature - selectedArcGISFeature = selectedFeature - } - } - } - } - - /** - * Creates and displays a bottom sheet to display and modify - * the attachments of [selectedFeature]. Calls [AttachmentsBottomSheet] to - * inflate bottom sheet and listen for interactions. - */ - private suspend fun createBottomSheet(selectedFeature: ArcGISFeature) { - // get the number of attachments - val attachmentList = selectedFeature.fetchAttachments().getOrElse { - return showError(it.message.toString()) - } - // get the attribute "typdamage" of the selected feature - val damageTypeAttribute = selectedFeature.attributes["typdamage"].toString() - - // creates a new BottomSheetDialog - bottomSheet = AttachmentsBottomSheet( - context = this@MainActivity, - bottomSheetBinding = attachmentsSheetBinding, - attachments = attachmentList, - damageType = damageTypeAttribute - ) - // set the content view to the root of the binding layout - bottomSheet?.setContentView(attachmentsSheetBinding.root) - // display the bottom sheet view - bottomSheet?.show() - } - - /** - * Retrieves the [attachment] data in the form of a byte array, converts it - * to a [BitmapDrawable], caches the bitmap as a png image, and open's the - * attachment image in the default image viewer. - */ - suspend fun fetchAttachment(attachment: Attachment) { - // display loading dialog - val dialog = createLoadingDialog("Fetching attachment data").show() - - // create folder /ArcGIS/Attachments in external storage - val fileDir = File(getExternalFilesDir(null)?.path + "/Attachments") - fileDir.mkdirs() - // create the file with the attachment name - val file = File(fileDir, attachment.name) - - // file provider URI - val contentUri = FileProvider.getUriForFile( - this, getString(R.string.provider_authority), file - ) - // open the file in gallery - val imageIntent = Intent().apply { - flags = Intent.FLAG_GRANT_READ_URI_PERMISSION - action = Intent.ACTION_VIEW - setDataAndType(contentUri, "image/png") - } - - // fetch the attachment data - attachment.fetchData().onSuccess { - // create a drawable from InputStream, then create the Bitmap - val bitmapDrawable = BitmapDrawable( - resources, - BitmapFactory.decodeByteArray(it, 0, it.size) - ) - // create a file output stream using the attachment file - FileOutputStream(file).use { imageOutputStream -> - // compress the bitmap to PNG format - bitmapDrawable.bitmap.compress(Bitmap.CompressFormat.PNG, 90, imageOutputStream) - // start activity using created intent - startActivity(imageIntent) - // dismiss dialog - dialog.dismiss() - } - }.onFailure { - // dismiss dialog - dialog.dismiss() - showError(it.message.toString()) - } - } - - /** - * Adds a new attachment to the [selectedArcGISFeature] using the [selectedImageUri] - * and updates the changes with the feature service table - */ - private fun addFeatureAttachment(selectedImageUri: Uri) { - // display a loading dialog - val dialog = createLoadingDialog("Adding feature attachment").show() - - // create an input stream at the selected URI - contentResolver.openInputStream(selectedImageUri)?.use { imageInputStream -> - // get the byte array of the image input stream - val imageBytes: ByteArray = imageInputStream.readBytes() - // create the attachment name with the current time - val attachmentName = "attachment_${System.currentTimeMillis()}.png" - - lifecycleScope.launch { - selectedArcGISFeature?.let { arcGISFeature -> - // add the attachment to the selected feature - arcGISFeature.addAttachment( - name = attachmentName, - contentType = "image/png", - data = imageBytes - ).onFailure { - return@launch showError(it.message.toString()) - } - // update the feature changes in the loaded service feature table - serviceFeatureTable.updateFeature(arcGISFeature).getOrElse { - return@launch showError(it.message.toString()) - } - } - applyServerEdits(dialog) - } - } - } - - /** - * Delete the [attachment] from the [selectedArcGISFeature] and update the changes - * with the feature service table - */ - fun deleteAttachment(attachment: Attachment) { - lifecycleScope.launch { - val dialog = createLoadingDialog("Deleting feature attachment").show() - selectedArcGISFeature?.let { arcGISFeature -> - // delete the attachment from the selected feature - arcGISFeature.deleteAttachment(attachment).getOrElse { - return@launch showError(it.message.toString()) - } - // update the feature changes in the loaded service feature table - serviceFeatureTable.updateFeature(arcGISFeature).getOrElse { - return@launch showError(it.message.toString()) - } - } - // apply changes back to the server - applyServerEdits(dialog) - } - } - - /** - * Applies changes from a Service Feature Table to the server. - * The [dialog] will be dismissed when changes are applied. - */ - private suspend fun applyServerEdits(dialog: AlertDialog) { - // close the bottom sheet, as it will be created - // after service changes are made - bottomSheet?.dismiss() - - // apply edits to the server - val updatedServerResult = serviceFeatureTable.applyEdits() - updatedServerResult.onSuccess { edits -> - dialog.dismiss() - // check that the feature table was successfully updated - if (edits.isEmpty()) { - return showError(getString(R.string.failure_edit_results)) - } - // if the edits were made successfully, create the bottom sheet to display new changes. - selectedArcGISFeature?.let { createBottomSheet(it) } - }.onFailure { - showError(it.message.toString()) - dialog.dismiss() - } - } - - /** - * Opens the default Android image selector - */ - fun selectAttachment() { - val mediaIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) - activityResultLauncher.launch(mediaIntent) - } - - /** - * Creates a loading dialog with the [message] - */ - private fun createLoadingDialog(message: String): MaterialAlertDialogBuilder { - // build and return a new alert dialog - return MaterialAlertDialogBuilder(this).apply { - // set message - setMessage(message) - // allow it to be cancellable - setCancelable(false) - // removes parent of the progressDialog layout, if previously assigned - loadingDialogBinding.root.parent?.let { parent -> - (parent as ViewGroup).removeAllViews() - } - // set the loading dialog layout to this alert dialog - setView(loadingDialogBinding.root) - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/edit-feature-attachments/src/main/res/drawable-v24/ic_launcher_foreground.xml b/edit-feature-attachments/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/edit-feature-attachments/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/edit-feature-attachments/src/main/res/drawable/ic_launcher_background.xml b/edit-feature-attachments/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/edit-feature-attachments/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/edit-feature-attachments/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/edit-feature-attachments/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/edit-feature-attachments/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/edit-feature-attachments/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/edit-feature-attachments/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/edit-feature-attachments/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/edit-feature-attachments/src/main/res/mipmap-hdpi/ic_launcher.png b/edit-feature-attachments/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-hdpi/ic_launcher_round.png b/edit-feature-attachments/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-mdpi/ic_launcher.png b/edit-feature-attachments/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-mdpi/ic_launcher_round.png b/edit-feature-attachments/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-xhdpi/ic_launcher.png b/edit-feature-attachments/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/edit-feature-attachments/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-xxhdpi/ic_launcher.png b/edit-feature-attachments/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/edit-feature-attachments/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/edit-feature-attachments/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/edit-feature-attachments/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/edit-feature-attachments/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-feature-attachments/src/main/res/values/strings.xml b/edit-feature-attachments/src/main/res/values/strings.xml deleted file mode 100644 index 6e32b47c0..000000000 --- a/edit-feature-attachments/src/main/res/values/strings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - Edit feature attachments - - - Are you sure you want to delete the attachment? - Yes - No - Server did not return edit results - - - https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0 - attachment_click - Edit attachments - Done - Add attachment - com.esri.arcgismaps.sample.editfeatureattachments.provider - diff --git a/edit-features-using-feature-forms/.gitignore b/edit-features-using-feature-forms/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/edit-features-using-feature-forms/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/edit-features-using-feature-forms/README.md b/edit-features-using-feature-forms/README.md deleted file mode 100644 index 834bea7de..000000000 --- a/edit-features-using-feature-forms/README.md +++ /dev/null @@ -1,45 +0,0 @@ -# Edit features using feature forms - -Display and edit feature attributes using feature forms - -![Image of edit features using feature forms](edit-features-using-feature-forms.png) - -## Use case - -Feature forms help enhance the accuracy, efficiency, and user experience of attribute editing in your application. Forms can be authored as part of the WebMap using [Field Maps Designer](https://www.arcgis.com/apps/fieldmaps/) or using Web Map Viewer. This allows for a simplified user experience to edit feature attribute data on the web-map. - -## How to use the sample - -Tap a feature on the feature form map to open a bottom sheet displaying the list of form elements. Select through the list of elements to view the coded value field groups and edit elements to update the field values. Tap the submit icon to commit the changes on the web map. - -## How it works - -1. Add a feature form enabled web-map to the MapView using `PortalItem` URL and itemID. -2. When the map is tapped, perform an identity operation to check if the tapped location is an `ArcGISFeature` and the `FeatureLayer.featureFormDefinition` is not null, indicating the feature layer does have an associated feature form definition. -3. Create a `FeatureForm()` object using the identified `ArcGISFeature` and the `FeatureLayer.featureFormDefinition`. -4. On the screen within a bottom sheet, use the `FeatureForm` Toolkit component to display the feature form configuration by providing the created `featureForm` object. -5. Optionally, you can add a `validationErrorVisibility` option to the `FeatureForm` Toolkit component that determines the behavior of when the validation errors are visible. -6. Once edits are added to the form fields, check to verify that there are no validation errors using `featureForm.validationErrors`. The list will be empty if there are no errors. -7. To commit edits on the service geodatabase: - 1. Call `featureForm.finishEditing()` to save edits to the database. - 2. Retrieve the backing service feature table's geodatabase using `(featureForm.feature.featureTable as? ServiceFeatureTable)?.serviceGeodatabase`. - 3. Verify the service geodatabase can commit changes back to the service using `serviceGeodatabase.serviceInfo?.canUseServiceGeodatabaseApplyEdits` - 4. If apply edits are allowed, call `serviceGeodatabase.applyEdits()` to apply local edits to the online service. - 5. If edits are not allowed on the `ServiceGeodatabase`, then apply edits to the `ServiceFeatureTable` using `(featureForm.feature.featureTable as? ServiceFeatureTable)?.applyEdits()` - -## Relevant API - -* ArcGISFeature -* FeatureForm -* FeatureLayer -* FieldFormElement -* GroupFormElement -* ServiceFeatureTable - -## Additional information - -This sample uses the FeatureForm and GeoViewCompose Toolkit modules to be able to implement a Composable MapView which displays a Composable FeatureForm UI. - -## Tags - -compose, edits, feature, featureforms, form, geoviewcompose, jetpack, toolkit diff --git a/edit-features-using-feature-forms/build.gradle.kts b/edit-features-using-feature-forms/build.gradle.kts deleted file mode 100644 index aa8e957b2..000000000 --- a/edit-features-using-feature-forms/build.gradle.kts +++ /dev/null @@ -1,55 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.editfeaturesusingfeatureforms" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.editfeaturesusingfeatureforms" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) - implementation(libs.arcgis.maps.kotlin.toolkit.featureforms) -} diff --git a/edit-features-using-feature-forms/proguard-rules.pro b/edit-features-using-feature-forms/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/edit-features-using-feature-forms/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/edit-features-using-feature-forms/src/main/AndroidManifest.xml b/edit-features-using-feature-forms/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/edit-features-using-feature-forms/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/edit-features-using-feature-forms/src/main/java/com/esri/arcgismaps/sample/editfeaturesusingfeatureforms/components/MapViewModel.kt b/edit-features-using-feature-forms/src/main/java/com/esri/arcgismaps/sample/editfeaturesusingfeatureforms/components/MapViewModel.kt deleted file mode 100644 index ec7638add..000000000 --- a/edit-features-using-feature-forms/src/main/java/com/esri/arcgismaps/sample/editfeaturesusingfeatureforms/components/MapViewModel.kt +++ /dev/null @@ -1,239 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.editfeaturesusingfeatureforms.components - -import android.app.Application -import androidx.compose.ui.unit.dp -import androidx.lifecycle.AndroidViewModel -import androidx.lifecycle.viewModelScope -import com.arcgismaps.data.ArcGISFeature -import com.arcgismaps.data.ServiceFeatureTable -import com.arcgismaps.exceptions.FeatureFormValidationException -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.PortalItem -import com.arcgismaps.mapping.featureforms.FeatureForm -import com.arcgismaps.mapping.featureforms.FeatureFormDefinition -import com.arcgismaps.mapping.featureforms.FieldFormElement -import com.arcgismaps.mapping.featureforms.FormElement -import com.arcgismaps.mapping.featureforms.GroupFormElement -import com.arcgismaps.mapping.layers.FeatureLayer -import com.arcgismaps.mapping.view.SingleTapConfirmedEvent -import com.arcgismaps.toolkit.geoviewcompose.MapViewProxy -import com.esri.arcgismaps.sample.editfeaturesusingfeatureforms.R -import com.esri.arcgismaps.sample.sampleslib.components.MessageDialogViewModel -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.launch - -/** - * A view model for the MainScreen UI - */ -class MapViewModel(application: Application) : AndroidViewModel(application) { - - val mapViewProxy = MapViewProxy() - - // feature forms enabled web-map showcasing places of interest with form fields - private var portalItem = PortalItem(application.getString(R.string.feature_form_web_map)) - - val map = ArcGISMap(portalItem) - - // keep track of the selected feature form - private val _featureForm = MutableStateFlow(null) - val featureForm: StateFlow = _featureForm.asStateFlow() - - // keep track of the list of validation errors - private val _errors = MutableStateFlow>(listOf()) - val errors: StateFlow> = _errors.asStateFlow() - - // create a ViewModel to handle dialog interactions - val messageDialogVM: MessageDialogViewModel = MessageDialogViewModel() - - init { - viewModelScope.launch { - // load a map that has a FeatureFormDefinition on any of its layers - map.load() - } - } - - /** - * Apply attribute edits to the Geodatabase backing the ServiceFeatureTable - * and refresh the local feature. Persisting changes to attributes is - * not part of the FeatureForm API. - * - * @param onEditsCompleted Invoked when edits are applied successfully - */ - fun applyEdits(onEditsCompleted: () -> Unit) { - val featureForm = _featureForm.value - ?: return messageDialogVM.showMessageDialog("Feature form state is not configured") - - // update the state flow with the list of validation errors found - _errors.value = validateFormInputEdits(featureForm) - // if there are no errors then update the feature - if (_errors.value.isEmpty()) { - val serviceFeatureTable = featureForm.feature.featureTable as? ServiceFeatureTable - ?: return messageDialogVM.showMessageDialog("Cannot save feature edit without a ServiceFeatureTable") - - viewModelScope.launch { - // commits changes of the edited feature to the database - featureForm.finishEditing().onSuccess { - serviceFeatureTable.serviceGeodatabase?.let { database -> - if (database.serviceInfo?.canUseServiceGeodatabaseApplyEdits == true) { - // applies all local edits in the tables to the service - database.applyEdits().onFailure { - return@onFailure messageDialogVM.showMessageDialog( - title = it.message.toString(), - description = it.cause.toString() - ) - } - } else { - // uploads any changes to the local table to the feature service - serviceFeatureTable.applyEdits().onFailure { - return@onFailure messageDialogVM.showMessageDialog( - title = it.message.toString(), - description = it.cause.toString() - ) - } - } - } - // resets the attributes and geometry to the values in the data source - featureForm.feature.refresh() - // unselect the feature after the edits have been saved - (featureForm.feature.featureTable?.layer as FeatureLayer).clearSelection() - // dismiss dialog when edits are completed - onEditsCompleted() - }.onFailure { - return@onFailure messageDialogVM.showMessageDialog( - title = it.message.toString(), - description = it.cause.toString() - ) - } - } - } - } - - /** - * Performs validation checks on the given [featureForm] with local edits. - * Return a list of [ErrorInfo] if errors are found, if not, empty list is returned. - */ - private fun validateFormInputEdits(featureForm: FeatureForm): List { - val errors = mutableListOf() - // If an element is editable or derives its value from an arcade expression, - // its errors must be corrected before submitting the form - featureForm.validationErrors.value.forEach { entry -> - entry.value.forEach { error -> - featureForm.elements.getFormElement(entry.key)?.let { formElement -> - if (formElement.isEditable.value || formElement.hasValueExpression) { - errors.add( - ErrorInfo( - fieldName = formElement.label, - error = error as FeatureFormValidationException - ) - ) - } - } - } - } - return errors - } - - /** - * Cancels the commit by resetting the validation errors. - */ - fun cancelCommit() { - // reset the validation errors - _errors.value = listOf() - } - - /** - * Discard edits and unselects feature from the layer - */ - fun rollbackEdits() { - // discard local edits to the feature form - _featureForm.value?.discardEdits() - // unselect the feature - (_featureForm.value?.feature?.featureTable?.layer as FeatureLayer).clearSelection() - // reset the validation errors - _errors.value = listOf() - } - - /** - * Perform an identify the tapped [ArcGISFeature] and retrieve the - * layer's [FeatureFormDefinition] to create the respective [FeatureForm] - */ - fun onSingleTapConfirmed(singleTapEvent: SingleTapConfirmedEvent) { - viewModelScope.launch { - mapViewProxy.identifyLayers( - screenCoordinate = singleTapEvent.screenCoordinate, - tolerance = 22.dp, - returnPopupsOnly = false - ).onSuccess { results -> - try { - results.forEach { result -> - result.geoElements.firstOrNull { - it is ArcGISFeature && (it.featureTable?.layer as? FeatureLayer)?.featureFormDefinition != null - }?.let { - val feature = it as ArcGISFeature - val layer = feature.featureTable!!.layer as FeatureLayer - val featureForm = FeatureForm(feature, layer.featureFormDefinition!!) - // select the feature - layer.selectFeature(feature) - // set the UI to an editing state with the FeatureForm - _featureForm.value = featureForm - } - } - } catch (e: Exception) { - messageDialogVM.showMessageDialog( - title = "Failed to create feature form for the feature", - description = e.message.toString() - ) - } - } - } - } -} - -/** - * Returns the [FieldFormElement] with the given [fieldName] in the [FeatureForm]. If none exists - * null is returned. - */ -fun List.getFormElement(fieldName: String): FieldFormElement? { - val fieldElements = filterIsInstance() - val element = if (fieldElements.isNotEmpty()) { - fieldElements.firstNotNullOfOrNull { - if (it.fieldName == fieldName) it else null - } - } else { - null - } - - return element ?: run { - val groupElements = filterIsInstance() - if (groupElements.isNotEmpty()) { - groupElements.firstNotNullOfOrNull { - it.elements.getFormElement(fieldName) - } - } else { - null - } - } -} - -/** - * Class that provides a validation error [error] for the field with name [fieldName]. - */ -data class ErrorInfo(val fieldName: String, val error: FeatureFormValidationException) diff --git a/edit-features-using-feature-forms/src/main/java/com/esri/arcgismaps/sample/editfeaturesusingfeatureforms/screens/MainScreen.kt b/edit-features-using-feature-forms/src/main/java/com/esri/arcgismaps/sample/editfeaturesusingfeatureforms/screens/MainScreen.kt deleted file mode 100644 index e2b815c40..000000000 --- a/edit-features-using-feature-forms/src/main/java/com/esri/arcgismaps/sample/editfeaturesusingfeatureforms/screens/MainScreen.kt +++ /dev/null @@ -1,354 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.editfeaturesusingfeatureforms.screens - -import android.content.res.Configuration -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.heightIn -import androidx.compose.foundation.layout.ime -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.wrapContentSize -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Check -import androidx.compose.material.icons.filled.Close -import androidx.compose.material3.AlertDialog -import androidx.compose.material3.Button -import androidx.compose.material3.Card -import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import com.arcgismaps.toolkit.featureforms.FeatureForm -import com.arcgismaps.toolkit.featureforms.ValidationErrorVisibility -import com.arcgismaps.toolkit.featureforms.theme.FeatureFormDefaults -import com.arcgismaps.toolkit.geoviewcompose.MapView -import com.esri.arcgismaps.sample.editfeaturesusingfeatureforms.R -import com.esri.arcgismaps.sample.editfeaturesusingfeatureforms.components.ErrorInfo -import com.esri.arcgismaps.sample.editfeaturesusingfeatureforms.components.MapViewModel -import com.esri.arcgismaps.sample.sampleslib.components.MessageDialog -import com.esri.arcgismaps.sample.sampleslib.components.SampleTopAppBar -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import kotlinx.coroutines.launch - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun MainScreen(mapViewModel: MapViewModel) { - - val scope = rememberCoroutineScope() - var showBottomSheet by remember { mutableStateOf(false) } - val sheetState = rememberModalBottomSheetState() - - // the feature form the currently selected feature - val featureForm by mapViewModel.featureForm.collectAsState() - // the validation errors found when the edits are applied - val formValidationErrors by mapViewModel.errors.collectAsState() - - // boolean trackers for save and discard edits dialogs - var showSaveEditsDialog by remember { mutableStateOf(false) } - var showDiscardEditsDialog by remember { mutableStateOf(false) } - - Scaffold( - modifier = Modifier.fillMaxSize(), - topBar = { SampleTopAppBar(title = stringResource(R.string.app_name)) } - ) { padding -> - // display the composable map using the mapViewModel - MapView( - arcGISMap = mapViewModel.map, - mapViewProxy = mapViewModel.mapViewProxy, - modifier = Modifier - .padding(padding) - .fillMaxSize(), - onSingleTapConfirmed = { mapViewModel.onSingleTapConfirmed(it) } - ) - - // update bottom sheet visibility when a feature is selected - LaunchedEffect(featureForm) { - showBottomSheet = featureForm != null - } - - if (showBottomSheet && featureForm != null) { - // display feature form bottom sheet - ModalBottomSheet( - onDismissRequest = { - showBottomSheet = false - showDiscardEditsDialog = true - }, - sheetState = sheetState - ) { - // top bar to manage save or discard edits - TopFormBar( - onClose = { showDiscardEditsDialog = true }, - onSave = { - showSaveEditsDialog = true - mapViewModel.applyEdits { - scope.launch { - sheetState.hide() - showBottomSheet = false - showSaveEditsDialog = false - } - } - }) - // display the selected feature form using the Toolkit component - FeatureForm( - featureForm = featureForm!!, - modifier = Modifier - .fillMaxSize() - .padding(top = 20.dp) - .navigationBarsPadding(), - validationErrorVisibility = ValidationErrorVisibility.Automatic, - colorScheme = FeatureFormDefaults.colorScheme( - groupElementColors = FeatureFormDefaults.groupElementColors( - outlineColor = MaterialTheme.colorScheme.secondary, - labelColor = MaterialTheme.colorScheme.onSurface, - supportingTextColor = MaterialTheme.colorScheme.onSurfaceVariant, - containerColor = MaterialTheme.colorScheme.surfaceContainer - ) - ), - typography = FeatureFormDefaults.typography( - readOnlyFieldTypography = FeatureFormDefaults.readOnlyFieldTypography( - labelStyle = MaterialTheme.typography.headlineSmall, - textStyle = MaterialTheme.typography.bodyMedium, - supportingTextStyle = MaterialTheme.typography.labelLarge - ) - ) - ) - } - } - } - - if (showSaveEditsDialog && formValidationErrors.isNotEmpty() && showBottomSheet) { - // validation errors found, cancel the commit and show validation errors - ValidationErrorsDialog(errors = formValidationErrors) { - showSaveEditsDialog = false - mapViewModel.cancelCommit() - } - } else if (showSaveEditsDialog && showBottomSheet) { - // no validation errors found, show dialog when commiting edits - SaveFormDialog() - } - - if (showDiscardEditsDialog) { - DiscardEditsDialog( - onConfirm = { - mapViewModel.rollbackEdits() - scope.launch { - sheetState.hide() - showDiscardEditsDialog = false - showBottomSheet = false - } - }, - onCancel = { - showDiscardEditsDialog = false - showBottomSheet = true - } - ) - } - - // Display a MessageDialog with any error information - mapViewModel.messageDialogVM.apply { - if (dialogStatus) { - MessageDialog( - title = messageTitle, - description = messageDescription, - onDismissRequest = ::dismissDialog - ) - } - } -} - -@Composable -fun DiscardEditsDialog(onConfirm: () -> Unit, onCancel: () -> Unit) { - AlertDialog( - onDismissRequest = onCancel, - confirmButton = { - Button(onClick = onConfirm) { - Text(text = stringResource(R.string.discard)) - } - }, - dismissButton = { - OutlinedButton(onClick = onCancel) { - Text(text = stringResource(R.string.cancel)) - } - }, - title = { - Text(text = stringResource(R.string.discard_edits)) - }, - text = { - Text(text = stringResource(R.string.all_changes_will_be_lost)) - } - ) -} - -@Composable -fun TopFormBar( - onClose: () -> Unit = {}, - onSave: () -> Unit = {}, -) { - Column { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 12.dp), - horizontalArrangement = Arrangement.Absolute.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - IconButton(onClick = onClose) { - Icon( - imageVector = Icons.Default.Close, - contentDescription = "Close Feature Editor" - ) - } - Text( - text = "Edit feature", - style = MaterialTheme.typography.titleMedium, - textAlign = TextAlign.Center - ) - IconButton(onClick = onSave) { - Icon( - imageVector = Icons.Default.Check, - contentDescription = "Save Feature", - tint = MaterialTheme.colorScheme.primary - ) - } - } - HorizontalDivider() - } -} - -@Composable -private fun SaveFormDialog() { - // show a progress dialog when no errors are present - Dialog(onDismissRequest = { /* cannot be dismissed */ }) { - Card(modifier = Modifier.wrapContentSize()) { - Column( - modifier = Modifier.padding(25.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - ) { - CircularProgressIndicator() - Spacer(modifier = Modifier.height(10.dp)) - Text(text = "Saving..") - } - } - } -} - -@Composable -private fun ValidationErrorsDialog(errors: List, onDismissRequest: () -> Unit) { - // show all the validation errors in a dialog - AlertDialog( - onDismissRequest = onDismissRequest, - modifier = Modifier.heightIn(max = 600.dp), - confirmButton = { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center - ) { - Button(onClick = onDismissRequest) { - Text(text = stringResource(R.string.view)) - } - } - }, - title = { - Column { - Text( - modifier = Modifier.fillMaxWidth(), - text = "Form Validation Errors", - style = MaterialTheme.typography.titleLarge, - textAlign = TextAlign.Center - ) - } - }, - text = { - Card(modifier = Modifier.fillMaxWidth()) { - Column(modifier = Modifier.padding(15.dp)) { - Text( - text = stringResource(R.string.attributes_failed, errors.count()), - color = MaterialTheme.colorScheme.error - ) - Spacer(modifier = Modifier.height(10.dp)) - LazyColumn(verticalArrangement = Arrangement.spacedBy(10.dp)) { - items(errors.count()) { index -> - Text( - text = "${errors[index].fieldName}: ${errors[index].error::class.simpleName.toString()}", - color = MaterialTheme.colorScheme.error - ) - } - } - } - } - } - ) -} - -@Preview -@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) -@Composable -fun SavePreview() { - SampleAppTheme { SaveFormDialog() } -} - -@Preview(showBackground = true) -@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) -@Composable -fun ValidationErrorsPreview() { - SampleAppTheme { ValidationErrorsDialog(listOf()) { } } -} - -@Preview(showBackground = true) -@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) -@Composable -fun DiscardEditsDialogPreview() { - SampleAppTheme { DiscardEditsDialog(onConfirm = {}) {} } -} - -@Preview(showBackground = true) -@Composable -fun TopFormBarPreview() { - SampleAppTheme { TopFormBar() } -} diff --git a/edit-features-using-feature-forms/src/main/res/drawable-v24/ic_launcher_foreground.xml b/edit-features-using-feature-forms/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/edit-features-using-feature-forms/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/edit-features-using-feature-forms/src/main/res/drawable/ic_launcher_background.xml b/edit-features-using-feature-forms/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/edit-features-using-feature-forms/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/edit-features-using-feature-forms/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/edit-features-using-feature-forms/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/edit-features-using-feature-forms/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/edit-features-using-feature-forms/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-hdpi/ic_launcher.png b/edit-features-using-feature-forms/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-hdpi/ic_launcher_round.png b/edit-features-using-feature-forms/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-mdpi/ic_launcher.png b/edit-features-using-feature-forms/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-mdpi/ic_launcher_round.png b/edit-features-using-feature-forms/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-xhdpi/ic_launcher.png b/edit-features-using-feature-forms/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/edit-features-using-feature-forms/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-xxhdpi/ic_launcher.png b/edit-features-using-feature-forms/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/edit-features-using-feature-forms/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/edit-features-using-feature-forms/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/edit-features-using-feature-forms/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/edit-features-using-feature-forms/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/edit-features-using-feature-forms/src/main/res/values/strings.xml b/edit-features-using-feature-forms/src/main/res/values/strings.xml deleted file mode 100644 index 1fc3c8787..000000000 --- a/edit-features-using-feature-forms/src/main/res/values/strings.xml +++ /dev/null @@ -1,10 +0,0 @@ - - Edit features using feature forms - https://www.arcgis.com/home/item.html?id=516e4d6aeb4c495c87c41e11274c767f - Cancel - %1$s attributes failed - View - Discard - Discard Edits? - All changes made within the form will be lost. - diff --git a/find-address-with-reverse-geocode/.gitignore b/find-address-with-reverse-geocode/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/find-address-with-reverse-geocode/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/find-address-with-reverse-geocode/build.gradle.kts b/find-address-with-reverse-geocode/build.gradle.kts deleted file mode 100644 index 861468512..000000000 --- a/find-address-with-reverse-geocode/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.findaddresswithreversegeocode" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.findaddresswithreversegeocode" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.android.material) - implementation(libs.androidx.constraintlayout) - implementation(project(":samples-lib")) -} diff --git a/find-address-with-reverse-geocode/proguard-rules.pro b/find-address-with-reverse-geocode/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/find-address-with-reverse-geocode/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/find-address-with-reverse-geocode/src/main/AndroidManifest.xml b/find-address-with-reverse-geocode/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/find-address-with-reverse-geocode/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/find-address-with-reverse-geocode/src/main/java/com/esri/arcgismaps/sample/findaddresswithreversegeocode/MainActivity.kt b/find-address-with-reverse-geocode/src/main/java/com/esri/arcgismaps/sample/findaddresswithreversegeocode/MainActivity.kt deleted file mode 100644 index 0b5bf0930..000000000 --- a/find-address-with-reverse-geocode/src/main/java/com/esri/arcgismaps/sample/findaddresswithreversegeocode/MainActivity.kt +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.findaddresswithreversegeocode - -import android.graphics.drawable.BitmapDrawable -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContextCompat -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.symbology.PictureMarkerSymbol -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.tasks.geocode.LocatorTask -import com.esri.arcgismaps.sample.findaddresswithreversegeocode.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // service url to be provided to the LocatorTask (geocoder) - private val geocodeServer = - "https://geocode-api.arcgis.com/arcgis/rest/services/World/GeocodeServer" - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - // create a MapView using binding - private val mapView by lazy { - activityMainBinding.mapView - } - - // display the street of the tapped location - private val titleTV by lazy { - activityMainBinding.titleTV - } - - // display the metro area of the tapped location - private val descriptionTV by lazy { - activityMainBinding.descriptionTV - } - - // set the pin graphic for tapped location - private val pinSymbol by lazy { - createPinSymbol() - } - - // create a graphics overlay - private val graphicsOverlay = GraphicsOverlay() - - // locator task to provide geocoding services - private val locatorTask = LocatorTask(geocodeServer) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - mapView.apply { - // add a map with a imagery basemap style - map = ArcGISMap(BasemapStyle.ArcGISImagery) - // add a graphics overlay to the map for showing where the user tapped - graphicsOverlays.add(graphicsOverlay) - // set initial viewpoint - setViewpoint(Viewpoint(34.058, -117.195, 5e4)) - } - - lifecycleScope.launch { - // load geocode locator task - locatorTask.load().onSuccess { - // locator task loaded, look for geo view tapped - mapView.onSingleTapConfirmed.collect { event -> - event.mapPoint?.let { mapPoint -> geoViewTapped(mapPoint) } - } - }.onFailure { - showError(it.message.toString()) - } - } - } - - /** - * Displays a pin of the tapped location using [mapPoint] - * and finds address with reverse geocode - */ - private suspend fun geoViewTapped(mapPoint: Point) { - // create graphic for tapped point - val pinGraphic = Graphic(mapPoint, pinSymbol) - graphicsOverlay.graphics.apply { - // clear existing graphics - clear() - // add the pin graphic - add(pinGraphic) - } - // normalize the geometry - needed if the user crosses the international date line. - val normalizedPoint = GeometryEngine.normalizeCentralMeridian(mapPoint) as Point - // reverse geocode to get address - locatorTask.reverseGeocode(normalizedPoint).onSuccess { addresses -> - // get the first result - val address = addresses.firstOrNull() - if (address == null) { - showError("Could not find address at tapped point") - return@onSuccess - } - // use the street and region for the title - val title = address.attributes["Address"].toString() - // use the metro area for the description details - val description = "${address.attributes["City"]} " + - "${address.attributes["Region"]} " + - "${address.attributes["CountryCode"]}" - // set the strings to the text views - titleTV.text = title - descriptionTV.text = description - }.onFailure { - showError(it.message.toString()) - } - } - - /** - * Create a picture marker symbol to represent a pin at the tapped location - */ - private fun createPinSymbol(): PictureMarkerSymbol { - // get pin drawable - val pinDrawable = ContextCompat.getDrawable( - this, - R.drawable.baseline_location_pin_red_48 - ) - //add a graphic for the tapped point - val pinSymbol = PictureMarkerSymbol.createWithImage( - pinDrawable as BitmapDrawable - ) - pinSymbol.apply { - // resize the dimensions of the symbol - width = 50f - height = 50f - // the image is a pin so offset the image so that the pinpoint - // is on the point rather than the image's true center - leaderOffsetX = 30f - offsetY = 25f - } - return pinSymbol - } - - private fun showError(errorMessage: String) { - Log.e(localClassName, errorMessage) - Snackbar.make(mapView, errorMessage, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/find-address-with-reverse-geocode/src/main/res/drawable-v24/ic_launcher_foreground.xml b/find-address-with-reverse-geocode/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/find-address-with-reverse-geocode/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/find-address-with-reverse-geocode/src/main/res/drawable/ic_launcher_background.xml b/find-address-with-reverse-geocode/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/find-address-with-reverse-geocode/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/find-address-with-reverse-geocode/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-address-with-reverse-geocode/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/find-address-with-reverse-geocode/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-address-with-reverse-geocode/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-hdpi/ic_launcher.png b/find-address-with-reverse-geocode/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-hdpi/ic_launcher_round.png b/find-address-with-reverse-geocode/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-mdpi/ic_launcher.png b/find-address-with-reverse-geocode/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-mdpi/ic_launcher_round.png b/find-address-with-reverse-geocode/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-xhdpi/ic_launcher.png b/find-address-with-reverse-geocode/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/find-address-with-reverse-geocode/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-xxhdpi/ic_launcher.png b/find-address-with-reverse-geocode/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/find-address-with-reverse-geocode/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/find-address-with-reverse-geocode/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/find-address-with-reverse-geocode/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/find-address-with-reverse-geocode/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-address-with-reverse-geocode/src/main/res/values/strings.xml b/find-address-with-reverse-geocode/src/main/res/values/strings.xml deleted file mode 100644 index c3ef88ed3..000000000 --- a/find-address-with-reverse-geocode/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Find address with reverse geocode - Tap on map to find address - diff --git a/find-closest-facility-from-point/.gitignore b/find-closest-facility-from-point/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/find-closest-facility-from-point/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/find-closest-facility-from-point/build.gradle.kts b/find-closest-facility-from-point/build.gradle.kts deleted file mode 100644 index ca5d27c24..000000000 --- a/find-closest-facility-from-point/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.findclosestfacilityfrompoint" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.findclosestfacilityfrompoint" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/find-closest-facility-from-point/proguard-rules.pro b/find-closest-facility-from-point/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/find-closest-facility-from-point/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/find-closest-facility-from-point/src/main/AndroidManifest.xml b/find-closest-facility-from-point/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/find-closest-facility-from-point/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/find-closest-facility-from-point/src/main/java/com/esri/arcgismaps/sample/findclosestfacilityfrompoint/MainActivity.kt b/find-closest-facility-from-point/src/main/java/com/esri/arcgismaps/sample/findclosestfacilityfrompoint/MainActivity.kt deleted file mode 100644 index 1c92443c9..000000000 --- a/find-closest-facility-from-point/src/main/java/com/esri/arcgismaps/sample/findclosestfacilityfrompoint/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.findclosestfacilityfrompoint - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.findclosestfacilityfrompoint.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - SampleApp() - } - } - } - - @Composable - private fun SampleApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/find-closest-facility-from-point/src/main/res/drawable-v24/ic_launcher_foreground.xml b/find-closest-facility-from-point/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/find-closest-facility-from-point/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/find-closest-facility-from-point/src/main/res/drawable/ic_launcher_background.xml b/find-closest-facility-from-point/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/find-closest-facility-from-point/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-closest-facility-from-point/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/find-closest-facility-from-point/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-closest-facility-from-point/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-closest-facility-from-point/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/find-closest-facility-from-point/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-closest-facility-from-point/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-closest-facility-from-point/src/main/res/mipmap-hdpi/ic_launcher.png b/find-closest-facility-from-point/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-hdpi/ic_launcher_round.png b/find-closest-facility-from-point/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-mdpi/ic_launcher.png b/find-closest-facility-from-point/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-mdpi/ic_launcher_round.png b/find-closest-facility-from-point/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-xhdpi/ic_launcher.png b/find-closest-facility-from-point/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/find-closest-facility-from-point/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-xxhdpi/ic_launcher.png b/find-closest-facility-from-point/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/find-closest-facility-from-point/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/find-closest-facility-from-point/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/find-closest-facility-from-point/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/find-closest-facility-from-point/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-closest-facility-from-point/src/main/res/values/strings.xml b/find-closest-facility-from-point/src/main/res/values/strings.xml deleted file mode 100644 index aa5a437ed..000000000 --- a/find-closest-facility-from-point/src/main/res/values/strings.xml +++ /dev/null @@ -1,5 +0,0 @@ - - Find closest facility from point - https://sampleserver6.arcgisonline.com/arcgis/rest/services/NetworkAnalysis/SanDiego/NAServer/ClosestFacility - https://static.arcgis.com/images/Symbols/SafetyHealth/Hospital.png - diff --git a/find-nearest-vertex/.gitignore b/find-nearest-vertex/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/find-nearest-vertex/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/find-nearest-vertex/build.gradle.kts b/find-nearest-vertex/build.gradle.kts deleted file mode 100644 index f64dc37c1..000000000 --- a/find-nearest-vertex/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.findnearestvertex" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.findnearestvertex" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/find-nearest-vertex/proguard-rules.pro b/find-nearest-vertex/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/find-nearest-vertex/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/find-nearest-vertex/src/main/AndroidManifest.xml b/find-nearest-vertex/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/find-nearest-vertex/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/find-nearest-vertex/src/main/java/com/esri/arcgismaps/sample/findnearestvertex/MainActivity.kt b/find-nearest-vertex/src/main/java/com/esri/arcgismaps/sample/findnearestvertex/MainActivity.kt deleted file mode 100644 index ce139e643..000000000 --- a/find-nearest-vertex/src/main/java/com/esri/arcgismaps/sample/findnearestvertex/MainActivity.kt +++ /dev/null @@ -1,192 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.findnearestvertex - -import android.os.Bundle -import android.util.Log -import android.view.View -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.Polygon -import com.arcgismaps.geometry.PolygonBuilder -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.layers.FeatureLayer -import com.arcgismaps.mapping.symbology.SimpleFillSymbol -import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleMarkerSymbol -import com.arcgismaps.mapping.symbology.SimpleMarkerSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.portal.Portal -import com.arcgismaps.mapping.PortalItem -import com.esri.arcgismaps.sample.findnearestvertex.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val distanceLayout: ConstraintLayout by lazy { - activityMainBinding.distanceLayout - } - - private val vertexDistanceTextView: TextView by lazy { - activityMainBinding.vertexDistanceTextView - } - - private val coordinateDistanceTextView: TextView by lazy { - activityMainBinding.coordinateDistanceTextView - } - - // California zone 5 (ftUS) state plane coordinate system. - private val statePlaneCaliforniaZone5SpatialReference = SpatialReference(2229) - - // create graphics with symbols for tapped location, nearest coordinate, and nearest vertex - private val tappedLocationGraphic = - Graphic(symbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.X, Color.magenta, 15f)) - - // create graphic symbol of the nearest coordinate - private val nearestCoordinateGraphic = - Graphic(symbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Diamond, Color.red, 10f)) - - // create graphic symbol of the nearest vertex - private val nearestVertexGraphic = - Graphic(symbol = SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, Color.blue, 15f)) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // create a polygon geometry - val polygon = PolygonBuilder(statePlaneCaliforniaZone5SpatialReference) { - addPoint(Point(6627416.41469281, 1804532.53233782)) - addPoint(Point(6669147.89779046, 2479145.16609522)) - addPoint(Point(7265673.02678292, 2484254.50442408)) - addPoint(Point(7676192.55880379, 2001458.66365744)) - }.toGeometry() - // set up the outline and fill color of the polygon - val polygonOutlineSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.green, 2f) - val polygonFillSymbol = SimpleFillSymbol( - SimpleFillSymbolStyle.ForwardDiagonal, - Color.green, - polygonOutlineSymbol - ) - // create a polygon graphic - val polygonGraphic = Graphic(polygon, polygonFillSymbol) - // create a graphics overlay to show the polygon, tapped location, and nearest vertex/coordinate - val graphicsOverlay = GraphicsOverlay( - listOf( - polygonGraphic, - tappedLocationGraphic, - nearestCoordinateGraphic, - nearestVertexGraphic - ) - ) - - // create a map using the portal item - val map = ArcGISMap(statePlaneCaliforniaZone5SpatialReference) - val portal = Portal("https://arcgisruntime.maps.arcgis.com") - val portalItem = PortalItem(portal, "99fd67933e754a1181cc755146be21ca") - val usStatesGeneralizedLayer = FeatureLayer.createWithItemAndLayerId(portalItem, 0) - // and add the feature layer to the map's operational layers - map.operationalLayers.add(usStatesGeneralizedLayer) - // add the map to the map view - mapView.map = map - // add the graphics overlay to the map view - mapView.graphicsOverlays.add(graphicsOverlay) - lifecycleScope.launch { - // check if map has loaded - map.load().onSuccess { - // zoom to the polygon's extent - mapView.setViewpointGeometry(polygon.extent, 100.0) - // get point on map tapped - mapView.onSingleTapConfirmed.collect { event -> - // find nearest vertex on map tapped - event.mapPoint?.let { findNearestVertex(it, polygon) } - } - }.onFailure { - showError("Error loading map") - } - } - } - - /** - * Finds the nearest vertex from [mapPoint] from the [polygon] - */ - private fun findNearestVertex(mapPoint: Point, polygon: Polygon) { - // show where the user clicked - tappedLocationGraphic.geometry = mapPoint - // use the geometry engine to get the nearest vertex - val nearestVertexResult = - GeometryEngine.nearestVertex(polygon, mapPoint) - // set the nearest vertex graphic's geometry to the nearest vertex - nearestVertexGraphic.geometry = nearestVertexResult?.coordinate - // use the geometry engine to get the nearest coordinate - val nearestCoordinateResult = - GeometryEngine.nearestCoordinate(polygon, mapPoint) - // set the nearest coordinate graphic's geometry to the nearest coordinate - nearestCoordinateGraphic.geometry = nearestCoordinateResult?.coordinate - // show the distances to the nearest vertex and nearest coordinate - distanceLayout.visibility = View.VISIBLE - // convert distance to miles - val vertexDistance = ((nearestVertexResult?.distance)?.div(5280.0))?.toInt() - val coordinateDistance = ((nearestCoordinateResult?.distance)?.div(5280.0))?.toInt() - // set the distance to the text views - vertexDistanceTextView.text = getString(R.string.nearest_vertex, vertexDistance) - coordinateDistanceTextView.text = - getString(R.string.nearest_coordinate, coordinateDistance) - - } - - private val Color.Companion.blue: Color - get() { - return fromRgba(0, 0, 255, 255) - } - - private val Color.Companion.magenta: Color - get() { - return fromRgba(255, 0, 255, 255) - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/find-nearest-vertex/src/main/res/drawable-v24/ic_launcher_foreground.xml b/find-nearest-vertex/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/find-nearest-vertex/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/find-nearest-vertex/src/main/res/drawable/ic_launcher_background.xml b/find-nearest-vertex/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/find-nearest-vertex/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-nearest-vertex/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/find-nearest-vertex/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-nearest-vertex/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-nearest-vertex/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/find-nearest-vertex/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-nearest-vertex/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-nearest-vertex/src/main/res/mipmap-hdpi/ic_launcher.png b/find-nearest-vertex/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-hdpi/ic_launcher_round.png b/find-nearest-vertex/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-mdpi/ic_launcher.png b/find-nearest-vertex/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-mdpi/ic_launcher_round.png b/find-nearest-vertex/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-xhdpi/ic_launcher.png b/find-nearest-vertex/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/find-nearest-vertex/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-xxhdpi/ic_launcher.png b/find-nearest-vertex/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/find-nearest-vertex/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/find-nearest-vertex/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/find-nearest-vertex/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/find-nearest-vertex/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-nearest-vertex/src/main/res/values/strings.xml b/find-nearest-vertex/src/main/res/values/strings.xml deleted file mode 100644 index f2662bb43..000000000 --- a/find-nearest-vertex/src/main/res/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Find nearest vertex - Vertex distance: %1$d mi - "Coordinate distance: %1$d mi" - Tap on the map to find vertex - diff --git a/find-route-around-barriers/.gitignore b/find-route-around-barriers/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/find-route-around-barriers/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/find-route-around-barriers/build.gradle.kts b/find-route-around-barriers/build.gradle.kts deleted file mode 100644 index 9abbceb6d..000000000 --- a/find-route-around-barriers/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.findroutearoundbarriers" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.findroutearoundbarriers" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/find-route-around-barriers/proguard-rules.pro b/find-route-around-barriers/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/find-route-around-barriers/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/find-route-around-barriers/src/main/AndroidManifest.xml b/find-route-around-barriers/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/find-route-around-barriers/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/find-route-around-barriers/src/main/java/com/esri/arcgismaps/sample/findroutearoundbarriers/MainActivity.kt b/find-route-around-barriers/src/main/java/com/esri/arcgismaps/sample/findroutearoundbarriers/MainActivity.kt deleted file mode 100644 index 95c9bfaf9..000000000 --- a/find-route-around-barriers/src/main/java/com/esri/arcgismaps/sample/findroutearoundbarriers/MainActivity.kt +++ /dev/null @@ -1,462 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.findroutearoundbarriers - -import android.graphics.drawable.BitmapDrawable -import android.os.Bundle -import android.util.Log -import android.view.View -import android.view.ViewGroup -import android.widget.AdapterView -import android.widget.ArrayAdapter -import android.widget.ImageView -import android.widget.ListView -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.coordinatorlayout.widget.CoordinatorLayout -import androidx.core.content.ContextCompat -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.symbology.CompositeSymbol -import com.arcgismaps.mapping.symbology.HorizontalAlignment -import com.arcgismaps.mapping.symbology.PictureMarkerSymbol -import com.arcgismaps.mapping.symbology.SimpleFillSymbol -import com.arcgismaps.mapping.symbology.SimpleFillSymbolStyle -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.symbology.TextSymbol -import com.arcgismaps.mapping.symbology.VerticalAlignment -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.tasks.networkanalysis.DirectionManeuver -import com.arcgismaps.tasks.networkanalysis.PolygonBarrier -import com.arcgismaps.tasks.networkanalysis.RouteParameters -import com.arcgismaps.tasks.networkanalysis.RouteTask -import com.arcgismaps.tasks.networkanalysis.Stop -import com.esri.arcgismaps.sample.findroutearoundbarriers.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.findroutearoundbarriers.databinding.OptionsDialogBinding -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.button.MaterialButton -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - // show the options dialog - private val optionsDialogBinding by lazy { - OptionsDialogBinding.inflate(layoutInflater) - } - - // set up the dialog UI views - private val findBestSequenceSwitch by lazy { - optionsDialogBinding.findBestSequenceSwitch - } - private val firstStopSwitch by lazy { - optionsDialogBinding.firstStopSwitch - } - private val lastStopSwitch by lazy { - optionsDialogBinding.lastStopSwitch - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val mainContainer: ConstraintLayout by lazy { - activityMainBinding.mainContainer - } - - private val addStopsButton: MaterialButton by lazy { - activityMainBinding.addStopsButton - } - - private val addBarriersButton: MaterialButton by lazy { - activityMainBinding.addBarriersButton - } - - private val resetButton by lazy { - activityMainBinding.resetButton - } - - private val optionsButton by lazy { - activityMainBinding.optionsButton - } - - private val directionsButton by lazy { - activityMainBinding.directionsButton - } - - private val bottomSheet by lazy { - activityMainBinding.directionSheet.directionSheetLayout - } - - private val header: ConstraintLayout by lazy { - activityMainBinding.directionSheet.header - } - - private val imageView: ImageView by lazy { - activityMainBinding.directionSheet.imageView - } - - private val cancelTV: TextView by lazy { - activityMainBinding.directionSheet.cancelTv - } - - private val directionsLV: ListView by lazy { - activityMainBinding.directionSheet.directionsLV - } - - private val stopList by lazy { mutableListOf() } - - private val barriersList by lazy { mutableListOf() } - - private val directionsList by lazy { mutableListOf() } - - private val stopsOverlay by lazy { GraphicsOverlay() } - - private val barriersOverlay by lazy { GraphicsOverlay() } - - private val routeOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } - - private val barrierSymbol by lazy { - SimpleFillSymbol(SimpleFillSymbolStyle.DiagonalCross, Color.red, null) - } - - // create route task from San Diego service - private val routeTask by lazy { - RouteTask(getString(R.string.routing_service_url)) - } - - private var routeParameters: RouteParameters? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - // some parts of the API require an Android Context to properly interact with Android system - // features, such as LocationProvider and application resources - ArcGISEnvironment.applicationContext = applicationContext - lifecycle.addObserver(mapView) - - // create and add a map with a navigation night basemap style - mapView.apply { - map = ArcGISMap(BasemapStyle.ArcGISStreets) - setViewpoint(Viewpoint(32.7270, -117.1750, 40000.0)) - graphicsOverlays.addAll(listOf(stopsOverlay, barriersOverlay, routeOverlay)) - } - - // set an on touch listener on the map view - lifecycleScope.launch { - mapView.onSingleTapConfirmed.collect { event -> - // add stop or barriers graphics to overlay - event.mapPoint?.let { mapPoint -> addStopOrBarrier(mapPoint) } - resetButton.isEnabled = true - } - } - - // coroutine scope to use the default parameters for the route calculation - lifecycleScope.launch { - routeTask.load().onSuccess { - routeParameters = routeTask.createDefaultParameters().getOrThrow().apply { - returnStops = true - returnDirections = true - } - }.onFailure { - showError(it.message.toString()) - } - } - - // make a clear button to reset the stops and routes - resetButton.setOnClickListener { - // clear stops from route parameters and stops list - routeParameters?.clearStops() - stopList.clear() - // clear barriers from route parameters and barriers list - routeParameters?.clearPolygonBarriers() - barriersList.clear() - // clear the directions list - directionsList.clear() - // clear all graphics overlays - mapView.graphicsOverlays.forEach { it.graphics.clear() } - resetButton.isEnabled = false - } - - // display the options dialog having the route finding parameters - optionsButton.setOnClickListener { - displayOptionsDialog() - } - - // display the bottom sheet with directions when the button is clicked - directionsButton.setOnClickListener { - if (directionsList.isEmpty()) return@setOnClickListener showError("Add stops on map to find route") - setupBottomSheet(directionsList) - } - - // hide the bottom sheet and make the map view span the whole screen - bottomSheet.visibility = View.INVISIBLE - (mainContainer.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = 0 - } - - /** - * Create options dialog with the route finding parameters to reorder stops to find the optimized route - */ - private fun displayOptionsDialog() { - // removes parent of the progressDialog layout, if previously assigned - optionsDialogBinding.root.parent?.let { parent -> - (parent as ViewGroup).removeAllViews() - } - - // set up the dialog builder - MaterialAlertDialogBuilder(this).apply { - setView(optionsDialogBinding.root) - show() - } - - // set the best sequence toggle state - findBestSequenceSwitch.isChecked = routeParameters?.findBestSequence ?: false - - // solve route on each state change - findBestSequenceSwitch.setOnCheckedChangeListener { _, _ -> - // update route params if the switch is toggled - routeParameters?.findBestSequence = findBestSequenceSwitch.isChecked - createAndDisplayRoute() - - // if best sequence switch is enabled, then enable the options - if (findBestSequenceSwitch.isChecked) { - firstStopSwitch.isEnabled = true - lastStopSwitch.isEnabled = true - - } else { - firstStopSwitch.apply { - isChecked = false - isEnabled = false - } - lastStopSwitch.apply { - isChecked = false - isEnabled = false - } - } - } - firstStopSwitch.setOnCheckedChangeListener { _, _ -> - routeParameters?.preserveFirstStop = firstStopSwitch.isChecked - createAndDisplayRoute() - } - lastStopSwitch.setOnCheckedChangeListener { _, _ -> - routeParameters?.preserveLastStop = lastStopSwitch.isChecked - createAndDisplayRoute() - } - } - - /** - * Add a stop or a barrier at the selected [mapPoint] to the correct graphics - * overlay depending on which button is currently checked. - */ - private fun addStopOrBarrier(mapPoint: Point) { - if (addStopsButton.isChecked) { - // normalize the geometry - needed if the user crosses the international date line. - val normalizedPoint = GeometryEngine.normalizeCentralMeridian(mapPoint) as Point - // use the mapPoint to create a stop - val stop = Stop(Point(normalizedPoint.x, normalizedPoint.y, mapPoint.spatialReference)) - // add the new stop to the list of stops - stopList.add(stop) - // create a marker symbol and graphics, and add the graphics to the graphics overlay - stopsOverlay.graphics.add(Graphic(mapPoint, createStopSymbol(stopList.size))) - } else if (addBarriersButton.isChecked) { - // create a buffered polygon around the clicked point - val barrierBufferPolygon = GeometryEngine.bufferOrNull(mapPoint, 200.0) - ?: return showError("Error creating buffer polygon") - // create a polygon barrier for the routing task, and add it to the list of barriers - barriersList.add(PolygonBarrier(barrierBufferPolygon)) - barriersOverlay.graphics.add(Graphic(barrierBufferPolygon, barrierSymbol)) - } - // solve the route once the graphics are created - createAndDisplayRoute() - } - - /** - * Create route parameters and a route task from them. Display the route result geometry as a - * graphic and call showDirectionsInBottomSheet which shows directions in a list view. - */ - private fun createAndDisplayRoute() = lifecycleScope.launch { - - // clear the previous route from the graphics overlay, if it exists - routeOverlay.graphics.clear() - // clear the directions list from the directions list view, if they exist - directionsList.clear() - - val routeParameters = routeParameters ?: return@launch - - if (stopList.size <= 1) return@launch - - routeParameters.apply { - // add the existing stops and barriers to the route parameters - setStops(stopList) - setPolygonBarriers(barriersList) - } - - // solve the route task - val routeResults = routeParameters.let { routeTask.solveRoute(it) } - - routeResults.onSuccess { routeResult -> - // get the first solved route - val firstRoute = routeResult.routes[0] - - // create Graphic for route - val graphic = Graphic( - firstRoute.routeGeometry, - SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.black, 3f) - ) - routeOverlay.graphics.add(graphic) - // get the direction text for each maneuver and add them to the list to display - directionsList.addAll(firstRoute.directionManeuvers) - }.onFailure { - showError("No route solution. ${it.message}") - } - - } - - /** Creates a bottom sheet to display a list of direction maneuvers. - * [directions] a list of DirectionManeuver which represents the route - */ - private fun setupBottomSheet(directions: List) { - val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet).apply { - // expand the bottom sheet, and ensure it is displayed on the screen when collapsed - state = BottomSheetBehavior.STATE_EXPANDED - peekHeight = header.height - // animate the arrow when the bottom sheet slides - addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { - override fun onSlide(bottomSheet: View, slideOffset: Float) { - imageView.rotation = slideOffset * 180f - } - - override fun onStateChanged(bottomSheet: View, newState: Int) { - imageView.rotation = when (newState) { - BottomSheetBehavior.STATE_EXPANDED -> 180f - else -> imageView.rotation - } - } - }) - } - - bottomSheet.apply { - visibility = View.VISIBLE - // expand or collapse the bottom sheet when the header is clicked - header.setOnClickListener { - bottomSheetBehavior.state = when (bottomSheetBehavior.state) { - BottomSheetBehavior.STATE_COLLAPSED -> BottomSheetBehavior.STATE_EXPANDED - else -> BottomSheetBehavior.STATE_COLLAPSED - } - - } - // rotate the arrow so it starts off in the correct rotation - imageView.rotation = 180f - - directionsLV.apply { - // set the adapter for the list view - adapter = ArrayAdapter( - this@MainActivity, - android.R.layout.simple_list_item_1, - directions.map { it.directionText } - ) - - // when the user taps a maneuver, set the viewpoint to that portion of the route - onItemClickListener = - AdapterView.OnItemClickListener { _, _, position, _ -> - // remove any graphics that are not the original (blue) route graphic - if (routeOverlay.graphics.size > 1) { - routeOverlay.graphics.removeAt(routeOverlay.graphics.size - 1) - } - // set the viewpoint to the selected maneuver - val geometry = directionsList[position].geometry - geometry?.let { mapView.setViewpoint(Viewpoint(it.extent, 20.0)) } - // create a graphic with a symbol for the maneuver and add it to the graphics overlay - val selectedRouteSymbol = SimpleLineSymbol( - SimpleLineSymbolStyle.Solid, - Color.green, 3f - ) - routeOverlay.graphics.add(Graphic(geometry, selectedRouteSymbol)) - // collapse the bottom sheet - bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED - } - } - // hide the bottom sheet when cancel button is clicked - cancelTV.setOnClickListener { - bottomSheet.visibility = View.INVISIBLE - } - } - - } - - /** - * Create a composite symbol consisting of a pin graphic overlaid with a particular [stopNumber]. - * Returns a [CompositeSymbol] consisting of the pin graphic overlaid with the stop number - */ - private fun createStopSymbol(stopNumber: Int): CompositeSymbol { - // create black stop number TextSymbol - val stopNumberSymbol = TextSymbol( - stopNumber.toString(), - Color.black, - 12f, - HorizontalAlignment.Center, - VerticalAlignment.Bottom - ).apply { - offsetY = 4f - } - - // create a new picture marker from a pin drawable - val pinSymbol = PictureMarkerSymbol.createWithImage( - ContextCompat.getDrawable( - this, - R.drawable.pin_symbol - ) as BitmapDrawable - ).apply { - // set the scale of the symbol - width = 24f - height = 24f - // set in pin "drop" to be offset to the point on map - offsetY = 10f - } - - // create a composite symbol and add the picture marker symbol and text symbol - val compositeSymbol = CompositeSymbol() - compositeSymbol.symbols.addAll(listOf(pinSymbol, stopNumberSymbol)) - - return compositeSymbol - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/find-route-around-barriers/src/main/res/drawable-v24/ic_launcher_foreground.xml b/find-route-around-barriers/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/find-route-around-barriers/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/find-route-around-barriers/src/main/res/drawable/ic_launcher_background.xml b/find-route-around-barriers/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/find-route-around-barriers/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-route-around-barriers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/find-route-around-barriers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-route-around-barriers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-route-around-barriers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/find-route-around-barriers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-route-around-barriers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-route-around-barriers/src/main/res/mipmap-hdpi/ic_launcher.png b/find-route-around-barriers/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-hdpi/ic_launcher_round.png b/find-route-around-barriers/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-mdpi/ic_launcher.png b/find-route-around-barriers/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-mdpi/ic_launcher_round.png b/find-route-around-barriers/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-xhdpi/ic_launcher.png b/find-route-around-barriers/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/find-route-around-barriers/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-xxhdpi/ic_launcher.png b/find-route-around-barriers/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/find-route-around-barriers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/find-route-around-barriers/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/find-route-around-barriers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/find-route-around-barriers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-around-barriers/src/main/res/values/strings.xml b/find-route-around-barriers/src/main/res/values/strings.xml deleted file mode 100644 index f097deb73..000000000 --- a/find-route-around-barriers/src/main/res/values/strings.xml +++ /dev/null @@ -1,17 +0,0 @@ - - Find route around barriers - Reset - Stops - Barriers - Directions - Collapse - Cancel - Find the best sequence - Preserve last stop - Preserve first stop - https://sampleserver7.arcgisonline.com/server/rest/services/NetworkAnalysis/SanDiego/NAServer/Route - Reset button - Options button - Directions button - Collapse directions - diff --git a/find-route-in-transport-network/.gitignore b/find-route-in-transport-network/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/find-route-in-transport-network/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/find-route-in-transport-network/build.gradle.kts b/find-route-in-transport-network/build.gradle.kts deleted file mode 100644 index ebc955632..000000000 --- a/find-route-in-transport-network/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.findrouteintransportnetwork" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.findrouteintransportnetwork" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(libs.androidx.appcompat) - implementation(project(":samples-lib")) -} diff --git a/find-route-in-transport-network/proguard-rules.pro b/find-route-in-transport-network/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/find-route-in-transport-network/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/find-route-in-transport-network/src/main/AndroidManifest.xml b/find-route-in-transport-network/src/main/AndroidManifest.xml deleted file mode 100644 index 556b670d3..000000000 --- a/find-route-in-transport-network/src/main/AndroidManifest.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/find-route-in-transport-network/src/main/java/com/esri/arcgismaps/sample/findrouteintransportnetwork/DownloadActivity.kt b/find-route-in-transport-network/src/main/java/com/esri/arcgismaps/sample/findrouteintransportnetwork/DownloadActivity.kt deleted file mode 100644 index 3a6720693..000000000 --- a/find-route-in-transport-network/src/main/java/com/esri/arcgismaps/sample/findrouteintransportnetwork/DownloadActivity.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.esri.arcgismaps.sample.findrouteintransportnetwork - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - //A zip file containing an offline routing network and .tpkx basemap - "https://arcgisruntime.maps.arcgis.com/home/item.html?id=df193653ed39449195af0c9725701dca" - ) - - ) - } -} diff --git a/find-route-in-transport-network/src/main/java/com/esri/arcgismaps/sample/findrouteintransportnetwork/MainActivity.kt b/find-route-in-transport-network/src/main/java/com/esri/arcgismaps/sample/findrouteintransportnetwork/MainActivity.kt deleted file mode 100644 index a82f50e6d..000000000 --- a/find-route-in-transport-network/src/main/java/com/esri/arcgismaps/sample/findrouteintransportnetwork/MainActivity.kt +++ /dev/null @@ -1,316 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.findrouteintransportnetwork - -import android.graphics.drawable.BitmapDrawable -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.core.content.ContextCompat -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.Envelope -import com.arcgismaps.geometry.Geometry -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.Basemap -import com.arcgismaps.mapping.layers.ArcGISTiledLayer -import com.arcgismaps.mapping.layers.TileCache -import com.arcgismaps.mapping.symbology.CompositeSymbol -import com.arcgismaps.mapping.symbology.HorizontalAlignment -import com.arcgismaps.mapping.symbology.PictureMarkerSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.symbology.TextSymbol -import com.arcgismaps.mapping.symbology.VerticalAlignment -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.ScreenCoordinate -import com.arcgismaps.tasks.networkanalysis.RouteParameters -import com.arcgismaps.tasks.networkanalysis.RouteTask -import com.arcgismaps.tasks.networkanalysis.Stop -import com.esri.arcgismaps.sample.findrouteintransportnetwork.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File -import kotlin.math.roundToInt - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val toggleButtons by lazy { - activityMainBinding.toggleButtons - } - - private val clearButton by lazy { - activityMainBinding.clearButton - } - - private val distanceTimeTextView by lazy { - activityMainBinding.distanceTimeTextView - } - - private val stopsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } - private val routeOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } - - private val envelope = Envelope( - Point(-1.3045e7, 3.87e6, 0.0, SpatialReference.webMercator()), - Point(-1.3025e7, 3.84e6, 0.0, SpatialReference.webMercator()) - ) - - // create a route task to calculate routes - private var routeTask: RouteTask? = null - - private var routeParameters: RouteParameters? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - // some parts of the API require an Android Context to properly interact with Android system - // features, such as LocationProvider and application resources - ArcGISEnvironment.applicationContext = applicationContext - lifecycle.addObserver(mapView) - - // create a tile cache from the .tpkx file - val tileCache = TileCache(provisionPath + getString(R.string.tpkx_path)) - val tiledLayer = ArcGISTiledLayer(tileCache) - // make a basemap with the tiled layer and add it to the mapview as an ArcGISMap - mapView.map = ArcGISMap(Basemap(tiledLayer)) - - // add the graphics overlays to the map view - mapView.graphicsOverlays.addAll(listOf(routeOverlay, stopsOverlay)) - - // create a route task using the geodatabase file - val geodatabaseFile = File(provisionPath + getString(R.string.geodatabase_path)) - routeTask = RouteTask(geodatabaseFile.path, "Streets_ND") - - // load the route task - lifecycleScope.launch { - routeTask?.load()?.onFailure { - showError(it.message.toString()) - }?.onSuccess { - // use the default parameters for the route calculation - routeParameters = routeTask?.createDefaultParameters()?.getOrThrow() - } - } - - toggleButtons.addOnButtonCheckedListener { _, checkedId, isChecked -> - if (isChecked) { - when (checkedId) { - R.id.fastestButton -> { - // calculate fastest route - routeParameters?.travelMode = - routeTask?.getRouteTaskInfo()?.travelModes?.get(0) - - // update route based on selection - updateRoute() - } - R.id.shortestButton -> { - // calculate shortest route - routeParameters?.travelMode = - routeTask?.getRouteTaskInfo()?.travelModes?.get(1) - - // update route based on selection - updateRoute() - } - } - } - } - - // make a clear button to reset the stops and routes - clearButton.setOnClickListener { - stopsOverlay.graphics.clear() - routeOverlay.graphics.clear() - clearButton.isEnabled = false - distanceTimeTextView.text = getString(R.string.tap_on_map_to_create_a_transport_network) - } - - // set up the touch listeners on the map view - setUpMapView() - } - - /** - * Sets up the viewpoint and onSingleTapConfirmed for the mapView. - * For single taps, graphics will be selected. - * */ - private fun setUpMapView() { - with(lifecycleScope) { - // set the viewpoint of the MapView - launch { - mapView.setViewpointGeometry(envelope) - } - - // add graphic at the tapped coordinate - launch { - mapView.onSingleTapConfirmed.collect { tapEvent -> - val screenCoordinate = tapEvent.screenCoordinate - addOrSelectGraphic(screenCoordinate) - clearButton.isEnabled = true - } - } - } - } - - /** - * Updates the calculated route using the - * stops on the map by calling routeTask.solveRoute(). - * Creates a graphic to display the route. - * */ - private fun updateRoute() = lifecycleScope.launch { - // get a list of stops from the graphics currently on the graphics overlay. - val stops = stopsOverlay.graphics.map { - Stop(it.geometry as Point) - } - - // do not calculate a route if there is only one stop - if (stops.size <= 1) return@launch - - routeParameters?.setStops(stops) - - // solve the route - val results = routeParameters?.let { routeTask?.solveRoute(it) } - if (results != null) { - results.onFailure { - showError("No route solution. ${it.message}") - routeOverlay.graphics.clear() - }.onSuccess { routeResult -> - // get the first solved route result - val route = routeResult.routes[0] - - // create graphic for route - val graphic = Graphic( - route.routeGeometry, SimpleLineSymbol( - SimpleLineSymbolStyle.Solid, - Color.black, 3F - ) - ) - routeOverlay.graphics.clear() - routeOverlay.graphics.add(graphic) - - // set distance-time text - val travelTime = route.travelTime.roundToInt() - val travelDistance = "%.2f".format( - route.totalLength * 0.000621371192 // convert meters to miles and round 2 decimals - ) - distanceTimeTextView.text = String.format("$travelTime min ($travelDistance mi)") - } - } - } - - /** - * Selects a graphic if there is one at the - * provided [screenCoordinate] or, if there is - * none, creates a new graphic. - * */ - private suspend fun addOrSelectGraphic(screenCoordinate: ScreenCoordinate) { - // identify the selected graphic - val result = - mapView.identifyGraphicsOverlay(stopsOverlay, screenCoordinate, 10.0, false) - - result.onFailure { - showError(it.message.toString()) - }.onSuccess { identifyGraphicsOverlayResult -> - val graphics = identifyGraphicsOverlayResult.graphics - - // unselect everything - if (stopsOverlay.selectedGraphics.isNotEmpty()) { - stopsOverlay.unselectGraphics(stopsOverlay.selectedGraphics) - } - - // if the user tapped on something, select it - if (graphics.isNotEmpty()) { - val firstGraphic = graphics[0] - firstGraphic.isSelected = true - } else { // there is no graphic at this location - val locationPoint = mapView.screenToLocation(screenCoordinate) - // check if tapped location is within the envelope - if (GeometryEngine.within(locationPoint as Geometry, envelope)) - // make a new graphic at the tapped location - createStopSymbol(stopsOverlay.graphics.size + 1, locationPoint) - else - showError("Tapped location is outside the transport network") - } - } - } - - /** - * Creates a composite symbol to represent a numbered stop. - * The [stopNumber] is the ordinal number of this stop and the - * symbol will be placed at the [locationPoint]. - */ - private fun createStopSymbol(stopNumber: Int, locationPoint: Point?) { - // create a orange pin PictureMarkerSymbol - val pinSymbol = PictureMarkerSymbol.createWithImage( - ContextCompat.getDrawable( - this, - R.drawable.pin_symbol - ) as BitmapDrawable - ).apply { - // set the scale of the symbol - width = 24f - height = 24f - // set in pin "drop" to be offset to the point on map - offsetY = 10f - } - - // create black stop number TextSymbol - val stopNumberSymbol = TextSymbol( - stopNumber.toString(), - Color.black, - 12f, - HorizontalAlignment.Center, - VerticalAlignment.Bottom - ).apply { - offsetY = 4f - } - - // create a composite symbol and add the picture marker symbol and text symbol - val compositeSymbol = CompositeSymbol() - compositeSymbol.symbols.addAll(listOf(pinSymbol, stopNumberSymbol)) - - // create a graphic to add to the overlay and update the route - val graphic = Graphic(locationPoint, compositeSymbol) - stopsOverlay.graphics.add(graphic) - - updateRoute() - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/find-route-in-transport-network/src/main/res/drawable-v24/ic_launcher_foreground.xml b/find-route-in-transport-network/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/find-route-in-transport-network/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/find-route-in-transport-network/src/main/res/drawable/ic_launcher_background.xml b/find-route-in-transport-network/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/find-route-in-transport-network/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-route-in-transport-network/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/find-route-in-transport-network/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-route-in-transport-network/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-route-in-transport-network/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/find-route-in-transport-network/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-route-in-transport-network/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-route-in-transport-network/src/main/res/mipmap-hdpi/ic_launcher.png b/find-route-in-transport-network/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-hdpi/ic_launcher_round.png b/find-route-in-transport-network/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-mdpi/ic_launcher.png b/find-route-in-transport-network/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-mdpi/ic_launcher_round.png b/find-route-in-transport-network/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-xhdpi/ic_launcher.png b/find-route-in-transport-network/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/find-route-in-transport-network/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-xxhdpi/ic_launcher.png b/find-route-in-transport-network/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/find-route-in-transport-network/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/find-route-in-transport-network/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/find-route-in-transport-network/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/find-route-in-transport-network/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route-in-transport-network/src/main/res/values/strings.xml b/find-route-in-transport-network/src/main/res/values/strings.xml deleted file mode 100644 index ae71b2ed1..000000000 --- a/find-route-in-transport-network/src/main/res/values/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - Find route in transport network - /streetmap_SD.tpkx - /sandiego.geodatabase - Tap on map to create a transport network - Shortest - Fastest - Clear - diff --git a/find-route/.gitignore b/find-route/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/find-route/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/find-route/build.gradle.kts b/find-route/build.gradle.kts deleted file mode 100644 index 66701dce3..000000000 --- a/find-route/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.findroute" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.findroute" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.androidx.coordinatorlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/find-route/proguard-rules.pro b/find-route/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/find-route/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/find-route/src/main/AndroidManifest.xml b/find-route/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/find-route/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/find-route/src/main/java/com/esri/arcgismaps/sample/findroute/MainActivity.kt b/find-route/src/main/java/com/esri/arcgismaps/sample/findroute/MainActivity.kt deleted file mode 100644 index 56fcf38dc..000000000 --- a/find-route/src/main/java/com/esri/arcgismaps/sample/findroute/MainActivity.kt +++ /dev/null @@ -1,296 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.findroute - -import android.graphics.drawable.BitmapDrawable -import android.os.Bundle -import android.util.Log -import android.view.View -import android.widget.AdapterView -import android.widget.ArrayAdapter -import android.widget.ImageView -import android.widget.LinearLayout -import android.widget.ListView -import android.widget.ProgressBar -import androidx.appcompat.app.AppCompatActivity -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.coordinatorlayout.widget.CoordinatorLayout -import androidx.core.content.ContextCompat -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.symbology.PictureMarkerSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.MapView -import com.arcgismaps.tasks.networkanalysis.DirectionManeuver -import com.arcgismaps.tasks.networkanalysis.RouteResult -import com.arcgismaps.tasks.networkanalysis.RouteTask -import com.arcgismaps.tasks.networkanalysis.Stop -import com.esri.arcgismaps.sample.findroute.databinding.ActivityMainBinding -import com.google.android.material.bottomsheet.BottomSheetBehavior -import com.google.android.material.floatingactionbutton.FloatingActionButton -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val graphicsOverlay: GraphicsOverlay by lazy { GraphicsOverlay() } - - private val mapView: MapView by lazy { - activityMainBinding.mapView - } - - private val mainContainer: ConstraintLayout by lazy { - activityMainBinding.mainContainer - } - - private val mainProgressBar: ProgressBar by lazy { - activityMainBinding.mainProgressBar - } - - private val directionFab: FloatingActionButton by lazy { - activityMainBinding.directionFab - } - - private val bottomSheet: LinearLayout by lazy { - activityMainBinding.bottomSheet.bottomSheetLayout - } - - private val header: ConstraintLayout by lazy { - activityMainBinding.bottomSheet.header - } - - private val imageView: ImageView by lazy { - activityMainBinding.bottomSheet.imageView - } - - private val directionsListView: ListView by lazy { - activityMainBinding.bottomSheet.directionsListView - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(activityMainBinding.mapView) - - mapView.apply { - // set the map to a new map with the navigation base map - map = ArcGISMap(BasemapStyle.ArcGISNavigation) - // set initial viewpoint to San Diego - setViewpoint(Viewpoint(32.7157, -117.1611, 200000.0)) - mapView.graphicsOverlays.add(graphicsOverlay) - } - - // create the symbols for the route - setupSymbols() - - // hide the bottom sheet and make the map view span the whole screen - bottomSheet.visibility = View.INVISIBLE - (mainContainer.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = 0 - - // solve the route and display the bottom sheet when the FAB is clicked - directionFab.setOnClickListener { lifecycleScope.launch { solveRoute() } } - } - - /** - * Solves the route using a Route Task, populates the navigation drawer with the directions, - * and displays a graphic of the route on the map. - */ - private suspend fun solveRoute() { - // set the applicationContext as it is required with RouteTask - ArcGISEnvironment.applicationContext = applicationContext - // create a route task instance - val routeTask = - RouteTask( - "https://route-api.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World" - ) - - // show the progress bar - mainProgressBar.visibility = View.VISIBLE - routeTask.createDefaultParameters().onSuccess { routeParams -> - // create stops - val stops = listOf( - Stop(Point(-117.1508, 32.7411, SpatialReference.wgs84())), - Stop(Point(-117.1555, 32.7033, SpatialReference.wgs84())) - ) - - routeParams.apply { - setStops(stops) - // set return directions as true to return turn-by-turn directions in the route's directionManeuvers - returnDirections = true - } - - // solve the route - val routeResult = routeTask.solveRoute(routeParams).getOrElse { - showError(it.message.toString()) - } as RouteResult - val route = routeResult.routes[0] - // create a simple line symbol for the route - val routeSymbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.blue, 5f) - - // create a graphic for the route and add it to the graphics overlay - graphicsOverlay.graphics.add(Graphic(route.routeGeometry, routeSymbol)) - // get the list of direction maneuvers and display it - // NOTE: to get turn-by-turn directions the route parameters - // must have the isReturnDirections parameter set to true. - val directions = route.directionManeuvers - setupBottomSheet(directions) - - // when the route is solved, hide the FAB and the progress bar - directionFab.visibility = View.GONE - mainProgressBar.visibility = View.GONE - }.onFailure { - showError(it.message.toString()) - mainProgressBar.visibility = View.GONE - } - } - - /** Creates a bottom sheet to display a list of direction maneuvers. - * [directions] a list of DirectionManeuver which represents the route - */ - private fun setupBottomSheet(directions: List) { - // create a bottom sheet behavior from the bottom sheet view in the main layout - val bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet).apply { - // expand the bottom sheet, and ensure it is displayed on the screen when collapsed - state = BottomSheetBehavior.STATE_EXPANDED - peekHeight = header.height - // animate the arrow when the bottom sheet slides - addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { - override fun onSlide(bottomSheet: View, slideOffset: Float) { - imageView.rotation = slideOffset * 180f - } - - override fun onStateChanged(bottomSheet: View, newState: Int) { - imageView.rotation = when (newState) { - BottomSheetBehavior.STATE_EXPANDED -> 180f - else -> imageView.rotation - } - } - }) - } - - bottomSheet.apply { - visibility = View.VISIBLE - // expand or collapse the bottom sheet when the header is clicked - header.setOnClickListener { - bottomSheetBehavior.state = when (bottomSheetBehavior.state) { - BottomSheetBehavior.STATE_COLLAPSED -> BottomSheetBehavior.STATE_EXPANDED - else -> BottomSheetBehavior.STATE_COLLAPSED - } - } - // rotate the arrow so it starts off in the correct rotation - imageView.rotation = 180f - } - - directionsListView.apply { - // Set the adapter for the list view - adapter = ArrayAdapter( - this@MainActivity, - android.R.layout.simple_list_item_1, - directions.map { it.directionText } - ) - // when the user taps a maneuver, set the viewpoint to that portion of the route - onItemClickListener = - AdapterView.OnItemClickListener { _, _, position, _ -> - directions[position].geometry?.let { geometry -> - // set the viewpoint to the selected maneuver - mapView.setViewpoint( - Viewpoint(geometry.extent, 20.0) - ) - // create a graphic with a symbol for the maneuver and add it to the graphics overlay - val selectedRouteSymbol = SimpleLineSymbol( - SimpleLineSymbolStyle.Solid, - Color.green, 5f - ) - graphicsOverlay.graphics.add(Graphic(geometry, selectedRouteSymbol)) - // collapse the bottom sheet - bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED - } - } - } - - // shrink the map view so it is not hidden under the bottom sheet header - (mainContainer.layoutParams as CoordinatorLayout.LayoutParams).bottomMargin = - header.height - } - - /** - * Set up the source, destination and route symbols. - */ - private fun setupSymbols() { - val startDrawable = - ContextCompat.getDrawable(this, R.drawable.ic_source) as BitmapDrawable - val pinSourceSymbol = PictureMarkerSymbol.createWithImage(startDrawable).apply { - // make the graphic smaller - width = 30f - height = 30f - offsetY = 20f - } - // create a point for the new graphic - val sourcePoint = Point( - -117.1508, 32.7411, SpatialReference.wgs84() - ) - // create a graphic and it to the graphics overlay - graphicsOverlay.graphics.add(Graphic(sourcePoint, pinSourceSymbol)) - - val endDrawable = - ContextCompat.getDrawable(this, R.drawable.ic_destination) as BitmapDrawable - - endDrawable.let { - val pinDestinationSymbol = - PictureMarkerSymbol.createWithImage(endDrawable).apply { - // make the graphic smaller - width = 30f - height = 30f - offsetY = 20f - } - // create a point for the new graphic - val destinationPoint = Point(-117.1555, 32.7033, SpatialReference.wgs84()) - // create a graphic and add it to the graphics overlay - graphicsOverlay.graphics.add(Graphic(destinationPoint, pinDestinationSymbol)) - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } - - private val Color.Companion.blue: Color - get() { - return fromRgba(0, 0, 255, 255) - } - -} diff --git a/find-route/src/main/res/drawable-v24/ic_launcher_foreground.xml b/find-route/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/find-route/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/find-route/src/main/res/drawable/ic_launcher_background.xml b/find-route/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/find-route/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/find-route/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/find-route/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-route/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-route/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/find-route/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/find-route/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/find-route/src/main/res/mipmap-hdpi/ic_launcher.png b/find-route/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/find-route/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-hdpi/ic_launcher_round.png b/find-route/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/find-route/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-mdpi/ic_launcher.png b/find-route/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/find-route/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-mdpi/ic_launcher_round.png b/find-route/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/find-route/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-xhdpi/ic_launcher.png b/find-route/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/find-route/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/find-route/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/find-route/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-xxhdpi/ic_launcher.png b/find-route/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/find-route/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/find-route/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/find-route/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/find-route/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/find-route/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/find-route/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/find-route/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/find-route/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/find-route/src/main/res/values/strings.xml b/find-route/src/main/res/values/strings.xml deleted file mode 100644 index 1a3d16fd8..000000000 --- a/find-route/src/main/res/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Find route - Directions - Collapse directions - Display Directions button - diff --git a/generate-geodatabase-replica-from-feature-service/.gitignore b/generate-geodatabase-replica-from-feature-service/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/generate-geodatabase-replica-from-feature-service/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/generate-geodatabase-replica-from-feature-service/build.gradle.kts b/generate-geodatabase-replica-from-feature-service/build.gradle.kts deleted file mode 100644 index 636a317e7..000000000 --- a/generate-geodatabase-replica-from-feature-service/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/generate-geodatabase-replica-from-feature-service/proguard-rules.pro b/generate-geodatabase-replica-from-feature-service/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/generate-geodatabase-replica-from-feature-service/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/generate-geodatabase-replica-from-feature-service/src/main/AndroidManifest.xml b/generate-geodatabase-replica-from-feature-service/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/generate-geodatabase-replica-from-feature-service/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/generate-geodatabase-replica-from-feature-service/src/main/java/com/esri/arcgismaps/sample/generategeodatabasereplicafromfeatureservice/MainActivity.kt b/generate-geodatabase-replica-from-feature-service/src/main/java/com/esri/arcgismaps/sample/generategeodatabasereplicafromfeatureservice/MainActivity.kt deleted file mode 100644 index af8178b2c..000000000 --- a/generate-geodatabase-replica-from-feature-service/src/main/java/com/esri/arcgismaps/sample/generategeodatabasereplicafromfeatureservice/MainActivity.kt +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice - -import android.os.Bundle -import android.util.Log -import android.view.ViewGroup -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.data.Geodatabase -import com.arcgismaps.data.ServiceFeatureTable -import com.arcgismaps.geometry.Envelope -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.layers.FeatureLayer -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.ScreenCoordinate -import com.arcgismaps.tasks.geodatabase.GenerateGeodatabaseJob -import com.arcgismaps.tasks.geodatabase.GeodatabaseSyncTask -import com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.generategeodatabasereplicafromfeatureservice.databinding.GenerateGeodatabaseDialogLayoutBinding -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - // setup data binding for the mapview - private val mapView by lazy { - activityMainBinding.mapView - } - - // starts the geodatabase replica process - private val generateButton by lazy { - activityMainBinding.generateButton - } - - private val resetButton by lazy { - activityMainBinding.resetButton - } - - // shows the geodatabase loading progress - private val progressDialog by lazy { - GenerateGeodatabaseDialogLayoutBinding.inflate(layoutInflater) - } - - // local file path to the geodatabase - private val geodatabaseFilePath by lazy { - getExternalFilesDir(null)?.path + getString(R.string.portland_trees_geodatabase_file) - } - - // keep track of the geodatabase replica generated by the feature service - private var geodatabase: Geodatabase? = null - - private val downloadArea: Graphic = Graphic() - - // create a Trees FeatureLayer using the first layer of the ServiceFeatureTable - private val featureLayer: FeatureLayer by lazy { - FeatureLayer.createWithFeatureTable( - featureTable = ServiceFeatureTable( - uri = application.getString(R.string.feature_server_url) + "/0" - ) - ) - } - - // creates a graphic overlay - private val graphicsOverlay: GraphicsOverlay = GraphicsOverlay() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // create and add a map with a Topographic basemap style - val map = ArcGISMap(BasemapStyle.ArcGISTopographic).apply { - operationalLayers.add(featureLayer) - } - // set the max map extents to that of the feature service - // representing portland area - map.maxExtent = Envelope( - -13687689.2185849, - 5687273.88331375, - -13622795.3756647, - 5727520.22085841, - spatialReference = SpatialReference.webMercator() - ) - // configure mapview assignments - mapView.apply { - this.map = map - // add the graphics overlay to display the boundary - graphicsOverlays.add(graphicsOverlay) - } - - // create a geodatabase sync task with the feature service url - // This feature service shows a web map of portland street trees, - // their attributes, as well as related inspection information - val geodatabaseSyncTask = GeodatabaseSyncTask(getString(R.string.feature_server_url)) - - // set the button's onClickListener - generateButton.setOnClickListener { - // start the geodatabase generation process - generateGeodatabase(geodatabaseSyncTask, map, downloadArea.geometry?.extent) - } - - resetButton.setOnClickListener { - // clear any layers already on the map - map.operationalLayers.clear() - // clear all symbols drawn - graphicsOverlay.graphics.clear() - // add the download boundary - graphicsOverlay.graphics.add(downloadArea) - // add back the feature layer - map.operationalLayers.add(featureLayer) - // close the current geodatabase, if a replica was already generated - geodatabase?.close() - // show generate button - generateButton.isEnabled = true - resetButton.isEnabled = false - } - - lifecycleScope.launch { - // show the error and return if map load failed - map.load().onFailure { - showError("Unable to load map") - return@launch - } - - geodatabaseSyncTask.load().onFailure { - // if the metadata load fails, show the error and return - showError("Failed to fetch geodatabase metadata") - return@launch - } - - // show download area once map is loaded - updateDownloadArea() - - // enable the generate button since the task is now loaded - generateButton.isEnabled = true - - // create a symbol to show a box around the extent we want to download - downloadArea.symbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.red, 2F) - // add the graphic to the graphics overlay when it is created - graphicsOverlay.graphics.add(downloadArea) - // update the download area on viewpoint change - mapView.viewpointChanged.collect { - updateDownloadArea() - } - } - } - - /** - * Displays a red border on the map to signify the [downloadArea] - */ - private fun updateDownloadArea() { - // define screen area to create replica - val minScreenPoint = ScreenCoordinate(200.0, 200.0) - val maxScreenPoint = ScreenCoordinate( - mapView.measuredWidth - 200.0, - mapView.measuredHeight - 200.0 - ) - // convert screen points to map points - val minPoint = mapView.screenToLocation(minScreenPoint) - val maxPoint = mapView.screenToLocation(maxScreenPoint) - // use the points to define and return an envelope - if (minPoint != null && maxPoint != null) { - val envelope = Envelope(minPoint, maxPoint) - downloadArea.geometry = envelope - } - } - - /** - * Starts a [geodatabaseSyncTask] with the given [map] and [extents], - * runs a GenerateGeodatabaseJob and saves the geodatabase file into local storage - */ - private fun generateGeodatabase( - geodatabaseSyncTask: GeodatabaseSyncTask, - map: ArcGISMap, - extents: Envelope? - ) { - if (extents == null) { - return showError("Download area extent is null") - } - - lifecycleScope.launch { - // create generate geodatabase parameters for the selected extents - val defaultParameters = - geodatabaseSyncTask.createDefaultGenerateGeodatabaseParameters(extents).getOrElse { - // show the error and return if the task fails - showError("Error creating geodatabase parameters") - return@launch - }.apply { - // set the parameters to only create a replica of the Trees (0) layer - layerOptions.removeIf { layerOptions -> - layerOptions.layerId != 0L - } - } - - // set return attachments option to false - // indicates if any attachments are added to the geodatabase from the feature service - defaultParameters.returnAttachments = false - // create a generate geodatabase job - geodatabaseSyncTask.createGenerateGeodatabaseJob(defaultParameters, geodatabaseFilePath) - .run { - // create a dialog to show the jobs progress - val materialDialogBuilder = createProgressDialog(this) - - // show the dialog and obtain a reference to it - val jobProgressDialog = materialDialogBuilder.show() - - // launch a progress collector to display progress - launch { - progress.collect { value -> - // update the progress bar and progress text - progressDialog.progressBar.progress = value - progressDialog.progressTextView.text = value.toString() - } - } - // start the generateGeodatabase job - start() - // if the job completed successfully, get the geodatabase from the result - val geodatabase = result().getOrElse { - // show an error and return if job failed - showError("Error fetching geodatabase: ${it.message}") - // dismiss the dialog - jobProgressDialog.dismiss() - return@launch - } - - // load and display the geodatabase - loadGeodatabase(geodatabase, map) - // dismiss the dialog view - jobProgressDialog.dismiss() - // unregister since we are not syncing - geodatabaseSyncTask.unregisterGeodatabase(geodatabase) - // show reset button as the task is now complete - generateButton.isEnabled = false - resetButton.isEnabled = true - } - } - } - - /** - * Loads the [replicaGeodatabase] and renders the feature layers on to the [map] - */ - private suspend fun loadGeodatabase(replicaGeodatabase: Geodatabase, map: ArcGISMap) { - // clear any layers already on the map - map.operationalLayers.clear() - // clear all symbols drawn - graphicsOverlay.graphics.clear() - - // load the geodatabase - replicaGeodatabase.load().onFailure { - // if the load failed, show the error and return - showError("Error loading geodatabase") - return - } - - // add all of the geodatabase feature tables to the map as feature layers - map.operationalLayers += replicaGeodatabase.featureTables.map { featureTable -> - FeatureLayer.createWithFeatureTable(featureTable) - } - - // keep track of the geodatabase to close it before generating a new replica - geodatabase = replicaGeodatabase - } - - /** - * Creates a new alert dialog using the progressDialog and provides - * GenerateGeodatabaseJob cancellation on dialog cancellation - * - * @param generateGeodatabaseJob the job to cancel - * - * @return returns an alert dialog - */ - private fun createProgressDialog(generateGeodatabaseJob: GenerateGeodatabaseJob): MaterialAlertDialogBuilder { - // build and return a new alert dialog - return MaterialAlertDialogBuilder(this).apply { - // setting it title - setTitle(getString(R.string.dialog_title)) - // allow it to be cancellable - setCancelable(false) - // sets negative button configuration - setNegativeButton("Cancel") { _, _ -> - // cancels the generateGeodatabaseJob - lifecycleScope.launch { - generateGeodatabaseJob.cancel() - } - } - // removes parent of the progressDialog layout, if previously assigned - progressDialog.root.parent?.let { parent -> - (parent as ViewGroup).removeAllViews() - } - // set the progressDialog Layout to this alert dialog - setView(progressDialog.root) - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/drawable-v24/ic_launcher_foreground.xml b/generate-geodatabase-replica-from-feature-service/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/generate-geodatabase-replica-from-feature-service/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/drawable/ic_launcher_background.xml b/generate-geodatabase-replica-from-feature-service/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/generate-geodatabase-replica-from-feature-service/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-hdpi/ic_launcher.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-hdpi/ic_launcher_round.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-mdpi/ic_launcher.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-mdpi/ic_launcher_round.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xhdpi/ic_launcher.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/generate-geodatabase-replica-from-feature-service/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-geodatabase-replica-from-feature-service/src/main/res/values/strings.xml b/generate-geodatabase-replica-from-feature-service/src/main/res/values/strings.xml deleted file mode 100644 index 6699c6345..000000000 --- a/generate-geodatabase-replica-from-feature-service/src/main/res/values/strings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - Generate geodatabase replica from feature service - https://services2.arcgis.com/ZQgQTuoyBrtmoGdP/arcgis/rest/services/Mobile_Data_Collection_WFL1/FeatureServer - Generate - Fetching result - /portland_trees_gdb.geodatabase - Reset map - diff --git a/generate-offline-map-using-android-jetpack-workmanager/.gitignore b/generate-offline-map-using-android-jetpack-workmanager/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/generate-offline-map-using-android-jetpack-workmanager/build.gradle.kts b/generate-offline-map-using-android-jetpack-workmanager/build.gradle.kts deleted file mode 100644 index 8a759e9a6..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/build.gradle.kts +++ /dev/null @@ -1,40 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.generateofflinemapusingandroidjetpackworkmanager" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.generateofflinemapusingandroidjetpackworkmanager" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) - implementation(libs.androidx.work.runtime.ktx) - implementation(libs.androidx.lifecycle.livedata.ktx) -} diff --git a/generate-offline-map-using-android-jetpack-workmanager/proguard-rules.pro b/generate-offline-map-using-android-jetpack-workmanager/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/AndroidManifest.xml b/generate-offline-map-using-android-jetpack-workmanager/src/main/AndroidManifest.xml deleted file mode 100644 index 58bd69d5e..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/src/main/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/java/com/esri/arcgismaps/sample/generateofflinemapusingandroidjetpackworkmanager/MainActivity.kt b/generate-offline-map-using-android-jetpack-workmanager/src/main/java/com/esri/arcgismaps/sample/generateofflinemapusingandroidjetpackworkmanager/MainActivity.kt deleted file mode 100644 index 4e66328db..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/src/main/java/com/esri/arcgismaps/sample/generateofflinemapusingandroidjetpackworkmanager/MainActivity.kt +++ /dev/null @@ -1,472 +0,0 @@ -/* - * Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.generateofflinemapusingandroidjetpackworkmanager - -import android.Manifest.permission.POST_NOTIFICATIONS -import android.content.pm.PackageManager -import android.os.Build -import android.os.Bundle -import android.util.Log -import android.view.ViewGroup -import androidx.appcompat.app.AppCompatActivity -import androidx.core.app.ActivityCompat -import androidx.core.content.ContextCompat -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.asFlow -import androidx.lifecycle.lifecycleScope -import androidx.work.ExistingWorkPolicy -import androidx.work.OneTimeWorkRequestBuilder -import androidx.work.OutOfQuotaPolicy -import androidx.work.WorkInfo -import androidx.work.WorkManager -import androidx.work.workDataOf -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.Envelope -import com.arcgismaps.geometry.Geometry -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.MobileMapPackage -import com.arcgismaps.mapping.PortalItem -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.ScreenCoordinate -import com.arcgismaps.portal.Portal -import com.arcgismaps.tasks.offlinemaptask.GenerateOfflineMapJob -import com.arcgismaps.tasks.offlinemaptask.GenerateOfflineMapParameters -import com.arcgismaps.tasks.offlinemaptask.OfflineMapTask -import com.esri.arcgismaps.sample.generateofflinemapusingandroidjetpackworkmanager.databinding.ActivityMainBinding -import com.esri.arcgismaps.sample.generateofflinemapusingandroidjetpackworkmanager.databinding.OfflineJobProgressDialogLayoutBinding -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File -import kotlin.random.Random - -// data parameter keys for the WorkManager -// key for the NotificationId parameter -const val notificationIdParameter = "NotificationId" - -// key for the json job file path -const val jobParameter = "JsonJobPath" - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val takeMapOfflineButton by lazy { - activityMainBinding.takeMapOfflineButton - } - - private val resetMapButton by lazy { - activityMainBinding.resetButton - } - - // instance of the WorkManager - private val workManager by lazy { - WorkManager.getInstance(this) - } - - // file path to store the offline map package - private val offlineMapPath by lazy { - getExternalFilesDir(null)?.path + getString(R.string.offlineMapFile) - } - - // shows the offline map job loading progress - private val progressLayout by lazy { - OfflineJobProgressDialogLayoutBinding.inflate(layoutInflater) - } - - // alert dialog view for the progress layout - private val progressDialog by lazy { - createProgressDialog().create() - } - - // used to uniquely identify the work request so that only one worker is active at a time - // also allows us to query and observe work progress - private val uniqueWorkName = "ArcgisMaps.Sample.OfflineMapJob.Worker" - - // create a graphic overlay - private val graphicsOverlay = GraphicsOverlay() - - // represents bounds of the downloadable area of the map - private val downloadArea = Graphic( - symbol = SimpleLineSymbol(SimpleLineSymbolStyle.Solid, Color.red, 2F) - ) - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // request notifications permission - requestNotificationPermission() - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // set up the portal item to take offline - setUpMapView() - - // clear the preview map and display the Portal Item - resetMapButton.setOnClickListener { - // enable offline button - takeMapOfflineButton.isEnabled = true - resetMapButton.isEnabled = false - // clear graphic overlays - graphicsOverlay.graphics.clear() - mapView.graphicsOverlays.clear() - - // set up the portal item to take offline - setUpMapView() - } - } - - /** - * Sets up a portal item and displays map area to take offline - */ - private fun setUpMapView() { - // create a portal item with the itemId of the web map - val portal = Portal(getString(R.string.portal_url)) - val portalItem = PortalItem(portal, getString(R.string.item_id)) - - // add the graphic to the graphics overlay when it is created - graphicsOverlay.graphics.add(downloadArea) - // create and add a map with with portal item - val map = ArcGISMap(portalItem) - // apply mapview assignments - mapView.apply { - this.map = map - graphicsOverlays.add(graphicsOverlay) - } - - lifecycleScope.launch { - map.load().onFailure { - // show an error and return if the map load failed - showMessage("Error loading map: ${it.message}") - return@launch - } - - // enable the take map offline button only after the map is loaded - takeMapOfflineButton.isEnabled = true - - // get the Control Valve layer from the map's operational layers - val operationalLayer = - map.operationalLayers.firstOrNull { layer -> - layer.name == "Control Valve" - } ?: return@launch showMessage("Error finding Control Valve layer") - - // limit the map scale to the layer's scale - map.maxScale = operationalLayer.maxScale ?: 0.0 - map.minScale = operationalLayer.minScale ?: 0.0 - - mapView.viewpointChanged.collect { - // upper left corner of the area to take offline - val minScreenPoint = ScreenCoordinate(200.0, 200.0) - // lower right corner of the downloaded area - val maxScreenPoint = ScreenCoordinate( - mapView.width - 200.0, - mapView.height - 200.0 - ) - // convert screen points to map points - val minPoint = mapView.screenToLocation(minScreenPoint) ?: return@collect - val maxPoint = mapView.screenToLocation(maxScreenPoint) ?: return@collect - // use the points to define and set an envelope for the downloadArea graphic - val envelope = Envelope(minPoint, maxPoint) - downloadArea.geometry = envelope - } - } - - // set onclick listener for the takeMapOfflineButton - takeMapOfflineButton.setOnClickListener { - // if the downloadArea's geometry is not null - downloadArea.geometry?.let { geometry -> - // create an OfflineMapJob - val offlineMapJob = createOfflineMapJob(map, geometry) - // start the OfflineMapJob - startOfflineMapJob(offlineMapJob) - // show the progress dialog - progressDialog.show() - // disable the button - takeMapOfflineButton.isEnabled = false - } - } - - // start observing the worker's progress and status - observeWorkStatus() - } - - /** - * Creates and returns a new GenerateOfflineMapJob for the [map] and its [areaOfInterest] - */ - private fun createOfflineMapJob( - map: ArcGISMap, - areaOfInterest: Geometry - ): GenerateOfflineMapJob { - // check and delete if the offline map package file already exists - File(offlineMapPath).deleteRecursively() - // specify the min scale and max scale as parameters - val maxScale = map.maxScale ?: 0.0 - var minScale = map.minScale ?: 0.0 - // minScale must always be larger than maxScale - if (minScale <= maxScale) { - minScale = maxScale + 1 - } - // set the offline map parameters - val generateOfflineMapParameters = GenerateOfflineMapParameters( - areaOfInterest, - minScale, - maxScale - ).apply { - // set job to cancel on any errors - continueOnErrors = false - } - // create an offline map task with the map - val offlineMapTask = OfflineMapTask(map) - // create an offline map job with the download directory path and parameters and - // return the job - return offlineMapTask.createGenerateOfflineMapJob( - generateOfflineMapParameters, - offlineMapPath - ) - } - - /** - * Starts the [offlineMapJob] using OfflineJobWorker with WorkManager. The [offlineMapJob] is - * serialized into a json file and the uri is passed to the OfflineJobWorker, since WorkManager - * enforces a MAX_DATA_BYTES for the WorkRequest's data - */ - private fun startOfflineMapJob(offlineMapJob: GenerateOfflineMapJob) { - // create a temporary file path to save the offlineMapJob json file - val offlineJobJsonPath = getExternalFilesDir(null)?.path + - getString(R.string.offlineJobJsonFile) - - // create the json file - val offlineJobJsonFile = File(offlineJobJsonPath) - // serialize the offlineMapJob into the file - offlineJobJsonFile.writeText(offlineMapJob.toJson()) - - // create a non-zero notification id for the OfflineJobWorker - // this id will be used to post or update any progress/status notifications - val notificationId = Random.Default.nextInt(1, 100) - - // create a one-time work request with an instance of OfflineJobWorker - val workRequest = OneTimeWorkRequestBuilder() - // run it as an expedited work - .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) - // add the input data - .setInputData( - // add the notificationId and the json file path as a key/value pair - workDataOf( - notificationIdParameter to notificationId, - jobParameter to offlineJobJsonFile.absolutePath - ) - ).build() - - // enqueue the work request to run as a unique work with the uniqueWorkName, so that - // only one instance of OfflineJobWorker is running at any time - // if any new work request with the uniqueWorkName is enqueued, it replaces any existing - // ones that are active - workManager.enqueueUniqueWork(uniqueWorkName, ExistingWorkPolicy.REPLACE, workRequest) - } - - /** - * Starts observing any running or completed OfflineJobWorker work requests by capturing the - * LiveData as a flow. The flow starts receiving updates when the activity is in started - * or resumed state. This allows the application to capture immediate progress when - * in foreground and latest progress when the app resumes or restarts. - */ - private fun observeWorkStatus() { - // get the livedata observer of the unique work as a flow - val liveDataFlow = workManager.getWorkInfosForUniqueWorkLiveData(uniqueWorkName).asFlow() - - lifecycleScope.launch { - // collect the live data flow to get the latest work info list - liveDataFlow.collect { workInfoList -> - if (workInfoList.isNotEmpty()) { - // fetch the first work info as we only ever run one work request at any time - val workInfo = workInfoList[0] - // check the current state of the work request - when (workInfo.state) { - // if work completed successfully - WorkInfo.State.SUCCEEDED -> { - // load and display the offline map - displayOfflineMap() - // dismiss the progress dialog - if (progressDialog.isShowing) { - progressDialog.dismiss() - } - } - // if the work failed or was cancelled - WorkInfo.State.FAILED, WorkInfo.State.CANCELLED -> { - // show an error message based on if it was cancelled or failed - if (workInfo.state == WorkInfo.State.FAILED) { - showMessage("Error generating offline map") - } else { - showMessage("Cancelled offline map generation") - } - // dismiss the progress dialog - if (progressDialog.isShowing) { - progressDialog.dismiss() - } - // enable the takeMapOfflineButton - takeMapOfflineButton.isEnabled = true - // this removes the completed WorkInfo from the WorkManager's database - // otherwise, the observer will emit the WorkInfo on every launch - // until WorkManager auto-prunes - workManager.pruneWork() - } - // if the work is currently in progress - WorkInfo.State.RUNNING -> { - // get the current progress value - val value = workInfo.progress.getInt("Progress", 0) - // update the progress bar and progress text - progressLayout.progressBar.progress = value - progressLayout.progressTextView.text = "$value%" - // shows the progress dialog if the app is relaunched and the - // dialog is not visible - if (!progressDialog.isShowing) { - progressDialog.show() - } - } - else -> { /* don't have to handle other states */ - } - } - } - } - } - } - - /** - * Loads the offline map package into the mapView - */ - private fun displayOfflineMap() { - lifecycleScope.launch { - // check if the offline map package file exists - if (File(offlineMapPath).exists()) { - // load it as a MobileMapPackage - val mapPackage = MobileMapPackage(offlineMapPath) - mapPackage.load().onFailure { - // if the load fails, show an error and return - showMessage("Error loading map package: ${it.message}") - return@launch - } - // add the map from the mobile map package to the MapView - mapView.map = mapPackage.maps.first() - // clear all the drawn graphics - graphicsOverlay.graphics.clear() - // disable the button to take the map offline once the offline map is showing - takeMapOfflineButton.isEnabled = false - resetMapButton.isEnabled = true - // this removes the completed WorkInfo from the WorkManager's database - // otherwise, the observer will emit the WorkInfo on every launch - // until WorkManager auto-prunes - workManager.pruneWork() - // display the offline map loaded message - showMessage("Loaded offline map. Map saved at: $offlineMapPath") - } else { - showMessage("Offline map does not exists at path: $offlineMapPath") - } - } - } - - /** - * Creates a progress dialog to show the OfflineMapJob worker progress. It cancels all the - * running workers when the dialog is cancelled - */ - private fun createProgressDialog(): MaterialAlertDialogBuilder { - // build and return a new alert dialog - return MaterialAlertDialogBuilder(this).apply { - // set it title - setTitle(getString(R.string.dialog_title)) - // allow it to be cancellable - setCancelable(false) - // set negative button configuration - setNegativeButton("Cancel") { _, _ -> - // cancel all the running work - workManager.cancelAllWork() - } - // removes parent of the progressDialog layout, if previously assigned - progressLayout.root.parent?.let { parent -> - (parent as ViewGroup).removeAllViews() - } - // set the progressDialog Layout to this alert dialog - setView(progressLayout.root) - } - } - - /** - * Request Post Notifications permission for API level 33+ - * https://developer.android.com/develop/ui/views/notifications/notification-permission - */ - private fun requestNotificationPermission() { - // request notification permission only for android versions >= 33 - if (Build.VERSION.SDK_INT >= 33) { - // check if push notifications permission is granted - val permissionCheckPostNotifications = - ContextCompat.checkSelfPermission(this@MainActivity, POST_NOTIFICATIONS) == - PackageManager.PERMISSION_GRANTED - - // if permission is not already granted, request permission from the user - if (!permissionCheckPostNotifications) { - ActivityCompat.requestPermissions( - this@MainActivity, - arrayOf(POST_NOTIFICATIONS), - 2 - ) - } - } - } - - /** - * Handle the permissions request response. - */ - override fun onRequestPermissionsResult( - requestCode: Int, - permissions: Array, - grantResults: IntArray - ) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_DENIED) { - Snackbar.make( - mapView, - "Notification permissions required to show progress!", - Snackbar.LENGTH_LONG - ).show() - } - } - - override fun onDestroy() { - super.onDestroy() - // dismiss the dialog when the activity is destroyed - progressDialog.dismiss() - } - - private fun showMessage(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/drawable-v24/ic_launcher_foreground.xml b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/drawable/ic_launcher_background.xml b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-hdpi/ic_launcher.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-hdpi/ic_launcher_round.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-mdpi/ic_launcher.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-mdpi/ic_launcher_round.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xhdpi/ic_launcher.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxhdpi/ic_launcher.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/values/strings.xml b/generate-offline-map-using-android-jetpack-workmanager/src/main/res/values/strings.xml deleted file mode 100644 index 03c1fd310..000000000 --- a/generate-offline-map-using-android-jetpack-workmanager/src/main/res/values/strings.xml +++ /dev/null @@ -1,14 +0,0 @@ - - Generate offline map using android jetpack workmanager - https://www.arcgis.com - acc027394bc84c2fb04d1ed317aac674 - Generating offline map.. - /offlineMap - /offlineJobJson - Offline Map Job Notifications - Shows notifications for offline map job progress - ArcGIS Maps Sample: Offline Map Download - NotificationAction - Take Map Offline - Reset Map - diff --git a/generate-offline-map/.gitignore b/generate-offline-map/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/generate-offline-map/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/generate-offline-map/build.gradle.kts b/generate-offline-map/build.gradle.kts deleted file mode 100644 index 14b01ecb9..000000000 --- a/generate-offline-map/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.generateofflinemap" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.generateofflinemap" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/generate-offline-map/proguard-rules.pro b/generate-offline-map/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/generate-offline-map/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/generate-offline-map/src/main/AndroidManifest.xml b/generate-offline-map/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/generate-offline-map/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/generate-offline-map/src/main/java/com/esri/arcgismaps/sample/generateofflinemap/MainActivity.kt b/generate-offline-map/src/main/java/com/esri/arcgismaps/sample/generateofflinemap/MainActivity.kt deleted file mode 100644 index 56e8d6bb0..000000000 --- a/generate-offline-map/src/main/java/com/esri/arcgismaps/sample/generateofflinemap/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2024 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.generateofflinemap - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.generateofflinemap.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - SampleApp() - } - } - } - - @Composable - private fun SampleApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/generate-offline-map/src/main/res/drawable-v24/ic_launcher_foreground.xml b/generate-offline-map/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/generate-offline-map/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/generate-offline-map/src/main/res/drawable/ic_launcher_background.xml b/generate-offline-map/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/generate-offline-map/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/generate-offline-map/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/generate-offline-map/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/generate-offline-map/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/generate-offline-map/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/generate-offline-map/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/generate-offline-map/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/generate-offline-map/src/main/res/mipmap-hdpi/ic_launcher.png b/generate-offline-map/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-hdpi/ic_launcher_round.png b/generate-offline-map/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-mdpi/ic_launcher.png b/generate-offline-map/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-mdpi/ic_launcher_round.png b/generate-offline-map/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-xhdpi/ic_launcher.png b/generate-offline-map/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/generate-offline-map/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-xxhdpi/ic_launcher.png b/generate-offline-map/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/generate-offline-map/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/generate-offline-map/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/generate-offline-map/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/generate-offline-map/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/generate-offline-map/src/main/res/values/strings.xml b/generate-offline-map/src/main/res/values/strings.xml deleted file mode 100644 index 282a115ca..000000000 --- a/generate-offline-map/src/main/res/values/strings.xml +++ /dev/null @@ -1,7 +0,0 @@ - - Generate offline map - https://www.arcgis.com - acc027394bc84c2fb04d1ed317aac674 - Take Map Offline - Reset Map - diff --git a/geocode-offline/.gitignore b/geocode-offline/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/geocode-offline/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/geocode-offline/build.gradle.kts b/geocode-offline/build.gradle.kts deleted file mode 100644 index e76341bff..000000000 --- a/geocode-offline/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.geocodeoffline" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.geocodeoffline" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(libs.androidx.appcompat) - implementation(project(":samples-lib")) -} diff --git a/geocode-offline/proguard-rules.pro b/geocode-offline/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/geocode-offline/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/geocode-offline/src/main/AndroidManifest.xml b/geocode-offline/src/main/AndroidManifest.xml deleted file mode 100644 index 8eaea2ef4..000000000 --- a/geocode-offline/src/main/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - diff --git a/geocode-offline/src/main/java/com/esri/arcgismaps/sample/geocodeoffline/DownloadActivity.kt b/geocode-offline/src/main/java/com/esri/arcgismaps/sample/geocodeoffline/DownloadActivity.kt deleted file mode 100644 index 16b0545df..000000000 --- a/geocode-offline/src/main/java/com/esri/arcgismaps/sample/geocodeoffline/DownloadActivity.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.esri.arcgismaps.sample.geocodeoffline - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // A .tpkx Tile Package file covering the San Diego, CA, USA area - "https://www.arcgis.com/home/item.html?id=22c3083d4fa74e3e9b25adfc9f8c0496", - // San Diego Locator Offline Dataset - "https://www.arcgis.com/home/item.html?id=3424d442ebe54f3cbf34462382d3aebe" - ) - ) - } -} diff --git a/geocode-offline/src/main/java/com/esri/arcgismaps/sample/geocodeoffline/MainActivity.kt b/geocode-offline/src/main/java/com/esri/arcgismaps/sample/geocodeoffline/MainActivity.kt deleted file mode 100644 index 3649a6c30..000000000 --- a/geocode-offline/src/main/java/com/esri/arcgismaps/sample/geocodeoffline/MainActivity.kt +++ /dev/null @@ -1,269 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.geocodeoffline - -import android.database.MatrixCursor -import android.graphics.drawable.BitmapDrawable -import android.os.Bundle -import android.provider.BaseColumns -import android.util.Log -import android.view.Menu -import android.widget.AutoCompleteTextView -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.widget.SearchView -import androidx.core.content.ContextCompat -import androidx.cursoradapter.widget.SimpleCursorAdapter -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.geometry.GeometryEngine -import com.arcgismaps.geometry.Point -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.Basemap -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.layers.ArcGISTiledLayer -import com.arcgismaps.mapping.layers.TileCache -import com.arcgismaps.mapping.symbology.PictureMarkerSymbol -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.tasks.geocode.GeocodeParameters -import com.arcgismaps.tasks.geocode.GeocodeResult -import com.arcgismaps.tasks.geocode.LocatorTask -import com.esri.arcgismaps.sample.geocodeoffline.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.io.File - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - // display the metro area of the tapped location - private val descriptionTV by lazy { - activityMainBinding.descriptionTV - } - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - // create a picture marker symbol - private val pinSymbol: PictureMarkerSymbol by lazy { - createPinSymbol() - } - - // geocode parameters used to perform a search - private val geocodeParameters: GeocodeParameters by lazy { - GeocodeParameters().apply { - // get all attributes - resultAttributeNames.add("*") - // get only the closest result - maxResults = 1 - } - } - - // locator task to provide geocoding services - private val locatorTask: LocatorTask by lazy { - LocatorTask(File(provisionPath, getString(R.string.san_diego_loc)).path) - } - - // create a graphics overlay - private val graphicsOverlay: GraphicsOverlay = GraphicsOverlay() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // load the tile cache from local storage - val tileCache = TileCache("$provisionPath/streetmap_SD.tpkx") - // create a tiled layer and add it to as the base map - val tiledLayer = ArcGISTiledLayer(tileCache) - mapView.apply { - map = ArcGISMap(Basemap(tiledLayer)) - // set map initial viewpoint - map?.initialViewpoint = Viewpoint(32.72, -117.155, 120000.0) - // add a graphics overlay to the map view - graphicsOverlays.add(graphicsOverlay) - } - - // load geocode locator task - lifecycleScope.launch { - locatorTask.load().onSuccess { - mapView.onSingleTapConfirmed.collect { event -> - // find address with reverse geocode using the tapped location - event.mapPoint?.let { mapPoint -> findAddressReverseGeocode(mapPoint) } - } - }.onFailure { - showError(it.message.toString()) - } - } - } - - override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.menu, menu) - val search = menu.findItem(R.id.appSearchBar) - // set up address search view and listeners - setupAddressSearchView(search.actionView as SearchView) - return super.onCreateOptionsMenu(menu) - } - - /** - * Sets up the address SearchView and uses MatrixCursor to - * show suggestions to the user as text is entered. - */ - private fun setupAddressSearchView(addressSearchView: SearchView) { - // disable threshold to show results from single character - val autoCompleteTextViewID = resources.getIdentifier("search_src_text", "id", packageName) - addressSearchView.findViewById(autoCompleteTextViewID).threshold = 0 - - // get the list of pre-made suggestions - val suggestions = resources.getStringArray(R.array.suggestion_items) - // set up parameters for searching with MatrixCursor - val columnNames = arrayOf(BaseColumns._ID, "address") - val suggestionsCursor = MatrixCursor(columnNames) - // add each address suggestion to a new row - suggestions.forEachIndexed { i, s -> suggestionsCursor.addRow(arrayOf(i, s)) } - - // column names for the adapter to look at when mapping data - val cols = arrayOf("address") - // ids that show where data should be assigned in the layout - val to = intArrayOf(R.id.suggestionAddress) - // define SimpleCursorAdapter - val suggestionsAdapter = SimpleCursorAdapter( - this@MainActivity, - R.layout.suggestion_address, suggestionsCursor, cols, to, 0 - ) - - addressSearchView.suggestionsAdapter = suggestionsAdapter - // handle an address suggestion being chosen - addressSearchView.setOnSuggestionListener(object : SearchView.OnSuggestionListener { - override fun onSuggestionSelect(position: Int): Boolean { - return false - } - - override fun onSuggestionClick(position: Int): Boolean { - // geocode the typed address - addressSearchView.setQuery(suggestions[position], true) - return true - } - }) - - // geocode the searched address on submit - addressSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener { - override fun onQueryTextSubmit(address: String): Boolean { - geocodeAddress(address) - addressSearchView.clearFocus() - return true - } - - override fun onQueryTextChange(newText: String?) = true - }) - } - - /** - * Use the locator task to geocode the given address. - * - * @param address as a string to geocode - */ - private fun geocodeAddress(address: String) = lifecycleScope.launch { - // clear graphics on map before displaying search results - graphicsOverlay.graphics.clear() - // load the locator task - locatorTask.load().getOrThrow() - // run the locatorTask geocode task, passing in the address - val geocodeResults = locatorTask.geocode(address, geocodeParameters).getOrThrow() - geocodeResults.ifEmpty { - // no address found in geocode so return - showError("No address found for $address") - return@launch - } - // display address found in geocode - displaySearchResultOnMap(geocodeResults) - } - - /** - * Get the reverse geocode result from the [mapPoint] - */ - private suspend fun findAddressReverseGeocode(mapPoint: Point) { - // normalize the geometry - needed if the user crosses the international date line. - val normalizedPoint = GeometryEngine.normalizeCentralMeridian(mapPoint) as Point - locatorTask.reverseGeocode(normalizedPoint).onSuccess { geocodeResults -> - // no address found in geocode so return - if (geocodeResults.isEmpty()) { - showError("Could not find address at tapped point") - return@onSuccess - } - displaySearchResultOnMap(geocodeResults) - }.onFailure { - showError(it.message.toString()) - } - } - - /** - * Turn the first address from [geocodeResultList] into a point marker and adds it to the graphic overlay of the map. - */ - private fun displaySearchResultOnMap(geocodeResultList: List) { - // clear graphics overlay of existing graphics - graphicsOverlay.graphics.clear() - - // create graphic object - val resultLocationGraphic = Graphic( - geocodeResultList[0].displayLocation, - geocodeResultList[0].attributes, pinSymbol - ) - graphicsOverlay.graphics.add(resultLocationGraphic) - descriptionTV.text = geocodeResultList[0].label - - // get the envelop to set the viewpoint - val envelope = graphicsOverlay.extent ?: return showError("Geocode result extent is null") - // animate viewpoint to geocode result's extent - lifecycleScope.launch { - mapView.setViewpointGeometry(envelope, 25.0) - } - } - - /** - * Creates a picture marker symbol from the pin icon. - */ - private fun createPinSymbol(): PictureMarkerSymbol { - val pinDrawable = ContextCompat.getDrawable(this, R.drawable.pin) as BitmapDrawable - val pinSymbol = PictureMarkerSymbol.createWithImage(pinDrawable) - pinSymbol.apply { - // resize the dimensions of the symbol - width = 18f - height = 65f - } - return pinSymbol - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/geocode-offline/src/main/res/drawable-v24/ic_launcher_foreground.xml b/geocode-offline/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/geocode-offline/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/geocode-offline/src/main/res/drawable/ic_launcher_background.xml b/geocode-offline/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/geocode-offline/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/geocode-offline/src/main/res/menu/menu.xml b/geocode-offline/src/main/res/menu/menu.xml deleted file mode 100644 index 777703c57..000000000 --- a/geocode-offline/src/main/res/menu/menu.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/geocode-offline/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/geocode-offline/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/geocode-offline/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/geocode-offline/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/geocode-offline/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/geocode-offline/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/geocode-offline/src/main/res/mipmap-hdpi/ic_launcher.png b/geocode-offline/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/geocode-offline/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-hdpi/ic_launcher_round.png b/geocode-offline/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/geocode-offline/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-mdpi/ic_launcher.png b/geocode-offline/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/geocode-offline/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-mdpi/ic_launcher_round.png b/geocode-offline/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/geocode-offline/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-xhdpi/ic_launcher.png b/geocode-offline/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/geocode-offline/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/geocode-offline/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/geocode-offline/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-xxhdpi/ic_launcher.png b/geocode-offline/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/geocode-offline/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/geocode-offline/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/geocode-offline/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/geocode-offline/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/geocode-offline/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/geocode-offline/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/geocode-offline/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/geocode-offline/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/geocode-offline/src/main/res/values/strings.xml b/geocode-offline/src/main/res/values/strings.xml deleted file mode 100644 index cf943df5b..000000000 --- a/geocode-offline/src/main/res/values/strings.xml +++ /dev/null @@ -1,13 +0,0 @@ - - Geocode offline - Search for an address or tap on the map - /SanDiego_StreetAddress.loc - Enter address - - 910 N Harbor Dr, San Diego, CA 92101 - 2920 Zoo Dr, San Diego, CA 92101 - 111 W Harbor Dr, San Diego, CA 92101 - 868 4th Ave, San Diego, CA 92101 - 750 A St, San Diego, CA 92101 - - diff --git a/gradle-plugins/build.gradle.kts b/gradle-plugins/build.gradle.kts new file mode 100644 index 000000000..e00110e4a --- /dev/null +++ b/gradle-plugins/build.gradle.kts @@ -0,0 +1,23 @@ +repositories { + google() + mavenCentral() +} + +plugins { + `kotlin-dsl` +} + +gradlePlugin { + plugins { + create("copyCodeFiles") { + id = "com.arcgismaps.sampleFiles.copy" + version = "1.0" + implementationClass = "com.arcgismaps.CopySampleFilesTask" + } + create("copyScreenshots") { + id = "com.arcgismaps.screenshots.copy" + version = "1.0" + implementationClass = "com.arcgismaps.CopyScreenshotsTask" + } + } +} diff --git a/gradle-plugins/settings.gradle.kts b/gradle-plugins/settings.gradle.kts new file mode 100644 index 000000000..014e161ed --- /dev/null +++ b/gradle-plugins/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "gradle-plugins" diff --git a/gradle-plugins/src/main/kotlin/com/arcgismaps/CopySampleFilesTask.kt b/gradle-plugins/src/main/kotlin/com/arcgismaps/CopySampleFilesTask.kt new file mode 100644 index 000000000..7988ac585 --- /dev/null +++ b/gradle-plugins/src/main/kotlin/com/arcgismaps/CopySampleFilesTask.kt @@ -0,0 +1,47 @@ +package com.arcgismaps + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.file.DuplicatesStrategy +import org.gradle.api.file.FileCollection +import org.gradle.api.tasks.Copy +import org.gradle.kotlin.dsl.register + +/** + * Copy md, kt, and json files to a directory (with the name of the associated sample) + * into the app's build assets directory. + */ +class CopySampleFilesTask : Plugin { + override fun apply(project: Project) { + project.tasks.register("copyCodeFiles") { + description = """ + Copies sample files for the given sample directory if a code file doesn't + already exist or a newer version is present. + """.trimIndent() + + // Define the input files + val inputFiles: FileCollection = project.fileTree("${project.rootDir.path}/samples/") { + exclude("**/build/") + include("**/*.md", "**/*.kt", "**/*.metadata.json") + } + + // Set input files + inputs.files(inputFiles) + + // Define the output directory + val outputDir = project.file("${project.rootDir.path}/app/build/sampleAssets/samples/") + outputs.dir(outputDir) + + from(inputFiles) { + eachFile { + path = path.substringBefore("/") + "/" + name + includeEmptyDirs = false + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } + } + + // Place in the assets codeFiles folder of the app. + into(outputDir) + } + } +} \ No newline at end of file diff --git a/gradle-plugins/src/main/kotlin/com/arcgismaps/CopyScreenshotsTask.kt b/gradle-plugins/src/main/kotlin/com/arcgismaps/CopyScreenshotsTask.kt new file mode 100644 index 000000000..90909d1dc --- /dev/null +++ b/gradle-plugins/src/main/kotlin/com/arcgismaps/CopyScreenshotsTask.kt @@ -0,0 +1,59 @@ +package com.arcgismaps + +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.api.file.DuplicatesStrategy +import org.gradle.api.tasks.Copy +import org.gradle.kotlin.dsl.register +import java.awt.image.BufferedImage +import javax.imageio.ImageIO + + +/** + * Copy screenshot files to a directory (with the name of the associated sample) + * into the app's build assets directory. + */ +class CopyScreenshotsTask : Plugin { + override fun apply(project: Project) { + project.tasks.register("copyScreenshots") { + description = """ + Copies screenshot screenshots from all the given sample directories. Note: + Screenshots must be in .png format. + """.trimIndent() + + // Define input and output directories + val inputDir = project.file("${project.rootDir.path}/samples/") + val outputDir = project.file("${project.rootDir.path}/app/build/sampleAssets/samples/") + + from(inputDir) { + // Include all screenshots. + exclude("**/build/") + exclude("**/mipmap*/**") + exclude("**/res/") + include("**/*.png") + eachFile { + // Prepend the kebab style sample directory to each file path. + path = path.substringBefore("/") + "/" + name.replace("-", "_") + includeEmptyDirs = false + // Don't overwrite existing files with the same name. + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + } + } + + into(outputDir) + + doLast { + outputDir.listFiles()?.forEach { sampleFolder -> + sampleFolder.listFiles()?.filter { it.name.endsWith(".png") }?.forEach { + val inputImage = ImageIO.read(it) + val outputImage = BufferedImage(350, 200, inputImage.type) + val g2d = outputImage.createGraphics() + g2d.drawImage(inputImage, 0, 0, 350, 200, null) + g2d.dispose() + ImageIO.write(outputImage, "png", it) + } + } + } + } + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 1b9f5f090..ed515f7b7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,19 +1,26 @@ # Project-wide Gradle settings. - +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. # enable daemon org.gradle.daemon=true - +# 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. org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - # 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 +# This option should only be used with decoupled projects. For more details, visit +# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects org.gradle.parallel=true - -# enable configure on demand -org.gradle.configureondemand=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true -android.enableJetifier=true +# Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official +# Enables namespacing of each library's R class so that its R class includes only the +# resources declared in the library itself and none from the library's dependencies, +# thereby reducing the size of the R class for that library +android.nonTransitiveRClass=true +android.enableJetifier=true \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9f36c0774..0992da2b6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,71 +1,117 @@ [versions] + # ArcGIS Maps SDK for Kotlin version -arcgisMapsKotlinVersion = "200.5.0" -# SDK versions -compileSdk = "34" -minSdk = "26" -targetSdk = "34" -versionCode = "2005000" -versionName = "200.5.0" -# Kotlin versions -kotlinVersion = "1.9.23" -ktxLifecycle = "2.7.0" -ktxFragmentsExt = "1.6.2" -ktxActivityExt = "1.9.0" -ktxAndroidCore = "1.13.0" +arcgisMapsKotlinVersion = "200.6.0" + +### Android versions +androidGradlePlugin = "8.7.1" +lifecycle = "2.8.4" +androidTools = "31.5.2" +appcompat = "1.7.0" +constraintLayoutVersion = "2.1.4" +kotlinxSerializationJson = "1.6.0" +accompanistSystemuicontroller = "0.32.0" +workVersion = "2.9.1" +datastorePreferences = "1.1.1" +roomVersion = "2.6.1" + +### Kotlin versions +kotlinVersion = "2.0.0" +coreKtx = "1.13.1" +# TODO is this needed: ktx-activity = { group = "androidx.activity", name = "activity-ktx", version.ref = "ktxActivity" } +ktxActivity = "1.9.1" +ksp = "2.0.0-1.0.21" kotlinCompilerExt = "1.5.12" -# Compose versions -composeActivityVersion = "1.9.0" -composeBOM = "2024.04.01" -# Library versions -appcompatVersion = "1.6.1" commonsIoVersion = "2.15.1" -constraintLayoutVersion = "2.1.4" -coordinateLayoutVersion = "1.2.0" -jsonSerialization = "1.6.3" -workVersion = "2.9.0" -multidexVersion = "2.0.1" -materialVersion = "1.11.0" -androidBrowserVersion = "1.8.0" -androidxWindow = "1.2.0" -# Plugin versions -gradleVersion = "8.3.2" -[plugins] -android-application = { id = "com.android.application", version.ref = "gradleVersion" } -android-library = { id = "com.android.library", version.ref = "gradleVersion" } -kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinVersion" } -kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinVersion" } +### Compose verions +composeBom = "2024.10.00" +activityCompose = "1.9.3" +material = "1.12.0" +navigationCompose = "2.8.3" + +### Testing versions +junit = "4.13.2" +junitVersion = "1.2.1" +espressoCore = "3.6.1" + +### Application Verions +versionCode = "2006000" +versionName = "200.6.0" +minSdk = "26" +targetSdk = "35" +### Third party libraries [libraries] -android-material = { group = "com.google.android.material", name = "material", version.ref = "materialVersion"} -androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompatVersion"} -androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "composeActivityVersion"} -androidx-activity-ktx = { group = "androidx.activity", name = "activity-ktx", version.ref = "ktxActivityExt"} -androidx-browser = { group = "androidx.browser", name = "browser", version.ref = "androidBrowserVersion"} -androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBOM"} -androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } + +### Android libs +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycle" } +androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycle" } +androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } +commons-io = { group = "commons-io", name = "commons-io", version.ref = "commonsIoVersion" } +android-material = { group = "com.google.android.material", name = "material", version.ref = "material" } +androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintLayoutVersion" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } +accompanist-systemuicontroller = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanistSystemuicontroller" } +androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workVersion" } +androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastorePreferences" } +androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "roomVersion" } +androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "roomVersion" } +androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "roomVersion" } + +### Compose libs +androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } +androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" } +androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } -androidx-window = { group = "androidx.window", name = "window", version.ref = "androidxWindow" } -androidx-window-core = { group = "androidx.window", name = "window-core", version.ref = "androidxWindow" } -androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintLayoutVersion"} -androidx-coordinatorlayout = { group = "androidx.coordinatorlayout", name = "coordinatorlayout", version.ref = "coordinateLayoutVersion"} -androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "ktxAndroidCore"} -androidx-fragment-ktx = { group = "androidx.fragment", name = "fragment-ktx", version.ref = "ktxFragmentsExt" } -androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "ktxLifecycle"} -androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "ktxLifecycle"} -androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "ktxLifecycle"} -androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "ktxLifecycle"} -androidx-multidex = { group = "androidx.multidex", name = "multidex", version.ref = "multidexVersion"} -androidx-work-runtime-ktx = { group = "androidx.work", name = "work-runtime-ktx", version.ref = "workVersion" } -arcgis-maps-kotlin = { group = "com.esri", name = "arcgis-maps-kotlin", version.ref = "arcgisMapsKotlinVersion"} -arcgis-maps-kotlin-toolkit-bom = { group = "com.esri", name = "arcgis-maps-kotlin-toolkit-bom", version.ref = "arcgisMapsKotlinVersion"} +androidx-lifecycle-viewmodel-compose = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-compose", version.ref = "lifecycle" } +androidx-compose-ui-test = { group = "androidx.compose.ui", name = "ui-test" } +androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } +androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } +androidx-compose-material3 = { group = "androidx.compose.material3", name = "material3" } +androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" } + +### ArcGIS Maps SDK for Kotlin libs +arcgis-maps-kotlin = { group = "com.esri", name = "arcgis-maps-kotlin", version.ref = "arcgisMapsKotlinVersion" } +arcgis-maps-kotlin-toolkit-bom = { group = "com.esri", name = "arcgis-maps-kotlin-toolkit-bom", version.ref = "arcgisMapsKotlinVersion" } arcgis-maps-kotlin-toolkit-authentication = { group = "com.esri", name = "arcgis-maps-kotlin-toolkit-authentication" } arcgis-maps-kotlin-toolkit-geoview-compose = { group = "com.esri", name = "arcgis-maps-kotlin-toolkit-geoview-compose" } arcgis-maps-kotlin-toolkit-featureforms = { group = "com.esri", name = "arcgis-maps-kotlin-toolkit-featureforms" } -commons-io = { group = "commons-io", name = "commons-io", version.ref = "commonsIoVersion" } -serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "jsonSerialization" } -stdlib-jdk8 = { group = "org.jetbrains.kotlin", name = "kotlin-stdlib-jdk8", version.ref = "kotlinVersion"} + +### Third party libraries +coil-compose = { group = "io.coil-kt.coil3", name = "coil-compose", version = "3.0.0-rc01" } +coil-network-http = { group = "io.coil-kt.coil3", name = "coil-network-okhttp", version = "3.0.0-rc01" } + +### Testing libs +junit = { group = "junit", name = "junit", version.ref = "junit" } +androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" } +androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" } + +# Dependencies of the included build-logic +android-gradlePlugin = { group = "com.android.tools.build", name = "gradle", version.ref = "androidGradlePlugin" } +kotlin-gradlePlugin = { group = "org.jetbrains.kotlin", name = "kotlin-gradle-plugin", version.ref = "kotlinVersion" } +ksp-gradlePlugin = { group = "com.google.devtools.ksp", name = "com.google.devtools.ksp.gradle.plugin", version.ref = "ksp" } +android-tools-common = { group = "com.android.tools", name = "common", version.ref = "androidTools" } + + +[plugins] +android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlinVersion" } +android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } +compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlinVersion" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinVersion" } +gradle-secrets = { id = "com.google.android.libraries.mapsplatform.secrets-gradle-plugin", version = "2.0.1" } + +# Plugins defined by the project build-logic +arcgismaps-android-application = { id = "arcgismaps.android.application", version = "unspecified" } +arcgismaps-android-application-compose = { id = "arcgismaps.android.application.compose", version = "unspecified" } +arcgismaps-android-library-compose = { id = "arcgismaps.android.library.compose", version = "unspecified" } +arcgismaps-android-library = { id = "arcgismaps.android.library", version = "unspecified" } +arcgismaps-kotlin-sample = { id = "arcgismaps.kotlin.sample", version = "unspecified" } +sample-files-copy = { id = "com.arcgismaps.sampleFiles.copy", version = "unspecified" } +screenshots-copy = { id = "com.arcgismaps.screenshots.copy", version = "unspecified" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9bcc5593d..043f02227 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Tue Apr 16 15:17:41 PDT 2024 +#Mon Nov 04 09:26:16 PST 2024 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew.bat b/gradlew.bat index 107acd32c..ac1b06f93 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,89 +1,89 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@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 Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@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="-Xmx64m" "-Xms64m" - -@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 execute - -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 execute - -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 - -: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 %* - -: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 +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@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 Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@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="-Xmx64m" "-Xms64m" + +@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 execute + +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 execute + +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 + +: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 %* + +: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/identify-layer-features/.gitignore b/identify-layer-features/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/identify-layer-features/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/identify-layer-features/build.gradle.kts b/identify-layer-features/build.gradle.kts deleted file mode 100644 index fc1bbbf5e..000000000 --- a/identify-layer-features/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.identifylayerfeatures" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.identifylayerfeatures" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/identify-layer-features/proguard-rules.pro b/identify-layer-features/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/identify-layer-features/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/identify-layer-features/src/main/AndroidManifest.xml b/identify-layer-features/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/identify-layer-features/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/identify-layer-features/src/main/java/com/esri/arcgismaps/sample/identifylayerfeatures/MainActivity.kt b/identify-layer-features/src/main/java/com/esri/arcgismaps/sample/identifylayerfeatures/MainActivity.kt deleted file mode 100644 index ac4844fa4..000000000 --- a/identify-layer-features/src/main/java/com/esri/arcgismaps/sample/identifylayerfeatures/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.identifylayerfeatures - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.identifylayerfeatures.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - IdentifyLayerFeaturesApp() - } - } - } - - @Composable - private fun IdentifyLayerFeaturesApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/identify-layer-features/src/main/res/drawable-v24/ic_launcher_foreground.xml b/identify-layer-features/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/identify-layer-features/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/identify-layer-features/src/main/res/drawable/ic_launcher_background.xml b/identify-layer-features/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/identify-layer-features/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/identify-layer-features/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/identify-layer-features/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/identify-layer-features/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/identify-layer-features/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/identify-layer-features/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/identify-layer-features/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/identify-layer-features/src/main/res/mipmap-hdpi/ic_launcher.png b/identify-layer-features/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-hdpi/ic_launcher_round.png b/identify-layer-features/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-mdpi/ic_launcher.png b/identify-layer-features/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-mdpi/ic_launcher_round.png b/identify-layer-features/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-xhdpi/ic_launcher.png b/identify-layer-features/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/identify-layer-features/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-xxhdpi/ic_launcher.png b/identify-layer-features/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/identify-layer-features/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/identify-layer-features/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/identify-layer-features/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/identify-layer-features/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/identify-layer-features/src/main/res/values/strings.xml b/identify-layer-features/src/main/res/values/strings.xml deleted file mode 100644 index 5a6b8c777..000000000 --- a/identify-layer-features/src/main/res/values/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - Identify layer features - - https://sampleserver6.arcgisonline.com/arcgis/rest/services/DamageAssessment/FeatureServer/0 - - - https://sampleserver6.arcgisonline.com/arcgis/rest/services/SampleWorldCities/MapServer - - diff --git a/manage-operational-layers/.gitignore b/manage-operational-layers/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/manage-operational-layers/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/manage-operational-layers/build.gradle.kts b/manage-operational-layers/build.gradle.kts deleted file mode 100644 index 0ca9e0a7f..000000000 --- a/manage-operational-layers/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.manageoperationallayers" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.manageoperationallayers" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/manage-operational-layers/proguard-rules.pro b/manage-operational-layers/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/manage-operational-layers/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/manage-operational-layers/src/main/AndroidManifest.xml b/manage-operational-layers/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/manage-operational-layers/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/manage-operational-layers/src/main/java/com/esri/arcgismaps/sample/manageoperationallayers/MainActivity.kt b/manage-operational-layers/src/main/java/com/esri/arcgismaps/sample/manageoperationallayers/MainActivity.kt deleted file mode 100644 index d97c91028..000000000 --- a/manage-operational-layers/src/main/java/com/esri/arcgismaps/sample/manageoperationallayers/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.manageoperationallayers - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.manageoperationallayers.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - ManageOperationalLayersApp() - } - } - } - - @Composable - private fun ManageOperationalLayersApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/manage-operational-layers/src/main/res/drawable-v24/ic_launcher_foreground.xml b/manage-operational-layers/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/manage-operational-layers/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/manage-operational-layers/src/main/res/drawable/ic_launcher_background.xml b/manage-operational-layers/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/manage-operational-layers/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/manage-operational-layers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/manage-operational-layers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/manage-operational-layers/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/manage-operational-layers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/manage-operational-layers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/manage-operational-layers/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/manage-operational-layers/src/main/res/mipmap-hdpi/ic_launcher.png b/manage-operational-layers/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-hdpi/ic_launcher_round.png b/manage-operational-layers/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-mdpi/ic_launcher.png b/manage-operational-layers/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-mdpi/ic_launcher_round.png b/manage-operational-layers/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-xhdpi/ic_launcher.png b/manage-operational-layers/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/manage-operational-layers/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-xxhdpi/ic_launcher.png b/manage-operational-layers/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/manage-operational-layers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/manage-operational-layers/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/manage-operational-layers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/manage-operational-layers/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/manage-operational-layers/src/main/res/values/strings.xml b/manage-operational-layers/src/main/res/values/strings.xml deleted file mode 100644 index 939a98883..000000000 --- a/manage-operational-layers/src/main/res/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Manage operational layers - https://sampleserver5.arcgisonline.com/arcgis/rest/services/Elevation/WorldElevations/MapServer - https://sampleserver5.arcgisonline.com/arcgis/rest/services/Census/MapServer - https://sampleserver5.arcgisonline.com/arcgis/rest/services/DamageAssessment/MapServer - diff --git a/navigate-route/.gitignore b/navigate-route/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/navigate-route/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/navigate-route/build.gradle.kts b/navigate-route/build.gradle.kts deleted file mode 100644 index 0b646c585..000000000 --- a/navigate-route/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.navigateroute" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.navigateroute" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/navigate-route/proguard-rules.pro b/navigate-route/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/navigate-route/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/navigate-route/src/main/AndroidManifest.xml b/navigate-route/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/navigate-route/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/navigate-route/src/main/java/com/esri/arcgismaps/sample/navigateroute/MainActivity.kt b/navigate-route/src/main/java/com/esri/arcgismaps/sample/navigateroute/MainActivity.kt deleted file mode 100644 index be304284a..000000000 --- a/navigate-route/src/main/java/com/esri/arcgismaps/sample/navigateroute/MainActivity.kt +++ /dev/null @@ -1,401 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.navigateroute - -import android.os.Bundle -import android.speech.tts.TextToSpeech -import android.text.format.DateUtils -import android.util.Log -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.Polyline -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.location.LocationDisplayAutoPanMode -import com.arcgismaps.location.RouteTrackerLocationDataSource -import com.arcgismaps.location.SimulatedLocationDataSource -import com.arcgismaps.location.SimulationParameters -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.symbology.SimpleLineSymbol -import com.arcgismaps.mapping.symbology.SimpleLineSymbolStyle -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.navigation.DestinationStatus -import com.arcgismaps.navigation.RouteTracker -import com.arcgismaps.navigation.TrackingStatus -import com.arcgismaps.tasks.networkanalysis.RouteResult -import com.arcgismaps.tasks.networkanalysis.RouteTask -import com.arcgismaps.tasks.networkanalysis.Stop -import com.esri.arcgismaps.sample.navigateroute.databinding.ActivityMainBinding -import com.google.android.material.button.MaterialButton -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.cancelAndJoin -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.launch -import java.time.Instant -import java.util.concurrent.atomic.AtomicBoolean - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val resetNavigationButton: MaterialButton by lazy { - activityMainBinding.resetNavigationButton - } - - private val recenterButton: MaterialButton by lazy { - activityMainBinding.recenterButton - } - - private val distanceRemainingTextView: TextView by lazy { - activityMainBinding.distanceRemainingTextView - } - - private val timeRemainingTextView: TextView by lazy { - activityMainBinding.timeRemainingTextView - } - - private val nextDirectionTextView: TextView by lazy { - activityMainBinding.nextDirectionTextView - } - - private val nextStopTextView: TextView by lazy { - activityMainBinding.nextStopTextView - } - - /** - * Destination list of stops for the RouteParameters - */ - private val routeStops by lazy { - listOf( - // San Diego Convention Center - Stop(Point(-117.160386, 32.706608, SpatialReference.wgs84())), - // USS San Diego Memorial - Stop(Point(-117.173034, 32.712327, SpatialReference.wgs84())), - // RH Fleet Aerospace Museum - Stop(Point(-117.147230, 32.730467, SpatialReference.wgs84())) - ) - } - - // instance of the route ahead polyline - private var routeAheadGraphic: Graphic = Graphic() - - // instance of the route traveled polyline - private var routeTraveledGraphic: Graphic = Graphic() - - // instance of the MapView's graphic overlay - private val graphicsOverlay = GraphicsOverlay() - - // boolean to check if Android text-speech is initialized - private var isTextToSpeechInitialized = AtomicBoolean(false) - - // instance of Android text-speech - private var textToSpeech: TextToSpeech? = null - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - // some parts of the API require an Android Context to properly interact with Android system - // features, such as LocationProvider and application resources - ArcGISEnvironment.applicationContext = applicationContext - - lifecycle.addObserver(mapView) - - // create and add a map with a streets basemap style - val map = ArcGISMap(BasemapStyle.ArcGISStreets) - mapView.map = map - - // create a graphics overlay to hold our route graphics - mapView.graphicsOverlays.add(graphicsOverlay) - - // create text-to-speech to replay navigation voice guidance - textToSpeech = TextToSpeech(this) { status -> - if (status != TextToSpeech.ERROR) { - textToSpeech?.language = resources.configuration.locales[0] - isTextToSpeechInitialized.set(true) - } - } - - // generate a route with directions and stops for navigation - val routeTask = RouteTask(getString(R.string.routing_service_url)) - - // create the default parameters and solve route - lifecycleScope.launch { - // load and set the route parameters - val routeParameters = routeTask.createDefaultParameters().getOrElse { - return@launch showError("Error creating default parameters:${it.message}") - }.apply { - setStops(routeStops) - returnDirections = true - returnStops = true - returnRoutes = true - } - - // get the solved route result - val routeResult = routeTask.solveRoute(routeParameters).getOrElse { - return@launch showError("Error solving route:${it.message}") - } - - // get the route geometry from the route result - val routeGeometry = routeResult.routes[0].routeGeometry - - // set the map view view point to show the whole route - if (routeGeometry?.extent != null) { - mapView.setViewpoint(Viewpoint(routeGeometry.extent)) - } else { - return@launch showError("Route geometry extent is null.") - } - - // start navigating on app launch - startNavigation(routeResult) - } - - // wire up recenter button - recenterButton.setOnClickListener { - mapView.locationDisplay.setAutoPanMode(LocationDisplayAutoPanMode.Navigation) - recenterButton.isEnabled = false - } - } - - /** - * Start the navigation along the provided route using the [routeResult] and - * collects updates in the location using the MapView's location display. - * */ - private fun startNavigation(routeResult: RouteResult) { - // get the route's geometry from the route result - val routeGeometry: Polyline = routeResult.routes[0].routeGeometry - ?: return showError("Route is missing geometry") - - // create the graphics using the route's geometry - createRouteGraphics(routeGeometry) - - // set up a simulated location data source which simulates movement along the route - val simulationParameters = SimulationParameters( - Instant.now(), - velocity = 35.0, - horizontalAccuracy = 5.0, - verticalAccuracy = 5.0 - ) - - // create the simulated data source using the geometry and parameters - val simulatedLocationDataSource = SimulatedLocationDataSource( - routeGeometry, simulationParameters - ) - - // set up a RouteTracker for navigation along the calculated route - val routeTracker = RouteTracker( - routeResult, - routeIndex = 0, - skipCoincidentStops = true - ).apply { - setSpeechEngineReadyCallback { - isTextToSpeechInitialized.get() && textToSpeech?.isSpeaking == false - } - } - // plays the direction voice guidance - lifecycleScope.launch { - updateVoiceGuidance(routeTracker) - } - - // create a route tracker location data source to snap the location display to the route - val routeTrackerLocationDataSource = RouteTrackerLocationDataSource( - routeTracker, - simulatedLocationDataSource - ) - - // get the map view's location display and set it up - val locationDisplay = mapView.locationDisplay.also { - // set the simulated location data source as the location data source for this app - it.dataSource = routeTrackerLocationDataSource - it.setAutoPanMode(LocationDisplayAutoPanMode.Navigation) - } - - // start the LocationDisplay, which starts the - // RouteTrackerLocationDataSource and SimulatedLocationDataSource - lifecycleScope.launch { - locationDisplay.dataSource.start().getOrElse { - showError("Error starting LocationDataSource: ${it.message} ") - } - // set the text for first destination - nextStopTextView.text = resources.getStringArray(R.array.stop_message)[0] - } - - // listen for changes in location - val locationDisplayJob = lifecycleScope.launch { - locationDisplay.location.collect { - // get the route's tracking status - val trackingStatus = routeTracker.trackingStatus.value ?: return@collect - - // displays the remaining and traversed route - updateRouteGraphics(trackingStatus) - - // display route status and directions info - displayRouteInfo(routeTracker, trackingStatus) - } - } - - // listen if user navigates the map view away from the - // location display, activate the recenter button - val autoPanModeJob = lifecycleScope.launch { - locationDisplay.autoPanMode.filter { it == LocationDisplayAutoPanMode.Off } - .collect { recenterButton.isEnabled = true } - } - - // reset the navigation if button is clicked - resetNavigationButton.setOnClickListener { - lifecycleScope.launch { - if (locationDisplayJob.isActive) { - // stop location data sources - locationDisplay.dataSource.stop() - // cancel the coroutine jobs - locationDisplayJob.cancelAndJoin() - autoPanModeJob.cancelAndJoin() - // start navigation again - startNavigation(routeResult) - } - } - } - } - - /** - * Uses Android's [textToSpeech] to speak to say the latest - * voice guidance from the [routeTracker] out loud. - */ - private suspend fun updateVoiceGuidance(routeTracker: RouteTracker) { - // listen for new voice guidance events - routeTracker.newVoiceGuidance.collect { voiceGuidance -> - // use Android's text to speech to speak the voice guidance - textToSpeech?.speak(voiceGuidance.text, TextToSpeech.QUEUE_FLUSH, null, null) - // set next direction text - nextDirectionTextView.text = getString(R.string.next_direction, voiceGuidance.text) - } - } - - /** - * Displays the route distance and time information using [trackingStatus], and - * switches destinations using [routeTracker]. When final destination is reached, - * the location data source is stopped. - */ - private suspend fun displayRouteInfo( - routeTracker: RouteTracker, - trackingStatus: TrackingStatus - ) { - // get remaining distance information - val remainingDistance = trackingStatus.destinationProgress.remainingDistance - // convert remaining minutes to hours:minutes:seconds - val remainingTimeString = - DateUtils.formatElapsedTime((trackingStatus.destinationProgress.remainingTime * 60).toLong()) - - // update text views - distanceRemainingTextView.text = getString( - R.string.distance_remaining, - remainingDistance.displayText, - remainingDistance.displayTextUnits.abbreviation - ) - timeRemainingTextView.text = getString(R.string.time_remaining, remainingTimeString) - - // if a destination has been reached - if (trackingStatus.destinationStatus == DestinationStatus.Reached) { - // if there are more destinations to visit. Greater than 1 because the start point is considered a "stop" - if (trackingStatus.remainingDestinationCount > 1) { - // switch to the next destination - routeTracker.switchToNextDestination().getOrElse { - return showError("Error retrieving next destination: ${it.message}") - } - // set second stop message - nextStopTextView.text = resources.getStringArray(R.array.stop_message)[1] - } else { - // the final destination has been reached, - // stop the location data source - mapView.locationDisplay.dataSource.stop() - // set last stop message - nextStopTextView.text = resources.getStringArray(R.array.stop_message)[2] - } - } - } - - /** - * Update the remaining and traveled route graphics using [trackingStatus] - */ - private fun updateRouteGraphics(trackingStatus: TrackingStatus) { - trackingStatus.routeProgress.let { - // set geometries for the route ahead and the remaining route - routeAheadGraphic.geometry = it.remainingGeometry - routeTraveledGraphic.geometry = it.traversedGeometry - } - } - - /** - * Initialize and add route travel graphics to the map using [routeGeometry] - */ - private fun createRouteGraphics(routeGeometry: Polyline) { - // clear any graphics from the current graphics overlay - graphicsOverlay.graphics.clear() - - // create a graphic (with a dashed line symbol) to represent the route - routeAheadGraphic = Graphic( - routeGeometry, - SimpleLineSymbol( - SimpleLineSymbolStyle.Dash, - Color(getColor(com.esri.arcgismaps.sample.sampleslib.R.color.colorPrimary)), - 5f - ) - ) - - // create a graphic (solid) to represent the route that's been traveled (initially empty) - routeTraveledGraphic = Graphic( - routeGeometry, - SimpleLineSymbol( - SimpleLineSymbolStyle.Solid, - Color.red, - 5f - ) - ) - - // add the graphics to the mapView's graphics overlays - mapView.graphicsOverlays[0].graphics.addAll( - listOf( - routeAheadGraphic, - routeTraveledGraphic - ) - ) - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} - diff --git a/navigate-route/src/main/res/drawable-v24/ic_launcher_foreground.xml b/navigate-route/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/navigate-route/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/navigate-route/src/main/res/drawable/ic_launcher_background.xml b/navigate-route/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/navigate-route/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/navigate-route/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/navigate-route/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/navigate-route/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/navigate-route/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/navigate-route/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/navigate-route/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/navigate-route/src/main/res/mipmap-hdpi/ic_launcher.png b/navigate-route/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/navigate-route/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-hdpi/ic_launcher_round.png b/navigate-route/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/navigate-route/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-mdpi/ic_launcher.png b/navigate-route/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/navigate-route/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-mdpi/ic_launcher_round.png b/navigate-route/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/navigate-route/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-xhdpi/ic_launcher.png b/navigate-route/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/navigate-route/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/navigate-route/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/navigate-route/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-xxhdpi/ic_launcher.png b/navigate-route/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/navigate-route/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/navigate-route/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/navigate-route/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/navigate-route/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/navigate-route/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/navigate-route/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/navigate-route/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/navigate-route/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/navigate-route/src/main/res/values/strings.xml b/navigate-route/src/main/res/values/strings.xml deleted file mode 100644 index 9992920d8..000000000 --- a/navigate-route/src/main/res/values/strings.xml +++ /dev/null @@ -1,14 +0,0 @@ - - Navigate route - https://sampleserver7.arcgisonline.com/server/rest/services/NetworkAnalysis/SanDiego/NAServer/Route - Distance remaining: %s %s - Time remaining: %s - Next direction: %s - Reset Navigation - Recenter - - Navigating to the first stop, the USS San Diego Memorial. - Navigating to the second stop, the Fleet Science Center. - Arrived at the final destination. - - diff --git a/play-kml-tour/.gitignore b/play-kml-tour/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/play-kml-tour/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/play-kml-tour/build.gradle.kts b/play-kml-tour/build.gradle.kts deleted file mode 100644 index acb69f7fe..000000000 --- a/play-kml-tour/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.playkmltour" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.playkmltour" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(libs.androidx.appcompat) - implementation(project(":samples-lib")) -} diff --git a/play-kml-tour/proguard-rules.pro b/play-kml-tour/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/play-kml-tour/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/play-kml-tour/src/main/AndroidManifest.xml b/play-kml-tour/src/main/AndroidManifest.xml deleted file mode 100644 index 07ff67411..000000000 --- a/play-kml-tour/src/main/AndroidManifest.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/play-kml-tour/src/main/java/com/esri/arcgismaps/sample/playkmltour/DownloadActivity.kt b/play-kml-tour/src/main/java/com/esri/arcgismaps/sample/playkmltour/DownloadActivity.kt deleted file mode 100644 index 9619f5308..000000000 --- a/play-kml-tour/src/main/java/com/esri/arcgismaps/sample/playkmltour/DownloadActivity.kt +++ /dev/null @@ -1,21 +0,0 @@ -package com.esri.arcgismaps.sample.playkmltour - -import android.content.Intent -import android.os.Bundle -import com.esri.arcgismaps.sample.sampleslib.DownloaderActivity - -class DownloadActivity : DownloaderActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - downloadAndStartSample( - Intent(this, MainActivity::class.java), - // get the app name of the sample - getString(R.string.app_name), - listOf( - // ArcGIS Portal item containing the .kmz markup tour file - // of Esri HQ and some of the global offices - "https://arcgisruntime.maps.arcgis.com/home/item.html?id=f10b1d37fdd645c9bc9b189fb546307c" - ) - ) - } -} diff --git a/play-kml-tour/src/main/java/com/esri/arcgismaps/sample/playkmltour/MainActivity.kt b/play-kml-tour/src/main/java/com/esri/arcgismaps/sample/playkmltour/MainActivity.kt deleted file mode 100644 index 4406f09ac..000000000 --- a/play-kml-tour/src/main/java/com/esri/arcgismaps/sample/playkmltour/MainActivity.kt +++ /dev/null @@ -1,249 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.playkmltour - -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.appcompat.content.res.AppCompatResources -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.mapping.ArcGISScene -import com.arcgismaps.mapping.ArcGISTiledElevationSource -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Surface -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.ViewpointType -import com.arcgismaps.mapping.kml.KmlContainer -import com.arcgismaps.mapping.kml.KmlDataset -import com.arcgismaps.mapping.kml.KmlNode -import com.arcgismaps.mapping.kml.KmlTour -import com.arcgismaps.mapping.kml.KmlTourController -import com.arcgismaps.mapping.kml.KmlTourStatus -import com.arcgismaps.mapping.layers.KmlLayer -import com.esri.arcgismaps.sample.playkmltour.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch -import java.io.File -import kotlin.math.roundToInt - - -class MainActivity : AppCompatActivity() { - - private val provisionPath: String by lazy { - getExternalFilesDir(null)?.path.toString() + File.separator + getString(R.string.app_name) - } - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val sceneView by lazy { - activityMainBinding.sceneView - } - - private val playPauseButton by lazy { - activityMainBinding.playPauseButton - } - - private val resetTourButton by lazy { - activityMainBinding.resetTourButton - } - - private val tourStatusTV by lazy { - activityMainBinding.tourStatusTV - } - - private val tourProgressBar by lazy { - activityMainBinding.tourProgressBar - } - - private var initialViewpoint: Viewpoint? = null - - private val kmlTourController = KmlTourController() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(sceneView) - - - // add elevation data - val surface = Surface().apply { - elevationSources.add(ArcGISTiledElevationSource(getString(R.string.world_terrain_service))) - } - - // create a scene and set the surface - sceneView.scene = ArcGISScene(BasemapStyle.ArcGISImagery).apply { - baseSurface = surface - } - - // add a KML layer from a KML dataset with a KML tour - val kmlDataset = KmlDataset(provisionPath + getString(R.string.kml_tour_path)) - val kmlLayer = KmlLayer(kmlDataset) - - // add the layer to the scene view's operational layers - sceneView.scene?.operationalLayers?.add(kmlLayer) - - // load the KML layer - lifecycleScope.launch { - kmlLayer.load().onFailure { - showError(it.message.toString()) - }.onSuccess { - // get the first loaded KML tour - val kmlTour = findFirstKMLTour(kmlDataset.rootNodes) - if (kmlTour == null) { - showError("Cannot find KML tour in dataset") - return@onSuccess - } - - // collect changes in KML tour status - collectKmlTourStatus(kmlTour) - - // set the KML tour to the controller - kmlTourController.tour = kmlTour - } - } - - resetTourButton.setOnClickListener { - // set tour to the initial viewpoint - initialViewpoint?.let { sceneView.setViewpoint(it) } - // reset tour controller - kmlTourController.reset() - } - - playPauseButton.setOnClickListener { - // button was clicked when tour was playing - if (kmlTourController.tour?.status?.value == KmlTourStatus.Playing) - // pause KML tour - kmlTourController.pause() - else - // play KML tour - kmlTourController.play() - } - } - - /** - * Recursively searches for the first KML tour in a list of [kmlNodes]. - * Returns the first [KmlTour], or null if there are no tours. - */ - private fun findFirstKMLTour(kmlNodes: List): KmlTour? { - kmlNodes.forEach { node -> - if (node is KmlTour) - return node - else if (node is KmlContainer) - return findFirstKMLTour(node.childNodes) - } - return null - } - - /** - * Collects KmlTourStatus events from the [kmlTour] and then calls - * showKmlTourStatus() - */ - private fun collectKmlTourStatus(kmlTour: KmlTour) = lifecycleScope.launch { - kmlTour.status.collect { kmlTourStatus -> - when (kmlTourStatus) { - KmlTourStatus.Completed -> { - showKmlTourStatus("Completed", isResetEnabled = false, isPlayingTour = false) - } - KmlTourStatus.Initialized -> { - showKmlTourStatus("Initialized", isResetEnabled = false, isPlayingTour = false) - } - KmlTourStatus.Paused -> { - showKmlTourStatus("Paused", isResetEnabled = true, isPlayingTour = false) - } - KmlTourStatus.Playing -> { - showKmlTourStatus("Playing", isResetEnabled = true, isPlayingTour = true) - // set the tour's initial viewpoint - if (initialViewpoint == null) { - initialViewpoint = sceneView.getCurrentViewpoint( - ViewpointType.BoundingGeometry - ) - } - } - else -> {} - } - } - } - - /** - * Displays the KML tour status using the [kmlTourStatus], display [resetTourButton] - * if [isResetEnabled] and set [playPauseButton] based on [isPlayingTour]. - */ - private fun showKmlTourStatus( - kmlTourStatus: String, - isResetEnabled: Boolean, - isPlayingTour: Boolean - ) { - // set the KML tour status - tourStatusTV.text = String.format("Tour status: %s", kmlTourStatus) - - // enable the buttons - resetTourButton.isEnabled = isResetEnabled - playPauseButton.isEnabled = true - - // show pause button if true - if (isPlayingTour) { - playPauseButton.apply { - // set button icon - icon = AppCompatResources.getDrawable( - this@MainActivity, - R.drawable.ic_round_pause_24 - ) - // set button text - text = getText(R.string.pause) - } - } else { // show play button if false - playPauseButton.apply { - // set button icon - icon = AppCompatResources.getDrawable( - this@MainActivity, - R.drawable.ic_round_play_arrow_24 - ) - // set button text - text = getString(R.string.play) - } - } - - // get progress of tour every second - lifecycleScope.launch { - // run as long as KML tour status is "Playing" - while (kmlTourStatus == "Playing") { - // get percentage of current position over total duration - val tourProgressInt = ((kmlTourController.currentPosition.value * 100.0) - / (kmlTourController.totalDuration.value)).roundToInt() - tourProgressBar.progress = tourProgressInt - // set a second delay - delay(1000) - } - } - - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(sceneView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/play-kml-tour/src/main/res/drawable-v24/ic_launcher_foreground.xml b/play-kml-tour/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/play-kml-tour/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/play-kml-tour/src/main/res/drawable/ic_launcher_background.xml b/play-kml-tour/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/play-kml-tour/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/play-kml-tour/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/play-kml-tour/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/play-kml-tour/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/play-kml-tour/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/play-kml-tour/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/play-kml-tour/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/play-kml-tour/src/main/res/mipmap-hdpi/ic_launcher.png b/play-kml-tour/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-hdpi/ic_launcher_round.png b/play-kml-tour/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-mdpi/ic_launcher.png b/play-kml-tour/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-mdpi/ic_launcher_round.png b/play-kml-tour/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-xhdpi/ic_launcher.png b/play-kml-tour/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/play-kml-tour/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-xxhdpi/ic_launcher.png b/play-kml-tour/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/play-kml-tour/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/play-kml-tour/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/play-kml-tour/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/play-kml-tour/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/play-kml-tour/src/main/res/values/strings.xml b/play-kml-tour/src/main/res/values/strings.xml deleted file mode 100644 index 2d8919e93..000000000 --- a/play-kml-tour/src/main/res/values/strings.xml +++ /dev/null @@ -1,9 +0,0 @@ - - Play KML tour - https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer - /Esri_tour.kmz - Tour status: - Reset tour - Play tour - Pause tour - diff --git a/project-geometry/.gitignore b/project-geometry/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/project-geometry/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/project-geometry/build.gradle.kts b/project-geometry/build.gradle.kts deleted file mode 100644 index 6e4f41c03..000000000 --- a/project-geometry/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.projectgeometry" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.projectgeometry" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/project-geometry/proguard-rules.pro b/project-geometry/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/project-geometry/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/project-geometry/src/main/AndroidManifest.xml b/project-geometry/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/project-geometry/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/project-geometry/src/main/java/com/esri/arcgismaps/sample/projectgeometry/MainActivity.kt b/project-geometry/src/main/java/com/esri/arcgismaps/sample/projectgeometry/MainActivity.kt deleted file mode 100644 index 31b59c282..000000000 --- a/project-geometry/src/main/java/com/esri/arcgismaps/sample/projectgeometry/MainActivity.kt +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.projectgeometry - -import android.graphics.BitmapFactory -import android.graphics.drawable.BitmapDrawable -import android.os.Bundle -import android.util.Log -import android.view.View -import android.widget.TextView -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.geometry.* -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.Viewpoint -import com.arcgismaps.mapping.symbology.PictureMarkerSymbol -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.MapView -import com.esri.arcgismaps.sample.projectgeometry.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch -import java.util.Locale - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - // setup the data binding for the MapView - private val mapView: MapView by lazy { - activityMainBinding.mapView - } - - // shows the projection information as a TextView - private val infoTextView: TextView by lazy { - activityMainBinding.infoTextView - } - - // setup the red pin marker image as bitmap drawable - private val markerDrawable: BitmapDrawable by lazy { - // load the bitmap from resources and create a drawable - val bitmap = BitmapFactory.decodeResource(resources, R.drawable.pin_symbol) - BitmapDrawable(resources, bitmap) - } - - // setup the red pin marker as a Graphic - private val markerGraphic: Graphic by lazy { - // creates a symbol from the marker drawable - val markerSymbol = PictureMarkerSymbol.createWithImage(markerDrawable).apply { - // resize the symbol into a smaller size - width = 30f - height = 30f - // offset in +y axis so the marker spawned - // is right on the touch point - offsetY = 25f - } - // create the graphic from the symbol - Graphic(symbol = markerSymbol) - } - - // creates a graphic overlay - private val graphicsOverlay: GraphicsOverlay = GraphicsOverlay() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - // create and add a map with a navigation night basemap style - val map = ArcGISMap(BasemapStyle.ArcGISNavigationNight) - // configure mapView assignments - mapView.apply { - this.map = map - // add our marker overlay to the graphics overlay - graphicsOverlay.graphics.add(markerGraphic) - // add the graphics overlay to display marker graphics - graphicsOverlays.add(graphicsOverlay) - // set the default viewpoint to Redlands,CA - setViewpoint(Viewpoint(34.058, -117.195, 5e4)) - } - - lifecycleScope.launch { - // check if the map has loaded successfully - map.load().onSuccess { - // capture and collect when the user taps on the screen - mapView.onSingleTapConfirmed.collect { event -> - event.mapPoint?.let { point -> onGeoViewTapped(point) } - } - }.onFailure { - // if map load failed, show the error - showError("Error Loading Map", mapView) - } - } - } - - /** - * Handles the SingleTapEvent by drawing a marker, re-centering the mapView to the marker - * and performs a Spatial reference transformation of the tapped Location - * using GeometryEngine and displays the result. - */ - private suspend fun onGeoViewTapped(point: Point) { - // update the marker location to where the user tapped on the map - markerGraphic.geometry = point - // set mapview to recenter to the tapped location - mapView.setViewpointGeometry(point.extent) - // project the web mercator location into a WGS84 - val projectedPoint = GeometryEngine.projectOrNull(point, SpatialReference.wgs84()) - // build and display the projection result as a string - infoTextView.text = getString( - R.string.projection_info_text, - point.toDisplayFormat(), - projectedPoint?.toDisplayFormat() - ) - } - - /** - * Displays an error onscreen - */ - private fun showError(message: String, view: View) { - Log.e(localClassName, message) - Snackbar.make(view, message, Snackbar.LENGTH_SHORT).show() - } -} - -/** - * Extension function for the Point type that returns - * a float-precision formatted string suitable for display - */ -private fun Point.toDisplayFormat() = - "${String.format(Locale.getDefault(),"%.5f", x)}, ${String.format(Locale.getDefault(),"%.5f", y)}" diff --git a/project-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml b/project-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/project-geometry/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/project-geometry/src/main/res/drawable/ic_launcher_background.xml b/project-geometry/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/project-geometry/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/project-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/project-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/project-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/project-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/project-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/project-geometry/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/project-geometry/src/main/res/mipmap-hdpi/ic_launcher.png b/project-geometry/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/project-geometry/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png b/project-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/project-geometry/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-mdpi/ic_launcher.png b/project-geometry/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/project-geometry/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png b/project-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/project-geometry/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png b/project-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/project-geometry/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/project-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/project-geometry/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png b/project-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/project-geometry/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/project-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/project-geometry/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/project-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/project-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/project-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/project-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/project-geometry/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/project-geometry/src/main/res/values/strings.xml b/project-geometry/src/main/res/values/strings.xml deleted file mode 100644 index 384a91a47..000000000 --- a/project-geometry/src/main/res/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Project geometry - Coordinates - Tap to begin - Original: %1s\nProjected: %2s - diff --git a/query-feature-table/.gitignore b/query-feature-table/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/query-feature-table/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/query-feature-table/build.gradle.kts b/query-feature-table/build.gradle.kts deleted file mode 100644 index dcb034a7f..000000000 --- a/query-feature-table/build.gradle.kts +++ /dev/null @@ -1,54 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.queryfeaturetable" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - compose = true - buildConfig = true - } - - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() - } - - namespace = "com.esri.arcgismaps.sample.queryfeaturetable" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.core.ktx) - implementation(libs.androidx.lifecycle.runtime.ktx) - implementation(libs.androidx.lifecycle.viewmodel.compose) - implementation(libs.androidx.activity.compose) - // Jetpack Compose Bill of Materials - implementation(platform(libs.androidx.compose.bom)) - // Jetpack Compose dependencies - implementation(libs.androidx.compose.ui) - implementation(libs.androidx.compose.material3) - implementation(libs.androidx.compose.ui.tooling) - implementation(libs.androidx.compose.ui.tooling.preview) - implementation(project(":samples-lib")) - // Toolkit dependencies - implementation(platform(libs.arcgis.maps.kotlin.toolkit.bom)) - implementation(libs.arcgis.maps.kotlin.toolkit.geoview.compose) -} diff --git a/query-feature-table/proguard-rules.pro b/query-feature-table/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/query-feature-table/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/query-feature-table/src/main/AndroidManifest.xml b/query-feature-table/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/query-feature-table/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/query-feature-table/src/main/java/com/esri/arcgismaps/sample/queryfeaturetable/MainActivity.kt b/query-feature-table/src/main/java/com/esri/arcgismaps/sample/queryfeaturetable/MainActivity.kt deleted file mode 100644 index c1938f4b4..000000000 --- a/query-feature-table/src/main/java/com/esri/arcgismaps/sample/queryfeaturetable/MainActivity.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.queryfeaturetable - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Surface -import androidx.compose.runtime.Composable -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.esri.arcgismaps.sample.sampleslib.theme.SampleAppTheme -import com.esri.arcgismaps.sample.queryfeaturetable.screens.MainScreen - -class MainActivity : ComponentActivity() { - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - - setContent { - SampleAppTheme { - QueryFeatureTableApp() - } - } - } - - @Composable - private fun QueryFeatureTableApp() { - Surface( - color = MaterialTheme.colorScheme.background - ) { - MainScreen( - sampleName = getString(R.string.app_name) - ) - } - } -} diff --git a/query-feature-table/src/main/res/drawable-v24/ic_launcher_foreground.xml b/query-feature-table/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/query-feature-table/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/query-feature-table/src/main/res/drawable/ic_launcher_background.xml b/query-feature-table/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/query-feature-table/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/query-feature-table/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/query-feature-table/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/query-feature-table/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/query-feature-table/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/query-feature-table/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/query-feature-table/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/query-feature-table/src/main/res/mipmap-hdpi/ic_launcher.png b/query-feature-table/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/query-feature-table/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-hdpi/ic_launcher_round.png b/query-feature-table/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/query-feature-table/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-mdpi/ic_launcher.png b/query-feature-table/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/query-feature-table/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-mdpi/ic_launcher_round.png b/query-feature-table/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/query-feature-table/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-xhdpi/ic_launcher.png b/query-feature-table/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/query-feature-table/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/query-feature-table/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/query-feature-table/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-xxhdpi/ic_launcher.png b/query-feature-table/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/query-feature-table/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/query-feature-table/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/query-feature-table/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/query-feature-table/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/query-feature-table/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/query-feature-table/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/query-feature-table/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/query-feature-table/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-feature-table/src/main/res/values/strings.xml b/query-feature-table/src/main/res/values/strings.xml deleted file mode 100644 index a67aa2905..000000000 --- a/query-feature-table/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - Query feature table - https://services.arcgis.com/jIL9msH9OI208GCb/arcgis/rest/services/USA_Daytime_Population_2016/FeatureServer/0 - diff --git a/query-features-with-arcade-expression/.gitignore b/query-features-with-arcade-expression/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/query-features-with-arcade-expression/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/query-features-with-arcade-expression/build.gradle.kts b/query-features-with-arcade-expression/build.gradle.kts deleted file mode 100644 index d524e8465..000000000 --- a/query-features-with-arcade-expression/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.queryfeatureswitharcadeexpression" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.queryfeatureswitharcadeexpression" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/query-features-with-arcade-expression/proguard-rules.pro b/query-features-with-arcade-expression/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/query-features-with-arcade-expression/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/query-features-with-arcade-expression/src/main/AndroidManifest.xml b/query-features-with-arcade-expression/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/query-features-with-arcade-expression/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/query-features-with-arcade-expression/src/main/java/com/esri/arcgismaps/sample/queryfeatureswitharcadeexpression/MainActivity.kt b/query-features-with-arcade-expression/src/main/java/com/esri/arcgismaps/sample/queryfeatureswitharcadeexpression/MainActivity.kt deleted file mode 100644 index b24e9ee7b..000000000 --- a/query-features-with-arcade-expression/src/main/java/com/esri/arcgismaps/sample/queryfeatureswitharcadeexpression/MainActivity.kt +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright 2023 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.queryfeatureswitharcadeexpression - -import android.graphics.BitmapFactory -import android.graphics.drawable.BitmapDrawable -import android.os.Bundle -import android.util.Log -import android.view.View -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.arcade.ArcadeEvaluator -import com.arcgismaps.arcade.ArcadeExpression -import com.arcgismaps.arcade.ArcadeProfile -import com.arcgismaps.data.ArcGISFeature -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.layers.Layer -import com.arcgismaps.mapping.symbology.PictureMarkerSymbol -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.arcgismaps.mapping.view.ScreenCoordinate -import com.arcgismaps.portal.Portal -import com.arcgismaps.mapping.PortalItem -import com.esri.arcgismaps.sample.queryfeatureswitharcadeexpression.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - private val infoTextView by lazy { - activityMainBinding.infoTextView - } - - // progress indicator - private val progressBar by lazy { - activityMainBinding.progressBar - } - - // setup the red pin marker image as a bitmap drawable - private val markerDrawable: BitmapDrawable by lazy { - // load the bitmap from resources and create a drawable - val bitmap = BitmapFactory.decodeResource(resources, R.drawable.map_pin_symbol) - BitmapDrawable(resources, bitmap) - } - - // setup the red pin marker as a Graphic - private val markerGraphic: Graphic by lazy { - // creates a symbol from the marker drawable - val markerSymbol = PictureMarkerSymbol.createWithImage(markerDrawable).apply { - // resize the symbol into a smaller size - width = 30f - height = 30f - // offset in +y axis so the marker spawned is right on the touch point - offsetY = 25f - } - // create the graphic from the symbol - Graphic(symbol = markerSymbol) - } - - // create a graphic overlay - private val graphicsOverlay = GraphicsOverlay() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - // create a portal item with the itemId of the web map - val portal = Portal("https://www.arcgis.com/") - val portalItem = PortalItem(portal, "539d93de54c7422f88f69bfac2aebf7d") - // create and add a map with with portal item - val map = ArcGISMap(portalItem) - // add the marker graphic to the graphics overlay - graphicsOverlay.graphics.add(markerGraphic) - mapView.apply { - this.map = map - // add the graphics overlay to the MapView - graphicsOverlays.add(graphicsOverlay) - } - - lifecycleScope.launch { - // show an error and return if the map load failed - map.load().onFailure { - return@launch showError("Error loading map:${it.message}") - } - - // get the RPD Beats layer from the map's operational layers - val policeBeatsLayer = map.operationalLayers.firstOrNull { layer -> - layer.id == "RPD_Reorg_9254" - } ?: return@launch showError("Error finding RPD Beats layer") - - // capture and collect when the user taps on the screen - mapView.onSingleTapConfirmed.collect { event -> - // update the marker location to where the user tapped on the map - event.mapPoint?.let { point -> - markerGraphic.geometry = point - mapView.setViewpointCenter(point) - } - // evaluate an Arcade expression on the tapped screen coordinate - evaluateArcadeExpression(event.screenCoordinate, map, policeBeatsLayer) - } - } - } - - /** - * Evaluates an Arcade expression that returns crime in the last 60 days at the tapped - * [screenCoordinate] on the [map] with the [policeBeatsLayer] and displays the result - * in a textview - */ - private suspend fun evaluateArcadeExpression( - screenCoordinate: ScreenCoordinate, - map: ArcGISMap, - policeBeatsLayer: Layer - ) { - // show the progress indicator as the Arcade evaluation can take time to complete - progressBar.visibility = View.VISIBLE - // identify the layer and its elements based on the position tapped on the mapView and - // get the result - val result = mapView.identifyLayer( - layer = policeBeatsLayer, - screenCoordinate = screenCoordinate, - tolerance = 12.0, - returnPopupsOnly = false - ) - // get the result as an IdentifyLayerResult - val identifyLayerResult = result.getOrElse { error -> - // if the identifyLayer operation failed show an error and return - showError("Error identifying layer:${error.message}") - // reset the text view to show its default text - infoTextView.text = getString(R.string.tap_to_begin) - // dismiss the progress indicator - progressBar.visibility = View.GONE - return - } - // if there are no geoElements identified - if (identifyLayerResult.geoElements.isEmpty()) { - // since the layer is a feature layer, display that no features were found - infoTextView.text = getString(R.string.no_features_found) - // dismiss the progress indicator - progressBar.visibility = View.GONE - return - } - // get the first identified GeoElement as an ArcGISFeature - val identifiedFeature = identifyLayerResult.geoElements.first() as ArcGISFeature - // create a string containing the Arcade expression - val expressionValue = - "var crimes = FeatureSetByName(\$map, 'Crime in the last 60 days');\n" + - "return Count(Intersects(\$feature, crimes));" - // create an ArcadeExpression using the string expression - val arcadeExpression = ArcadeExpression(expressionValue) - // create an ArcadeEvaluator with the ArcadeExpression and an ArcadeProfile - val arcadeEvaluator = ArcadeEvaluator(arcadeExpression, ArcadeProfile.FormCalculation) - // create a map of profile variables with the feature and map as key value pairs - val profileVariables = mapOf("\$feature" to identifiedFeature, "\$map" to map) - // evaluate using the previously set profile variables and get the result - val evaluationResult = arcadeEvaluator.evaluate(profileVariables) - // get the result as an ArcadeEvaluationResult - val arcadeEvaluationResult = evaluationResult.getOrElse { error -> - // if the evaluation failed show an error and return - showError("Error evaluating Arcade expression:${error.message}") - // reset the text view to show its default text - infoTextView.text = getString(R.string.tap_to_begin) - // dismiss the progress indicator - progressBar.visibility = View.GONE - return - } - // get the crimes count from the arcadeEvaluationResult as a numerical double value - val crimesCount = arcadeEvaluationResult.result as Double - // display this result in a textview - infoTextView.text = getString(R.string.crime_info_text, crimesCount.toInt()) - // hide the progress indicator - progressBar.visibility = View.GONE - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/query-features-with-arcade-expression/src/main/res/drawable-v24/ic_launcher_foreground.xml b/query-features-with-arcade-expression/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/query-features-with-arcade-expression/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/query-features-with-arcade-expression/src/main/res/drawable/ic_launcher_background.xml b/query-features-with-arcade-expression/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/query-features-with-arcade-expression/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/query-features-with-arcade-expression/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/query-features-with-arcade-expression/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/query-features-with-arcade-expression/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/query-features-with-arcade-expression/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-hdpi/ic_launcher.png b/query-features-with-arcade-expression/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-hdpi/ic_launcher_round.png b/query-features-with-arcade-expression/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-mdpi/ic_launcher.png b/query-features-with-arcade-expression/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-mdpi/ic_launcher_round.png b/query-features-with-arcade-expression/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-xhdpi/ic_launcher.png b/query-features-with-arcade-expression/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/query-features-with-arcade-expression/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-xxhdpi/ic_launcher.png b/query-features-with-arcade-expression/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/query-features-with-arcade-expression/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/query-features-with-arcade-expression/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/query-features-with-arcade-expression/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/query-features-with-arcade-expression/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/query-features-with-arcade-expression/src/main/res/values/strings.xml b/query-features-with-arcade-expression/src/main/res/values/strings.xml deleted file mode 100644 index 4a1c44c8e..000000000 --- a/query-features-with-arcade-expression/src/main/res/values/strings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - Query features with arcade expression - Tap to begin - Crime in the last 60 days: %1d - No features found - diff --git a/render-multilayer-symbols/.gitignore b/render-multilayer-symbols/.gitignore deleted file mode 100644 index 796b96d1c..000000000 --- a/render-multilayer-symbols/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build diff --git a/render-multilayer-symbols/build.gradle.kts b/render-multilayer-symbols/build.gradle.kts deleted file mode 100644 index c85164204..000000000 --- a/render-multilayer-symbols/build.gradle.kts +++ /dev/null @@ -1,38 +0,0 @@ -plugins { - id("com.android.application") - id("org.jetbrains.kotlin.android") -} - -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - applicationId = "com.esri.arcgismaps.sample.rendermultilayersymbols" - minSdk = libs.versions.minSdk.get().toInt() - targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = libs.versions.versionCode.get().toInt() - versionName = libs.versions.versionName.get() - buildConfigField("String", "API_KEY", project.properties["API_KEY"].toString()) - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - dataBinding = true - buildConfig = true - } - - namespace = "com.esri.arcgismaps.sample.rendermultilayersymbols" -} - -dependencies { - // lib dependencies from rootProject build.gradle.kts - implementation(libs.androidx.constraintlayout) - implementation(libs.android.material) - implementation(project(":samples-lib")) -} diff --git a/render-multilayer-symbols/proguard-rules.pro b/render-multilayer-symbols/proguard-rules.pro deleted file mode 100644 index 2f9dc5a47..000000000 --- a/render-multilayer-symbols/proguard-rules.pro +++ /dev/null @@ -1,21 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle.kts. -# -# 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 diff --git a/render-multilayer-symbols/src/main/AndroidManifest.xml b/render-multilayer-symbols/src/main/AndroidManifest.xml deleted file mode 100644 index c6647b46d..000000000 --- a/render-multilayer-symbols/src/main/AndroidManifest.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/render-multilayer-symbols/src/main/java/com/esri/arcgismaps/sample/rendermultilayersymbols/MainActivity.kt b/render-multilayer-symbols/src/main/java/com/esri/arcgismaps/sample/rendermultilayersymbols/MainActivity.kt deleted file mode 100644 index c3e4f1d29..000000000 --- a/render-multilayer-symbols/src/main/java/com/esri/arcgismaps/sample/rendermultilayersymbols/MainActivity.kt +++ /dev/null @@ -1,518 +0,0 @@ -/* Copyright 2022 Esri - * - * 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. - * - */ - -package com.esri.arcgismaps.sample.rendermultilayersymbols - -import android.graphics.BitmapFactory -import android.graphics.drawable.BitmapDrawable -import android.os.Bundle -import android.util.Log -import androidx.appcompat.app.AppCompatActivity -import androidx.databinding.DataBindingUtil -import androidx.lifecycle.lifecycleScope -import com.arcgismaps.ApiKey -import com.arcgismaps.ArcGISEnvironment -import com.arcgismaps.Color -import com.arcgismaps.geometry.Envelope -import com.arcgismaps.geometry.Geometry -import com.arcgismaps.geometry.Point -import com.arcgismaps.geometry.PolygonBuilder -import com.arcgismaps.geometry.PolylineBuilder -import com.arcgismaps.geometry.SpatialReference -import com.arcgismaps.mapping.ArcGISMap -import com.arcgismaps.mapping.BasemapStyle -import com.arcgismaps.mapping.symbology.DashGeometricEffect -import com.arcgismaps.mapping.symbology.HatchFillSymbolLayer -import com.arcgismaps.mapping.symbology.HorizontalAlignment -import com.arcgismaps.mapping.symbology.MultilayerPointSymbol -import com.arcgismaps.mapping.symbology.MultilayerPolygonSymbol -import com.arcgismaps.mapping.symbology.MultilayerPolylineSymbol -import com.arcgismaps.mapping.symbology.MultilayerSymbol -import com.arcgismaps.mapping.symbology.PictureMarkerSymbolLayer -import com.arcgismaps.mapping.symbology.SolidFillSymbolLayer -import com.arcgismaps.mapping.symbology.SolidStrokeSymbolLayer -import com.arcgismaps.mapping.symbology.StrokeSymbolLayerCapStyle -import com.arcgismaps.mapping.symbology.SymbolAnchor -import com.arcgismaps.mapping.symbology.SymbolAnchorPlacementMode -import com.arcgismaps.mapping.symbology.SymbolLayer -import com.arcgismaps.mapping.symbology.TextSymbol -import com.arcgismaps.mapping.symbology.VectorMarkerSymbolElement -import com.arcgismaps.mapping.symbology.VectorMarkerSymbolLayer -import com.arcgismaps.mapping.symbology.VerticalAlignment -import com.arcgismaps.mapping.view.Graphic -import com.arcgismaps.mapping.view.GraphicsOverlay -import com.esri.arcgismaps.sample.rendermultilayersymbols.databinding.ActivityMainBinding -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.launch - -private val Color.Companion.blue: Color - get() { - return fromRgba(0, 0, 255, 255) - } - -private val Color.Companion.yellow: Color - get() { - return fromRgba(255, 255, 0, 255) - } - -private val Color.Companion.magenta: Color - get() { - return fromRgba(255, 0, 255, 255) - } - -// define offset used to keep a consistent distance between symbols in the same column -private const val OFFSET = 20.0 - -class MainActivity : AppCompatActivity() { - - // set up data binding for the activity - private val activityMainBinding: ActivityMainBinding by lazy { - DataBindingUtil.setContentView(this, R.layout.activity_main) - } - - private val mapView by lazy { - activityMainBinding.mapView - } - - // define the graphics overlay to add the multilayer symbols - private var graphicsOverlay: GraphicsOverlay = GraphicsOverlay() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - // authentication with an API key or named user is - // required to access basemaps and other location services - ArcGISEnvironment.apiKey = ApiKey.create(BuildConfig.API_KEY) - lifecycle.addObserver(mapView) - - mapView.apply { - // set the map to be displayed in the layout's map view - mapView.map = ArcGISMap(BasemapStyle.ArcGISLightGray) - // add the graphic overlay to the map view - graphicsOverlays.add(graphicsOverlay) - } - - // create labels to go above each category of graphic - addTextGraphics() - - // create picture marker symbols, from URI or local cache - addImageGraphics() - - // add graphics with simple vector marker symbol elements (MultilayerPoint Simple Markers on app UI) - val solidFillSymbolLayer = SolidFillSymbolLayer(Color.red) - val multilayerPolygonSymbol = MultilayerPolygonSymbol(listOf(solidFillSymbolLayer)) - val solidStrokeSymbolLayer = - SolidStrokeSymbolLayer(1.0, Color.red, listOf(DashGeometricEffect())) - val multilayerPolylineSymbol = MultilayerPolylineSymbol(listOf(solidStrokeSymbolLayer)) - - // define vector element for a diamond, triangle and cross - val diamondGeometry = - Geometry.fromJsonOrNull("{\"rings\":[[[0.0,2.5],[2.5,0.0],[0.0,-2.5],[-2.5,0.0],[0.0,2.5]]]}") - val triangleGeometry = - Geometry.fromJsonOrNull("{\"rings\":[[[0.0,5.0],[5,-5.0],[-5,-5.0],[0.0,5.0]]]}") - val crossGeometry = - Geometry.fromJsonOrNull("{\"paths\":[[[-1,1],[0,0],[1,-1]],[[1,1],[0,0],[-1,-1]]]}") - - if (diamondGeometry == null || triangleGeometry == null || crossGeometry == null) { - showError("Error reading geometry from json") - return - } - - // add red diamond graphic - addGraphicsWithVectorMarkerSymbolElements( - multilayerPolygonSymbol, diamondGeometry, 0.0 - ) - // add red triangle graphic - addGraphicsWithVectorMarkerSymbolElements( - multilayerPolygonSymbol, triangleGeometry, OFFSET - ) - // add red cross graphic - addGraphicsWithVectorMarkerSymbolElements( - multilayerPolylineSymbol, crossGeometry, 2 * OFFSET - ) - - // create line marker symbols with short dash dot dot - addLineGraphicsWithMarkerSymbols( - listOf(4.0, 6.0, 0.5, 6.0, 0.5, 6.0), 0.0 - ) - // create line marker symbol with short dash - addLineGraphicsWithMarkerSymbols( - listOf(4.0, 6.0), OFFSET - ) - // create line marker symbol with dash dot dot - addLineGraphicsWithMarkerSymbols( - listOf(7.0, 9.0, 0.5, 9.0), 2 * OFFSET - ) - - // create polygon marker symbols - // cross-hatched diagonal lines - addPolygonGraphicsWithMarkerSymbols( - listOf(-45.0, 45.0), 0.0 - ) - // hatched diagonal lines - addPolygonGraphicsWithMarkerSymbols( - listOf(-45.0), OFFSET - ) - // hatched vertical lines - addPolygonGraphicsWithMarkerSymbols( - listOf(90.0), 2 * OFFSET - ) - - // define vector element for a hexagon which will be used as the basis of a complex point - val complexPointGeometry = - Geometry.fromJsonOrNull("{\"rings\":[[[-2.89,5.0],[2.89,5.0],[5.77,0.0],[2.89,-5.0],[-2.89,-5.0],[-5.77,0.0],[-2.89,5.0]]]}") - - // create the more complex multilayer graphics: a point, polygon, and polyline - complexPointGeometry?.let { addComplexPoint(it) } - addComplexPolygon() - addComplexPolyline() - } - - /** - * Creates the label graphics to be displayed above each category of symbol, - * and adds them to the graphics overlay. - */ - private fun addTextGraphics() { - graphicsOverlay.graphics.addAll( - listOf( - Graphic( - Point(-150.0, 50.0, SpatialReference.wgs84()), - getTextSymbol("MultilayerPoint\nSimple Markers") - ), Graphic( - Point(-80.0, 50.0, SpatialReference.wgs84()), - getTextSymbol("MultilayerPoint\nPicture Markers") - ), Graphic( - Point(0.0, 50.0, SpatialReference.wgs84()), - getTextSymbol("Multilayer\nPolyline") - ), Graphic( - Point(65.0, 50.0, SpatialReference.wgs84()), - getTextSymbol("Multilayer\nPolygon") - ), Graphic( - Point(130.0, 50.0, SpatialReference.wgs84()), - getTextSymbol("Multilayer\nComplex Symbols") - ) - ) - ) - } - - /** - * @return the TextSymbol with the [text] to be displayed on the map. - */ - private fun getTextSymbol(text: String): TextSymbol { - val textSymbol = TextSymbol( - text, Color.black, 10F, HorizontalAlignment.Center, VerticalAlignment.Middle - ) - // give the text symbol a white background - textSymbol.backgroundColor = Color.white - return textSymbol - } - - /** - * Create picture marker symbols from online URI and local cache. - */ - private fun addImageGraphics() { - // URI of image to display - val blueTentImageURI = "https://static.arcgis.com/images/Symbols/OutdoorRecreation/Camping.png" - // load the PictureMarkerSymbolLayer using the image URI - val pictureMarkerFromUri = PictureMarkerSymbolLayer(blueTentImageURI) - // add loaded layer to the map - addGraphicFromPictureMarkerSymbolLayer(pictureMarkerFromUri, 0.0) - // load blue pin from as a bitmap - val bitmap = BitmapFactory.decodeResource(resources, R.drawable.blue_pin) - // load the PictureMarkerSymbolLayer using the bitmap drawable - val pictureMarkerFromCache = PictureMarkerSymbolLayer.createWithImage(BitmapDrawable(resources, bitmap)) - // add loaded layer to the map - addGraphicFromPictureMarkerSymbolLayer(pictureMarkerFromCache, 40.0) - } - - /** - * Loads a picture marker symbol layer and after it has loaded, creates a new multilayer point symbol from it. - * A graphic is created from the multilayer point symbol and added to the graphics overlay. - * - * The [pictureMarkerSymbolLayer] to be loaded. - * The [offset] value used to keep a consistent distance between symbols in the same column. - */ - private fun addGraphicFromPictureMarkerSymbolLayer( - pictureMarkerSymbolLayer: PictureMarkerSymbolLayer, offset: Double - ) = lifecycleScope.launch { - // wait for the picture marker symbol layer to load and check it has loaded - pictureMarkerSymbolLayer.load().getOrElse { - showError("Picture marker symbol layer failed to load: ${it.message}") - } - // set the size of the layer and create a new multilayer point symbol from it - pictureMarkerSymbolLayer.size = 40.0 - val multilayerPointSymbol = MultilayerPointSymbol(listOf(pictureMarkerSymbolLayer)) - // create location for the symbol - val point = Point(-80.0, 20.0 - offset, SpatialReference.wgs84()) - - // create graphic with the location and symbol and add it to the graphics overlay - val graphic = Graphic(point, multilayerPointSymbol) - graphicsOverlay.graphics.add(graphic) - } - - /** - * Adds new graphics constructed from multilayer point symbols. - * - * The [multilayerSymbol] to construct the vector marker symbol element with. - * The input [geometry] for the vector marker symbol element. - * [offset] the value used to keep a consistent distance between symbols in the same column. - */ - private fun addGraphicsWithVectorMarkerSymbolElements( - multilayerSymbol: MultilayerSymbol, geometry: Geometry, offset: Double - ) { - // define a vector element and create a new multilayer point symbol from it - val vectorMarkerSymbolElement = VectorMarkerSymbolElement(geometry, multilayerSymbol) - val vectorMarkerSymbolLayer = VectorMarkerSymbolLayer(listOf(vectorMarkerSymbolElement)) - val multilayerPointSymbol = MultilayerPointSymbol(listOf(vectorMarkerSymbolLayer)) - - // create point graphic using the symbol and add it to the graphics overlay - val graphic = - Graphic(Point(-150.0, 20 - offset, SpatialReference.wgs84()), multilayerPointSymbol) - graphicsOverlay.graphics.add(graphic) - } - - /** - * Adds new graphics constructed from multilayer polyline symbols. - * - * The pattern of [dashSpacing] dots/dashes used by the line and - * [offset] the value used to keep a consistent distance between symbols in the same column. - */ - private fun addLineGraphicsWithMarkerSymbols(dashSpacing: List, offset: Double) { - // create a dash effect from the provided values - val dashGeometricEffect = DashGeometricEffect(dashSpacing) - // create stroke used by line symbols - val solidStrokeSymbolLayer = SolidStrokeSymbolLayer( - 3.0, Color.red, listOf(dashGeometricEffect) - ).apply { - capStyle = StrokeSymbolLayerCapStyle.Round - } - // create a polyline for the multilayer polyline symbol - val polylineBuilder = PolylineBuilder(SpatialReference.wgs84()) { - addPoint(Point(-30.0, 20 - offset)) - addPoint(Point(30.0, 20 - offset)) - } - // create a multilayer polyline symbol from the solidStrokeSymbolLayer - val multilayerPolylineSymbol = MultilayerPolylineSymbol(listOf(solidStrokeSymbolLayer)) - // create a polyline graphic with geometry using the symbol created above, and add it to the graphics overlay - graphicsOverlay.graphics.add( - Graphic( - polylineBuilder.toGeometry(), multilayerPolylineSymbol - ) - ) - } - - /** - * Adds new graphics constructed from multilayer polygon symbols. - * - * Takes a list containing the [angles] at which to draw fill lines within the polygon and - * [offset] the value used to keep a consistent distance between symbols in the same column. - */ - private fun addPolygonGraphicsWithMarkerSymbols(angles: List, offset: Double) { - val polygonBuilder = PolygonBuilder(SpatialReference.wgs84()) { - addPoint(Point(60.0, 25 - offset)) - addPoint(Point(70.0, 25 - offset)) - addPoint(Point(70.0, 20 - offset)) - addPoint(Point(60.0, 20 - offset)) - } - - // create a stroke symbol layer to be used by patterns - val strokeForHatches = SolidStrokeSymbolLayer(2.0, Color.red, listOf(DashGeometricEffect())) - - // create a stroke symbol layer to be used as an outline for aforementioned patterns - val strokeForOutline = - SolidStrokeSymbolLayer(1.0, Color.black, listOf(DashGeometricEffect())) - - // create a list to hold all necessary symbol layers - at least one for patterns and one for an outline at the end - val symbolLayerList = mutableListOf() - - // for each angle, create a symbol layer using the pattern stroke, with hatched lines at the given angle - for (i in angles.indices) { - val hatchFillSymbolLayer = HatchFillSymbolLayer( - MultilayerPolylineSymbol(listOf(strokeForHatches)), angles[i] - ) - // define separation distance for lines and add them to the symbol layer list - hatchFillSymbolLayer.separation = 9.0 - symbolLayerList.add(hatchFillSymbolLayer) - } - - // assign the outline layer to the last element of the symbol layer list - symbolLayerList.add(strokeForOutline) - // create a multilayer polygon symbol from the symbol layer list - val multilayerPolygonSymbol = - MultilayerPolygonSymbol(symbolLayerList) - // create a polygon graphic with geometry using the symbol created above, and add it to the graphics overlay - val graphic = Graphic(polygonBuilder.toGeometry(), multilayerPolygonSymbol) - graphicsOverlay.graphics.add(graphic) - } - - /** - * Creates a complex point from multiple symbol layers and a provided geometry. - * @param complexPointGeometry a base geometry upon which other symbol layers are drawn. - */ - private fun addComplexPoint(complexPointGeometry: Geometry) { - // create marker layers for complex point - val orangeSquareVectorMarkerLayer: VectorMarkerSymbolLayer = - getLayerForComplexPoint(Color.cyan, Color.blue, 11.0) - val blackSquareVectorMarkerLayer: VectorMarkerSymbolLayer = - getLayerForComplexPoint(Color.black, Color.cyan, 6.0) - val purpleSquareVectorMarkerLayer: VectorMarkerSymbolLayer = getLayerForComplexPoint( - Color.transparent, Color.magenta, 14.0 - ) - - // set anchors for marker layers - orangeSquareVectorMarkerLayer.anchor = - SymbolAnchor(-4.0, -6.0, SymbolAnchorPlacementMode.Absolute) - blackSquareVectorMarkerLayer.anchor = - SymbolAnchor(2.0, 1.0, SymbolAnchorPlacementMode.Absolute) - purpleSquareVectorMarkerLayer.anchor = - SymbolAnchor(4.0, 2.0, SymbolAnchorPlacementMode.Absolute) - - // create a yellow hexagon with a black outline - val yellowFillLayer = SolidFillSymbolLayer(Color.yellow) - val blackOutline = SolidStrokeSymbolLayer(2.0, Color.black, listOf(DashGeometricEffect())) - val hexagonVectorElement = VectorMarkerSymbolElement( - complexPointGeometry, MultilayerPolylineSymbol(listOf(yellowFillLayer, blackOutline)) - ) - val hexagonVectorMarkerLayer = VectorMarkerSymbolLayer(listOf(hexagonVectorElement)).apply { - size = 35.0 - } - - // create the multilayer point symbol - val multilayerPointSymbol = MultilayerPointSymbol( - listOf( - hexagonVectorMarkerLayer, - orangeSquareVectorMarkerLayer, - blackSquareVectorMarkerLayer, - purpleSquareVectorMarkerLayer - ) - ) - - // create the multilayer point graphic using the symbols created above - val complexPointGraphic = - Graphic(Point(130.0, 20.0, SpatialReference.wgs84()), multilayerPointSymbol) - graphicsOverlay.graphics.add(complexPointGraphic) - } - - /** - * Creates a symbol layer for use in the composition of a complex point - * using [fillColor], [outlineColor] as colors and the [size] of the symbol - * Then return a [VectorMarkerSymbolLayer] of the created symbol. - */ - private fun getLayerForComplexPoint( - fillColor: Color, outlineColor: Color, size: Double - ): VectorMarkerSymbolLayer { - // create the fill layer and outline - val fillLayer = SolidFillSymbolLayer(fillColor) - val outline = SolidStrokeSymbolLayer( - 2.0, outlineColor, listOf(DashGeometricEffect()) - ) - // create a geometry from an envelope - val geometry = Envelope( - Point(-0.5, -0.5, SpatialReference.wgs84()), Point(0.5, 0.5, SpatialReference.wgs84()) - ) - //create a symbol element using the geometry, fill layer, and outline - val vectorMarkerSymbolElement = VectorMarkerSymbolElement( - geometry, MultilayerPolygonSymbol(listOf(fillLayer, outline)) - ) - // create a symbol layer containing just the above symbol element, set its size, and return it - val vectorMarkerSymbolLayer = - VectorMarkerSymbolLayer(listOf(vectorMarkerSymbolElement)).apply { - this.size = size - } - return vectorMarkerSymbolLayer - } - - /** - * Adds a complex polygon generated with multiple symbol layers. - */ - private fun addComplexPolygon() { - // create the multilayer polygon symbol - val multilayerPolygonSymbol = MultilayerPolygonSymbol(getLayersForComplexPolys(true)) - // create the polygon - val polygonBuilder = PolygonBuilder(SpatialReference.wgs84()) { - addPoint(Point(120.0, 0.0)) - addPoint(Point(140.0, 0.0)) - addPoint(Point(140.0, -10.0)) - addPoint(Point(120.0, -10.0)) - } - // create a multilayer polygon graphic with geometry using the symbols - // created above and add it to the graphics overlay - graphicsOverlay.graphics.add( - Graphic( - polygonBuilder.toGeometry(), multilayerPolygonSymbol - ) - ) - } - - /** - * Adds a complex polyline generated with multiple symbol layers. - */ - private fun addComplexPolyline() { - // create the multilayer polyline symbol - val multilayerPolylineSymbol = MultilayerPolylineSymbol(getLayersForComplexPolys(false)) - val polylineBuilder = PolylineBuilder(SpatialReference.wgs84()) { - addPoint(Point(120.0, -25.0)) - addPoint(Point(140.0, -25.0)) - } - // create the multilayer polyline graphic with geometry using the symbols created above and add it to the graphics overlay - graphicsOverlay.graphics.add( - Graphic( - polylineBuilder.toGeometry(), multilayerPolylineSymbol - ) - ) - } - - /** - * Generates and returns the symbol layers used by the addComplexPolygon and addComplexPolyline methods. - * [includeRedFill] indicates whether to include the red fill needed by the complex polygon. - * @return a list of symbol layers including the necessary effects. - */ - private fun getLayersForComplexPolys(includeRedFill: Boolean): List { - // create a black dash effect - val blackDashes = SolidStrokeSymbolLayer( - 1.0, Color.black, listOf(DashGeometricEffect(listOf(5.0, 3.0))) - ).apply { - capStyle = StrokeSymbolLayerCapStyle.Square - } - - // create a black outline - val blackOutline = SolidStrokeSymbolLayer( - 7.0, Color.black, listOf(DashGeometricEffect()) - ).apply { - capStyle = StrokeSymbolLayerCapStyle.Round - } - - // create a yellow stroke inside - val yellowStroke = SolidStrokeSymbolLayer( - 5.0, Color.yellow, listOf(DashGeometricEffect()) - ).apply { - capStyle = StrokeSymbolLayerCapStyle.Round - } - - return if (includeRedFill) { - // create a red filling for the polygon - val redFillLayer = SolidFillSymbolLayer(Color.red) - listOf(redFillLayer, blackOutline, yellowStroke, blackDashes) - } else { - listOf(blackOutline, yellowStroke, blackDashes) - } - } - - private fun showError(message: String) { - Log.e(localClassName, message) - Snackbar.make(mapView, message, Snackbar.LENGTH_SHORT).show() - } -} diff --git a/render-multilayer-symbols/src/main/res/drawable-v24/ic_launcher_foreground.xml b/render-multilayer-symbols/src/main/res/drawable-v24/ic_launcher_foreground.xml deleted file mode 100644 index c7bd21dbd..000000000 --- a/render-multilayer-symbols/src/main/res/drawable-v24/ic_launcher_foreground.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - diff --git a/render-multilayer-symbols/src/main/res/drawable/ic_launcher_background.xml b/render-multilayer-symbols/src/main/res/drawable/ic_launcher_background.xml deleted file mode 100644 index 6d8cae103..000000000 --- a/render-multilayer-symbols/src/main/res/drawable/ic_launcher_background.xml +++ /dev/null @@ -1,170 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/render-multilayer-symbols/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/render-multilayer-symbols/src/main/res/mipmap-anydpi-v26/ic_launcher.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/render-multilayer-symbols/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/render-multilayer-symbols/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/render-multilayer-symbols/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml deleted file mode 100644 index 6b78462d6..000000000 --- a/render-multilayer-symbols/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/render-multilayer-symbols/src/main/res/mipmap-hdpi/ic_launcher.png b/render-multilayer-symbols/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a2f590828..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-hdpi/ic_launcher_round.png b/render-multilayer-symbols/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 1b5239980..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-mdpi/ic_launcher.png b/render-multilayer-symbols/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index ff10afd6e..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-mdpi/ic_launcher_round.png b/render-multilayer-symbols/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 115a4c768..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-xhdpi/ic_launcher.png b/render-multilayer-symbols/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index dcd3cd808..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/render-multilayer-symbols/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 459ca609d..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-xxhdpi/ic_launcher.png b/render-multilayer-symbols/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 8ca12fe02..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/render-multilayer-symbols/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index 8e19b410a..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/render-multilayer-symbols/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index b824ebdd4..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/render-multilayer-symbols/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4c19a13c2..000000000 Binary files a/render-multilayer-symbols/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/render-multilayer-symbols/src/main/res/values/strings.xml b/render-multilayer-symbols/src/main/res/values/strings.xml deleted file mode 100644 index 8edc79c1b..000000000 --- a/render-multilayer-symbols/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - Render multilayer symbols - diff --git a/samples-lib/build.gradle.kts b/samples-lib/build.gradle.kts index 5bf54b61f..f577f4811 100644 --- a/samples-lib/build.gradle.kts +++ b/samples-lib/build.gradle.kts @@ -1,36 +1,25 @@ plugins { - id("com.android.library") - id("org.jetbrains.kotlin.android") + alias(libs.plugins.arcgismaps.android.library) + alias(libs.plugins.arcgismaps.android.library.compose) + alias(libs.plugins.gradle.secrets) } -android { - compileSdk = libs.versions.compileSdk.get().toInt() - - defaultConfig { - minSdk = libs.versions.minSdk.get().toInt() - consumerProguardFiles("consumer-rules.pro") - } - - buildTypes { - release { - isMinifyEnabled = false - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - } - } +secrets { + // this file doesn't contain secrets, it just provides defaults which can be committed into git. + defaultPropertiesFileName = "secrets.defaults.properties" +} +android { + namespace = "com.esri.arcgismaps.sample.sampleslib" buildFeatures { - dataBinding = true buildConfig = true - compose = true - } - composeOptions { - kotlinCompilerExtensionVersion = libs.versions.kotlinCompilerExt.get() + dataBinding = true } - - namespace = "com.esri.arcgismaps.sample.sampleslib" } dependencies { + // Only module specific dependencies needed here + // lib dependencies from rootProject build.gradle implementation(libs.androidx.lifecycle.runtime.ktx) implementation(libs.androidx.constraintlayout) @@ -46,5 +35,7 @@ dependencies { implementation(libs.androidx.compose.material3) implementation(libs.androidx.compose.ui.tooling) implementation(libs.androidx.compose.ui.tooling.preview) + implementation(libs.arcgis.maps.kotlin) } + diff --git a/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/DownloaderActivity.kt b/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/DownloaderActivity.kt index 1f8591c1a..13d26bc31 100644 --- a/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/DownloaderActivity.kt +++ b/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/DownloaderActivity.kt @@ -102,7 +102,7 @@ abstract class DownloaderActivity : AppCompatActivity() { * at the [destinationPath]. The downloadManager clears the directory if user chooses * to re-download the provisioned data. */ - private suspend fun sampleDownloadManager( + private fun sampleDownloadManager( provisionURLs: List, destinationPath: String, ): Flow = flow { diff --git a/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/components/BottomSheet.kt b/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/components/BottomSheet.kt index fc88228ac..c05478008 100644 --- a/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/components/BottomSheet.kt +++ b/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/components/BottomSheet.kt @@ -22,7 +22,6 @@ import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment diff --git a/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/components/JobLoadingDialog.kt b/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/components/JobLoadingDialog.kt index 258d7b980..f57ae457e 100644 --- a/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/components/JobLoadingDialog.kt +++ b/samples-lib/src/main/java/com/esri/arcgismaps/sample/sampleslib/components/JobLoadingDialog.kt @@ -84,7 +84,8 @@ fun JobLoadingDialog( ) // row of progress indicator and percentage text. Row( - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp) ) { // set ease animation when progress state changes val progressAnimation by animateFloatAsState( @@ -96,13 +97,13 @@ fun JobLoadingDialog( ) // create the linear progress indicator LinearProgressIndicator( + modifier = Modifier.fillMaxWidth().weight(1f), progress = { progressAnimation }, ) // progress percentage text Text( text = "$progress%", - textAlign = TextAlign.Center, - modifier = Modifier.fillMaxWidth() + textAlign = TextAlign.Center ) } diff --git a/samples-lib/src/main/res/drawable/arcgis_maps_sdks_64.xml b/samples-lib/src/main/res/drawable/arcgis_maps_sdks_64.xml new file mode 100644 index 000000000..8390b45f6 --- /dev/null +++ b/samples-lib/src/main/res/drawable/arcgis_maps_sdks_64.xml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples-lib/src/main/res/drawable/arcgis_sdk_foreground.xml b/samples-lib/src/main/res/drawable/arcgis_sdk_foreground.xml new file mode 100644 index 000000000..25cbc9858 --- /dev/null +++ b/samples-lib/src/main/res/drawable/arcgis_sdk_foreground.xml @@ -0,0 +1,9 @@ + + + diff --git a/samples-lib/src/main/res/mipmap-anydpi-v26/arcgis_sdk.xml b/samples-lib/src/main/res/mipmap-anydpi-v26/arcgis_sdk.xml new file mode 100644 index 000000000..8dcfe3274 --- /dev/null +++ b/samples-lib/src/main/res/mipmap-anydpi-v26/arcgis_sdk.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/samples-lib/src/main/res/mipmap-anydpi-v26/arcgis_sdk_round.xml b/samples-lib/src/main/res/mipmap-anydpi-v26/arcgis_sdk_round.xml new file mode 100644 index 000000000..8dcfe3274 --- /dev/null +++ b/samples-lib/src/main/res/mipmap-anydpi-v26/arcgis_sdk_round.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk.webp b/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk.webp new file mode 100644 index 000000000..7d9d890bc Binary files /dev/null and b/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk.webp differ diff --git a/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk_background.webp b/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk_background.webp new file mode 100644 index 000000000..2844fe0a2 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk_background.webp differ diff --git a/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk_round.webp b/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk_round.webp new file mode 100644 index 000000000..7d9d890bc Binary files /dev/null and b/samples-lib/src/main/res/mipmap-hdpi/arcgis_sdk_round.webp differ diff --git a/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk.webp b/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk.webp new file mode 100644 index 000000000..3af13249e Binary files /dev/null and b/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk.webp differ diff --git a/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk_background.webp b/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk_background.webp new file mode 100644 index 000000000..dc0fb4029 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk_background.webp differ diff --git a/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk_round.webp b/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk_round.webp new file mode 100644 index 000000000..3af13249e Binary files /dev/null and b/samples-lib/src/main/res/mipmap-mdpi/arcgis_sdk_round.webp differ diff --git a/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk.webp b/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk.webp new file mode 100644 index 000000000..cc4a2b5d9 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk.webp differ diff --git a/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk_background.webp b/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk_background.webp new file mode 100644 index 000000000..af87f8dd0 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk_background.webp differ diff --git a/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk_round.webp b/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk_round.webp new file mode 100644 index 000000000..cc4a2b5d9 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xhdpi/arcgis_sdk_round.webp differ diff --git a/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk.webp b/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk.webp new file mode 100644 index 000000000..f0e02de89 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk.webp differ diff --git a/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk_background.webp b/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk_background.webp new file mode 100644 index 000000000..52f290a15 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk_background.webp differ diff --git a/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk_round.webp b/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk_round.webp new file mode 100644 index 000000000..f0e02de89 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xxhdpi/arcgis_sdk_round.webp differ diff --git a/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk.webp b/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk.webp new file mode 100644 index 000000000..457e9ebb9 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk.webp differ diff --git a/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk_background.webp b/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk_background.webp new file mode 100644 index 000000000..9e1d3b862 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk_background.webp differ diff --git a/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk_round.webp b/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk_round.webp new file mode 100644 index 000000000..457e9ebb9 Binary files /dev/null and b/samples-lib/src/main/res/mipmap-xxxhdpi/arcgis_sdk_round.webp differ diff --git a/samples-lib/src/main/res/values-v35/styles.xml b/samples-lib/src/main/res/values-v35/styles.xml new file mode 100644 index 000000000..0e8d457ea --- /dev/null +++ b/samples-lib/src/main/res/values-v35/styles.xml @@ -0,0 +1,6 @@ + + + + diff --git a/samples-lib/src/main/res/values/styles.xml b/samples-lib/src/main/res/values/styles.xml index 0e0431d19..263e655a2 100644 --- a/samples-lib/src/main/res/values/styles.xml +++ b/samples-lib/src/main/res/values/styles.xml @@ -59,7 +59,7 @@ - +