diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 364c27b1..47e540da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,9 @@ jobs: distribution: 'adopt' java-version: '21' - name: Build ApiDemos - run: cd Maps3DSamples/ApiDemos && ./gradlew buildDebugPreBundle + run: ./gradlew :Maps3DSamples:ApiDemos:java-app:assembleDebug :Maps3DSamples:ApiDemos:kotlin-app:assembleDebug + - name: Run ApiDemos Unit Tests + run: ./gradlew :Maps3DSamples:ApiDemos:java-app:testDebugUnitTest :Maps3DSamples:ApiDemos:kotlin-app:testDebugUnitTest build-advanced: runs-on: ubuntu-latest @@ -52,4 +54,6 @@ jobs: distribution: 'adopt' java-version: '21' - name: Build advanced - run: cd Maps3DSamples/advanced && ./gradlew buildDebugPreBundle \ No newline at end of file + run: ./gradlew :Maps3DSamples:advanced:app:assembleDebug + - name: Run advanced Unit Tests + run: ./gradlew :Maps3DSamples:advanced:app:testDebugUnitTest diff --git a/LOG.md b/LOG.md deleted file mode 100644 index 400812ef..00000000 --- a/LOG.md +++ /dev/null @@ -1,8 +0,0 @@ - -### Task: Implement Monster Tour and Long Press popup (Project: Maps3D Samples) -* **Start:** [Unknown] (Branch: main) -* **End:** $(date +"%I:%M:%S %p %Z") -* **Time Spent:** [Unknown] -* **Purpose:** The user wanted to automate the traversal of the various monster markers in the map, and add a quick-select popup menu to the random button, configuring properties like altitude mode via JSON. -* **Summary of Work:** Shifted marker definitions to a central `monsters.json` data file. Implemented an asynchronous touring sequence in both Kotlin (Coroutines) and Java (Handlers) to fly to, orbit, and display info popovers for each character. Wired up a standard `android.widget.PopupMenu` for the random button long-press. Adjusted altitude modes in JSON. -* **Status:** **[IN PROGRESS (Unmerged)]** diff --git a/Maps3DSamples/ApiDemos/java-app/build.gradle.kts b/Maps3DSamples/ApiDemos/java-app/build.gradle.kts index a3132ef5..74f68eb4 100644 --- a/Maps3DSamples/ApiDemos/java-app/build.gradle.kts +++ b/Maps3DSamples/ApiDemos/java-app/build.gradle.kts @@ -14,59 +14,7 @@ * limitations under the License. */ -import java.util.Properties -import org.gradle.api.GradleException - -// Check for secrets.properties file and valid API key before proceeding with build tasks. -val secretsFile = rootProject.file("secrets.properties") -val isCI = System.getenv("CI")?.toBoolean() ?: false - -if (!isCI) { - val requestedTasks = gradle.startParameter.taskNames - if (requestedTasks.isEmpty() && !secretsFile.exists()) { - // It's likely an IDE sync if no tasks are specified, so just issue a warning. - println("Warning: secrets.properties not found. Gradle sync may succeed, but building/running the app will fail.") - } else if (requestedTasks.isNotEmpty()) { - val buildTaskKeywords = listOf("build", "install", "assemble") - val isBuildTask = requestedTasks.any { task -> - buildTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val testTaskKeywords = listOf("test", "report", "lint") - val isTestTask = requestedTasks.any { task -> - testTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val isDebugTask = requestedTasks.any { task -> - task.contains("Debug", ignoreCase = true) || task.contains("installAndLaunch", ignoreCase = true) - } - - if (isBuildTask && !isTestTask && isDebugTask) { - val defaultsFile = rootProject.file("local.defaults.properties") - val requiredKeysMessage = if (defaultsFile.exists()) { - defaultsFile.readText() - } else { - "MAPS3D_API_KEY=" - } - - if (!secretsFile.exists()) { - throw GradleException("secrets.properties file not found. Please create a 'secrets.properties' file in the root project directory with the following content:\n\n$requiredKeysMessage") - } - - val secrets = Properties() - secretsFile.inputStream().use { secrets.load(it) } - val apiKey = secrets.getProperty("MAPS3D_API_KEY") - - if (apiKey.isNullOrBlank() || !apiKey.matches(Regex("^AIza[a-zA-Z0-9_-]{35}$"))) { - throw GradleException("Invalid or missing MAPS3D_API_KEY in secrets.properties. Please provide a valid Google Maps API key (starts with 'AIza').") - } - } - } -} +val isCI = rootProject.extra["isCI"] as? Boolean ?: false plugins { alias(libs.plugins.android.application) @@ -88,7 +36,13 @@ android { versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + + if (isCI) { + manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + manifestPlaceholders["PLACES_API_KEY"] = "DEFAULT_API_KEY" + } + + buildConfigField("Boolean", "IS_CI", "${isCI}") } buildTypes { diff --git a/Maps3DSamples/ApiDemos/java-app/src/main/java/com/example/maps3djava/Maps3DJavaApplication.java b/Maps3DSamples/ApiDemos/java-app/src/main/java/com/example/maps3djava/Maps3DJavaApplication.java index aafef684..21bab65b 100644 --- a/Maps3DSamples/ApiDemos/java-app/src/main/java/com/example/maps3djava/Maps3DJavaApplication.java +++ b/Maps3DSamples/ApiDemos/java-app/src/main/java/com/example/maps3djava/Maps3DJavaApplication.java @@ -58,6 +58,9 @@ public void onCreate() { * incorrectly configured, and a RuntimeException is thrown. */ private void checkApiKey() { + if (BuildConfig.IS_CI) { + return; + } try { ApplicationInfo appInfo = getPackageManager().getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA); diff --git a/Maps3DSamples/ApiDemos/kotlin-app/build.gradle.kts b/Maps3DSamples/ApiDemos/kotlin-app/build.gradle.kts index af79b14f..5c8d8aaa 100644 --- a/Maps3DSamples/ApiDemos/kotlin-app/build.gradle.kts +++ b/Maps3DSamples/ApiDemos/kotlin-app/build.gradle.kts @@ -14,60 +14,7 @@ * limitations under the License. */ -import org.gradle.api.GradleException -import java.io.File -import java.util.Properties - -// Check for secrets.properties file and valid API key before proceeding with build tasks. -val secretsFile = rootProject.file("secrets.properties") -val isCI = System.getenv("CI")?.toBoolean() ?: false - -if (!isCI) { - val requestedTasks = gradle.startParameter.taskNames - if (requestedTasks.isEmpty() && !secretsFile.exists()) { - // It's likely an IDE sync if no tasks are specified, so just issue a warning. - println("Warning: secrets.properties not found. Gradle sync may succeed, but building/running the app will fail.") - } else if (requestedTasks.isNotEmpty()) { - val buildTaskKeywords = listOf("build", "install", "assemble") - val isBuildTask = requestedTasks.any { task -> - buildTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val testTaskKeywords = listOf("test", "report", "lint") - val isTestTask = requestedTasks.any { task -> - testTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val isDebugTask = requestedTasks.any { task -> - task.contains("Debug", ignoreCase = true) || task.contains("installAndLaunch", ignoreCase = true) - } - - if (isBuildTask && !isTestTask && isDebugTask) { - val defaultsFile = rootProject.file("local.defaults.properties") - val requiredKeysMessage = if (defaultsFile.exists()) { - defaultsFile.readText() - } else { - "MAPS3D_API_KEY=" - } - - if (!secretsFile.exists()) { - throw GradleException("secrets.properties file not found. Please create a 'secrets.properties' file in the root project directory with the following content:\n\n$requiredKeysMessage") - } - - val secrets = Properties() - secretsFile.inputStream().use { secrets.load(it) } - val apiKey = secrets.getProperty("MAPS3D_API_KEY") - - if (apiKey.isNullOrBlank() || !apiKey.matches(Regex("^AIza[a-zA-Z0-9_-]{35}$"))) { - throw GradleException("Invalid or missing MAPS3D_API_KEY in secrets.properties. Please provide a valid Google Maps API key (starts with 'AIza').") - } - } - } -} +val isCI = rootProject.extra["isCI"] as? Boolean ?: false plugins { alias(libs.plugins.android.application) @@ -91,7 +38,13 @@ android { versionName = "1.8.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + + if (isCI) { + manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + manifestPlaceholders["PLACES_API_KEY"] = "DEFAULT_API_KEY" + } + + buildConfigField("Boolean", "IS_CI", "${isCI}") } buildTypes { diff --git a/Maps3DSamples/ApiDemos/kotlin-app/src/main/java/com/example/maps3dkotlin/Maps3DKotlinApplication.kt b/Maps3DSamples/ApiDemos/kotlin-app/src/main/java/com/example/maps3dkotlin/Maps3DKotlinApplication.kt index 4f1da61e..26872d3c 100644 --- a/Maps3DSamples/ApiDemos/kotlin-app/src/main/java/com/example/maps3dkotlin/Maps3DKotlinApplication.kt +++ b/Maps3DSamples/ApiDemos/kotlin-app/src/main/java/com/example/maps3dkotlin/Maps3DKotlinApplication.kt @@ -49,6 +49,9 @@ class Maps3DKotlinApplication : Application() { * incorrectly configured, and a RuntimeException is thrown. */ private fun checkApiKey() { + if (BuildConfig.IS_CI) { + return + } try { val appInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA) diff --git a/Maps3DSamples/advanced/app/build.gradle.kts b/Maps3DSamples/advanced/app/build.gradle.kts index f356ea89..c9224bfa 100644 --- a/Maps3DSamples/advanced/app/build.gradle.kts +++ b/Maps3DSamples/advanced/app/build.gradle.kts @@ -14,59 +14,7 @@ * limitations under the License. */ -import java.util.Properties -import org.gradle.api.GradleException - -// Check for secrets.properties file and valid API key before proceeding with build tasks. -val secretsFile = rootProject.file("secrets.properties") -val isCI = System.getenv("CI")?.toBoolean() ?: false - -if (!isCI) { - val requestedTasks = gradle.startParameter.taskNames - if (requestedTasks.isEmpty() && !secretsFile.exists()) { - // It's likely an IDE sync if no tasks are specified, so just issue a warning. - println("Warning: secrets.properties not found. Gradle sync may succeed, but building/running the app will fail.") - } else if (requestedTasks.isNotEmpty()) { - val buildTaskKeywords = listOf("build", "install", "assemble") - val isBuildTask = requestedTasks.any { task -> - buildTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val testTaskKeywords = listOf("test", "report", "lint") - val isTestTask = requestedTasks.any { task -> - testTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val isDebugTask = requestedTasks.any { task -> - task.contains("Debug", ignoreCase = true) || task.contains("installAndLaunch", ignoreCase = true) - } - - if (isBuildTask && !isTestTask && isDebugTask) { - val defaultsFile = rootProject.file("local.defaults.properties") - val requiredKeysMessage = if (defaultsFile.exists()) { - defaultsFile.readText() - } else { - "MAPS3D_API_KEY=" - } - - if (!secretsFile.exists()) { - throw GradleException("secrets.properties file not found. Please create a 'secrets.properties' file in the root project directory with the following content:\n\n$requiredKeysMessage") - } - - val secrets = Properties() - secretsFile.inputStream().use { secrets.load(it) } - val apiKey = secrets.getProperty("MAPS3D_API_KEY") - - if (apiKey.isNullOrBlank() || !apiKey.matches(Regex("^AIza[a-zA-Z0-9_-]{35}$"))) { - throw GradleException("Invalid or missing MAPS3D_API_KEY in secrets.properties. Please provide a valid Google Maps API key (starts with 'AIza').") - } - } - } -} +val isCI = rootProject.extra["isCI"] as? Boolean ?: false plugins { alias(libs.plugins.android.application) @@ -94,7 +42,12 @@ android { versionName = "1.8.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" - manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + + if (isCI) { + manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + manifestPlaceholders["PLACES_API_KEY"] = "DEFAULT_API_KEY" + } + buildConfigField("Boolean", "IS_CI", "${isCI}") } buildTypes { @@ -178,4 +131,4 @@ tasks.register("installAndLaunch") { commandLine("adb", "shell", "am", "start", "-n", "com.example.advancedmaps3dsamples/.MainActivity") } -tasks.register("prepareKotlinBuildScriptModel"){} \ No newline at end of file +tasks.register("prepareKotlinBuildScriptModel"){} diff --git a/PlacesUIKit3D/build.gradle.kts b/PlacesUIKit3D/build.gradle.kts index adf9abcd..32c6ee29 100644 --- a/PlacesUIKit3D/build.gradle.kts +++ b/PlacesUIKit3D/build.gradle.kts @@ -14,6 +14,8 @@ * limitations under the License. */ +val isCI = rootProject.extra["isCI"] as? Boolean ?: false + // The `plugins` block is where we apply Gradle plugins to this module. // Plugins add new tasks and configurations to our build process. plugins { @@ -57,6 +59,13 @@ android { // Specifies the instrumentation runner for running Android tests. testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + if (isCI) { + manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + manifestPlaceholders["PLACES_API_KEY"] = "DEFAULT_API_KEY" + } + + buildConfigField("Boolean", "IS_CI", "${isCI}") } buildTypes { diff --git a/PlacesUIKit3D/src/main/java/com/example/placesuikit3d/Maps3DPlacesApplication.kt b/PlacesUIKit3D/src/main/java/com/example/placesuikit3d/Maps3DPlacesApplication.kt index e54e5163..63f797b6 100644 --- a/PlacesUIKit3D/src/main/java/com/example/placesuikit3d/Maps3DPlacesApplication.kt +++ b/PlacesUIKit3D/src/main/java/com/example/placesuikit3d/Maps3DPlacesApplication.kt @@ -32,6 +32,9 @@ class Maps3DPlacesApplication : Application() { } private fun initializePlaces() { + if (BuildConfig.IS_CI) { + return + } val apiKey = BuildConfig.PLACES_API_KEY if (apiKey == null || apiKey.isBlank() || apiKey == "DEFAULT_API_KEY") { @@ -58,6 +61,9 @@ class Maps3DPlacesApplication : Application() { * incorrectly configured, and a RuntimeException is thrown. */ private fun checkApiKey() { + if (BuildConfig.IS_CI) { + return + } try { val appInfo = packageManager.getApplicationInfo(packageName, PackageManager.GET_META_DATA) diff --git a/build.gradle.kts b/build.gradle.kts index 793378a9..f63217f5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,76 @@ +/* + * Copyright 2026 Google LLC + * + * 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. + */ + +import java.util.Properties + plugins { alias(libs.plugins.spotless) apply false } + +// Evaluate if we are in a CI environment +val isCI = System.getenv("CI")?.toBoolean() ?: false + +// Share the isCI flag with all subprojects via Gradle's extra properties +extra["isCI"] = isCI + +if (!isCI) { + val secretsFile = file("secrets.properties") + val requestedTasks = gradle.startParameter.taskNames + + if (requestedTasks.isEmpty() && !secretsFile.exists()) { + // It's likely an IDE sync if no tasks are specified, so just issue a warning. + println("Warning: secrets.properties not found. Gradle sync may succeed, but building/running the app will fail.") + } else if (requestedTasks.isNotEmpty()) { + val buildTaskKeywords = setOf("build", "install", "assemble") + val testTaskKeywords = setOf("test", "report", "lint") + + val isBuildTask = requestedTasks.any { name -> + buildTaskKeywords.any { kw -> name.contains(kw, ignoreCase = true) } + } + val isTestTask = requestedTasks.any { name -> + testTaskKeywords.any { kw -> name.contains(kw, ignoreCase = true) } + } + val isDebugTask = requestedTasks.any { task -> + task.contains("Debug", ignoreCase = true) || task.contains("installAndLaunch", ignoreCase = true) + } + + if (isBuildTask && !isTestTask && isDebugTask) { + val defaultsFile = file("local.defaults.properties") + val requiredKeysMessage = if (defaultsFile.exists()) { + defaultsFile.readText() + } else { + "MAPS3D_API_KEY=\nPLACES_API_KEY=" + } + + if (!secretsFile.exists()) { + throw GradleException("secrets.properties file not found. Please create a 'secrets.properties' file in the root project directory with the following content:\n\n$requiredKeysMessage") + } + + val secrets = Properties() + secretsFile.inputStream().use { secrets.load(it) } + val mapsApiKey = secrets.getProperty("MAPS3D_API_KEY") + val placesApiKey = secrets.getProperty("PLACES_API_KEY") + + if (mapsApiKey.isNullOrBlank() || !mapsApiKey.matches(Regex("^AIza[a-zA-Z0-9_-]{35}$"))) { + throw GradleException("Invalid or missing MAPS3D_API_KEY in secrets.properties. Please provide a valid Google Maps API key (starts with 'AIza').") + } + + if (placesApiKey.isNullOrBlank() || !placesApiKey.matches(Regex("^AIza[a-zA-Z0-9_-]{35}$"))) { + throw GradleException("Invalid or missing PLACES_API_KEY in secrets.properties. Please provide a valid Google Places API key (starts with 'AIza').") + } + } + } +} diff --git a/snippets/java-app/build.gradle.kts b/snippets/java-app/build.gradle.kts index 342ec7cb..6eae12cd 100644 --- a/snippets/java-app/build.gradle.kts +++ b/snippets/java-app/build.gradle.kts @@ -14,59 +14,7 @@ * limitations under the License. */ -import java.util.Properties -import org.gradle.api.GradleException - -// Check for secrets.properties file and valid API key before proceeding with build tasks. -val secretsFile = rootProject.file("secrets.properties") -val isCI = System.getenv("CI")?.toBoolean() ?: false - -if (!isCI) { - val requestedTasks = gradle.startParameter.taskNames - if (requestedTasks.isEmpty() && !secretsFile.exists()) { - // It's likely an IDE sync if no tasks are specified, so just issue a warning. - println("Warning: secrets.properties not found. Gradle sync may succeed, but building/running the app will fail.") - } else if (requestedTasks.isNotEmpty()) { - val buildTaskKeywords = listOf("build", "install", "assemble") - val isBuildTask = requestedTasks.any { task -> - buildTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val testTaskKeywords = listOf("test", "report", "lint") - val isTestTask = requestedTasks.any { task -> - testTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val isDebugTask = requestedTasks.any { task -> - task.contains("Debug", ignoreCase = true) || task.contains("installAndLaunch", ignoreCase = true) - } - - if (isBuildTask && !isTestTask && isDebugTask) { - val defaultsFile = rootProject.file("local.defaults.properties") - val requiredKeysMessage = if (defaultsFile.exists()) { - defaultsFile.readText() - } else { - "MAPS3D_API_KEY=" - } - - if (!secretsFile.exists()) { - throw GradleException("secrets.properties file not found. Please create a 'secrets.properties' file in the root project directory with the following content:\n\n$requiredKeysMessage") - } - - val secrets = Properties() - secretsFile.inputStream().use { secrets.load(it) } - val apiKey = secrets.getProperty("MAPS3D_API_KEY") - - if (apiKey.isNullOrBlank() || !apiKey.matches(Regex("^AIza[a-zA-Z0-9_-]{35}$"))) { - throw GradleException("Invalid or missing MAPS3D_API_KEY in secrets.properties. Please provide a valid Google Maps API key (starts with 'AIza').") - } - } - } -} +val isCI = rootProject.extra["isCI"] as? Boolean ?: false plugins { alias(libs.plugins.android.application) @@ -86,6 +34,12 @@ android { versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + if (isCI) { + manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + manifestPlaceholders["PLACES_API_KEY"] = "DEFAULT_API_KEY" + } + buildConfigField("Boolean", "IS_CI", "${isCI}") } buildTypes { diff --git a/snippets/kotlin-app/build.gradle.kts b/snippets/kotlin-app/build.gradle.kts index 7f641cec..39cc595f 100644 --- a/snippets/kotlin-app/build.gradle.kts +++ b/snippets/kotlin-app/build.gradle.kts @@ -14,59 +14,7 @@ * limitations under the License. */ -import java.util.Properties -import org.gradle.api.GradleException - -// Check for secrets.properties file and valid API key before proceeding with build tasks. -val secretsFile = rootProject.file("secrets.properties") -val isCI = System.getenv("CI")?.toBoolean() ?: false - -if (!isCI) { - val requestedTasks = gradle.startParameter.taskNames - if (requestedTasks.isEmpty() && !secretsFile.exists()) { - // It's likely an IDE sync if no tasks are specified, so just issue a warning. - println("Warning: secrets.properties not found. Gradle sync may succeed, but building/running the app will fail.") - } else if (requestedTasks.isNotEmpty()) { - val buildTaskKeywords = listOf("build", "install", "assemble") - val isBuildTask = requestedTasks.any { task -> - buildTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val testTaskKeywords = listOf("test", "report", "lint") - val isTestTask = requestedTasks.any { task -> - testTaskKeywords.any { keyword -> - task.contains(keyword, ignoreCase = true) - } - } - - val isDebugTask = requestedTasks.any { task -> - task.contains("Debug", ignoreCase = true) || task.contains("installAndLaunch", ignoreCase = true) - } - - if (isBuildTask && !isTestTask && isDebugTask) { - val defaultsFile = rootProject.file("local.defaults.properties") - val requiredKeysMessage = if (defaultsFile.exists()) { - defaultsFile.readText() - } else { - "MAPS3D_API_KEY=" - } - - if (!secretsFile.exists()) { - throw GradleException("secrets.properties file not found. Please create a 'secrets.properties' file in the root project directory with the following content:\n\n$requiredKeysMessage") - } - - val secrets = Properties() - secretsFile.inputStream().use { secrets.load(it) } - val apiKey = secrets.getProperty("MAPS3D_API_KEY") - - if (apiKey.isNullOrBlank() || !apiKey.matches(Regex("^AIza[a-zA-Z0-9_-]{35}$"))) { - throw GradleException("Invalid or missing MAPS3D_API_KEY in secrets.properties. Please provide a valid Google Maps API key (starts with 'AIza').") - } - } - } -} +val isCI = rootProject.extra["isCI"] as? Boolean ?: false plugins { alias(libs.plugins.android.application) @@ -87,6 +35,12 @@ android { versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + + if (isCI) { + manifestPlaceholders["MAPS3D_API_KEY"] = "DEFAULT_API_KEY" + manifestPlaceholders["PLACES_API_KEY"] = "DEFAULT_API_KEY" + } + buildConfigField("Boolean", "IS_CI", "${isCI}") } buildTypes {