From de23ecd099cecfb77f79b5156c5dd2820474aacb Mon Sep 17 00:00:00 2001 From: dkhawk <107309+dkhawk@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:41:28 -0700 Subject: [PATCH 1/7] refactor: standardize build configuration and SDK versions - Extract `compileSdk`, `minSdk`, `targetSdk` to version catalog and set `compileSdk`/`targetSdk` to 36. - Fix build deprecations: replace `buildDir` with `layout.buildDirectory` and move `kotlinOptions` to `compilerOptions`. - Update Kotlin to 2.3.0 and Gradle to 8.13.2. - Switch app module to use local project dependencies (`:maps-rx`, `:places-rx`) instead of version catalog artifacts. - Remove unused `ExampleInstrumentedTest`. - Update .gitignore to exclude secrets.properties. --- .gitignore | 3 +- app/build.gradle.kts | 25 +++++++----- .../rx/demo/ExampleInstrumentedTest.kt | 38 ------------------- gradle/libs.versions.toml | 12 +++--- maps-rx/build.gradle.kts | 16 +++++--- places-rx/build.gradle.kts | 14 ++++--- shared/build.gradle.kts | 14 ++++--- 7 files changed, 49 insertions(+), 73 deletions(-) delete mode 100644 app/src/androidTest/java/com/google/maps/android/rx/demo/ExampleInstrumentedTest.kt diff --git a/.gitignore b/.gitignore index 69f06a0..d12d7d5 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ secure.properties # This covers new IDEs, like Antigravity .vscode/ -**/bin/ \ No newline at end of file +**/bin/ +/secrets.properties diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ef66262..0204399 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -22,20 +22,20 @@ plugins { android { lint { - sarifOutput = file("$buildDir/reports/lint-results.sarif") + sarifOutput = layout.buildDirectory.file("reports/lint-results.sarif").get().asFile } buildFeatures { buildConfig = true } - compileSdk = 35 + compileSdk = libs.versions.compileSdk.get().toInt() namespace = "com.google.maps.android.rx.demo" defaultConfig { applicationId = "com.google.maps.android.rx.demo" - minSdk = 24 - targetSdk = 35 + minSdk = libs.versions.minSdk.get().toInt() + targetSdk = libs.versions.targetSdk.get().toInt() versionCode = 1 versionName = "1.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" @@ -52,18 +52,16 @@ android { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } - - kotlinOptions { - jvmTarget = "1.8" - } } dependencies { + implementation(project(":shared")) + // RxJava bindings for the Maps SDK - implementation(libs.mapsRx) + implementation(project(":maps-rx")) // RxJava bindings for the Places SDK - implementation(libs.placesRx) + implementation(project(":places-rx")) // It is recommended to also include the latest Maps SDK, Places SDK and RxJava so you // have the latest features and bug fixes. @@ -80,5 +78,12 @@ dependencies { } secrets { + propertiesFileName = "secrets.properties" defaultPropertiesFileName = "local.defaults.properties" } + +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) + } +} diff --git a/app/src/androidTest/java/com/google/maps/android/rx/demo/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/google/maps/android/rx/demo/ExampleInstrumentedTest.kt deleted file mode 100644 index 06ddfdf..0000000 --- a/app/src/androidTest/java/com/google/maps/android/rx/demo/ExampleInstrumentedTest.kt +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2021 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. - -package com.google.maps.android.rx.demo - -import androidx.test.platform.app.InstrumentationRegistry -import androidx.test.ext.junit.runners.AndroidJUnit4 - -import org.junit.Test -import org.junit.runner.RunWith - -import org.junit.Assert.* - -/** - * Instrumented test, which will execute on an Android device. - * - * See [testing documentation](http://d.android.com/tools/testing). - */ -@RunWith(AndroidJUnit4::class) -class ExampleInstrumentedTest { - @Test - fun useAppContext() { - // Context of the app under test. - val appContext = InstrumentationRegistry.getInstrumentation().targetContext - assertEquals("com.google.maps.android.rx.demo", appContext.packageName) - } -} \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 52bee65..56381ec 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,8 +1,12 @@ [versions] -kotlin = "2.2.21" +compileSdk = "36" +minSdk = "24" +targetSdk = "36" + +kotlin = "2.3.0" rxandroid = "3.0.2" rxjava = "3.1.12" -gradle = "8.13.1" +gradle = "8.13.2" jacoco-android = "0.2.1" dokka-gradle-plugin = "2.1.0" secrets-gradle-plugin = "2.0.1" @@ -14,13 +18,9 @@ material = "1.13.0" rxLifecycle = "4.0.2" mapsKtx = "5.2.1" volley = "1.2.1" -mapsRx = "1.0.0" -placesRx = "1.0.0" gradleMavenPublishPlugin = "0.35.0" [libraries] -mapsRx = { module = "com.google.maps.android:maps-rx", version.ref = "mapsRx" } -placesRx = { module = "com.google.maps.android:places-rx", version.ref = "placesRx" } jetbrainsKotlinStdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } kotlinStdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" } rxJava = { module = "io.reactivex.rxjava3:rxjava", version.ref = "rxjava" } diff --git a/maps-rx/build.gradle.kts b/maps-rx/build.gradle.kts index dc5a76a..40c64b6 100644 --- a/maps-rx/build.gradle.kts +++ b/maps-rx/build.gradle.kts @@ -1,3 +1,5 @@ +import org.gradle.kotlin.dsl.dependencies + /* * Copyright 2025 Google LLC * @@ -16,15 +18,15 @@ android { lint { - sarifOutput = file("$buildDir/reports/lint-results.sarif") + sarifOutput = layout.buildDirectory.file("reports/lint-results.sarif").get().asFile } namespace = "com.google.maps.android.rx.maps" - compileSdk = 35 + compileSdk = libs.versions.compileSdk.get().toInt() defaultConfig { - minSdk = 24 + minSdk = libs.versions.minSdk.get().toInt() testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } @@ -33,10 +35,12 @@ android { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } +} - kotlinOptions { - jvmTarget = "1.8" - freeCompilerArgs += "-Xexplicit-api=strict" +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) + freeCompilerArgs.add("-Xexplicit-api=strict") } } diff --git a/places-rx/build.gradle.kts b/places-rx/build.gradle.kts index d9179b2..b58588e 100644 --- a/places-rx/build.gradle.kts +++ b/places-rx/build.gradle.kts @@ -16,15 +16,15 @@ android { lint { - sarifOutput = file("$buildDir/reports/lint-results.sarif") + sarifOutput = layout.buildDirectory.file("reports/lint-results.sarif").get().asFile } namespace = "com.google.maps.android.rx.places" - compileSdk = 35 + compileSdk = libs.versions.compileSdk.get().toInt() defaultConfig { - minSdk = 24 + minSdk = libs.versions.minSdk.get().toInt() testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } @@ -33,10 +33,12 @@ android { sourceCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8 } +} - kotlinOptions { - jvmTarget = "1.8" - freeCompilerArgs += "-Xexplicit-api=strict" +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) + freeCompilerArgs.add("-Xexplicit-api=strict") } } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index 2ba8ff6..9ee19d4 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -21,21 +21,23 @@ plugins { android { lint { - sarifOutput = file("$buildDir/reports/lint-results.sarif") + sarifOutput = layout.buildDirectory.file("reports/lint-results.sarif").get().asFile } namespace = "com.google.maps.android.rx.shared" - compileSdk = 35 + compileSdk = libs.versions.compileSdk.get().toInt() defaultConfig { - minSdk = 24 + minSdk = libs.versions.minSdk.get().toInt() testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles("consumer-rules.pro") } +} - kotlinOptions { - jvmTarget = "1.8" - freeCompilerArgs += "-Xexplicit-api=strict" +tasks.withType().configureEach { + compilerOptions { + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) + freeCompilerArgs.add("-Xexplicit-api=strict") } } From f80874ab9b275d5f2186b07ee52d78271c9182a9 Mon Sep 17 00:00:00 2001 From: dkhawk <107309+dkhawk@users.noreply.github.com> Date: Mon, 22 Dec 2025 11:56:56 -0700 Subject: [PATCH 2/7] feat: enhance demo app and add testing infrastructure - Fix lint/deprecation warnings in MainActivity and PlacesRx - Expand demo app with FindCurrentPlace and FetchPhoto UI - Update build files to JDK 17 - Add testing dependencies (JUnit, Mockito, Mockk) - Add initial (ignored) unit tests for maps-rx and places-rx --- app/build.gradle.kts | 12 +- app/src/main/AndroidManifest.xml | 3 + .../maps/android/rx/demo/MainActivity.kt | 179 +++++++++++++++--- app/src/main/res/layout/activity_main.xml | 40 ++++ gradle/libs.versions.toml | 17 +- maps-rx/build.gradle.kts | 14 +- .../google/maps/android/rx/maps/MapsRxTest.kt | 38 ++++ .../org.mockito.plugins.MockMaker | 1 + places-rx/build.gradle.kts | 14 +- .../rx/places/PlacesClientFetchPhotoSingle.kt | 4 + .../PlacesClientFindCurrentPlaceSingle.kt | 4 + .../maps/android/rx/places/PlacesRxTest.kt | 46 +++++ shared/build.gradle.kts | 14 +- 13 files changed, 349 insertions(+), 37 deletions(-) create mode 100644 app/src/main/res/layout/activity_main.xml create mode 100644 maps-rx/src/test/java/com/google/maps/android/rx/maps/MapsRxTest.kt create mode 100644 maps-rx/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker create mode 100644 places-rx/src/test/java/com/google/maps/android/rx/places/PlacesRxTest.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0204399..b64d370 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -49,8 +49,8 @@ android { } compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } } @@ -75,6 +75,12 @@ dependencies { implementation(libs.mapsKtx) implementation(libs.kotlinStdlib) + testImplementation(libs.junit) + testImplementation(libs.robolectric) + testImplementation(libs.androidxTestCore) + testImplementation(libs.androidxTestExtJunit) + testImplementation(libs.mockitoCore) + testImplementation(libs.mockitoKotlin) } secrets { @@ -84,6 +90,6 @@ secrets { tasks.withType().configureEach { compilerOptions { - jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_1_8) + jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17) } } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e38dab7..f5284c5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,6 +18,9 @@ + + + + if (permissions.all { it.value }) { + enableMyLocation() + } else { + Toast.makeText(this, "Permissions required for Places demo", Toast.LENGTH_SHORT).show() } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - setContentView(mapView) + setContentView(R.layout.activity_main) + + // Initialize Places (provide a valid API key in local.defaults.properties or secrets) + // Note: SDK must be initialized. Usually done in Application class, + // but here confirming if it's initialized or doing it here if simple. + // Assuming Places is initialized in application or we do it here if needed. + // For this demo, let's assume Application class initializes it or we add a check. + // Actually, we should check if Places is initialized. + if (!Places.isInitialized()) { + try { + val appInfo = packageManager.getApplicationInfo(packageName, android.content.pm.PackageManager.GET_META_DATA) + val apiKey = appInfo.metaData?.getString("com.google.android.geo.API_KEY") ?: "" + if (apiKey.isNotEmpty()) { + Places.initialize(applicationContext, apiKey) + } + } catch (e: Exception) { + Log.e(TAG, "Places not initialized", e) + } + } + + placesClient = Places.createClient(this) + mapView = findViewById(R.id.mapView) + val mapViewBundle = savedInstanceState?.getBundle(MAPVIEW_BUNDLE_KEY) mapView.onCreate(mapViewBundle) mapView.observe(lifecycle) - lifecycle.coroutineScope.launchWhenCreated { - val googleMap = mapView.awaitMap() - googleMap.cameraIdleEvents() - .compose(provider.bindToLifecycle()) - .subscribe { - Log.d(TAG, "Camera is idle") + lifecycleScope.launch { + lifecycle.repeatOnLifecycle(Lifecycle.State.CREATED) { + val googleMap = mapView.awaitMap() + + // Camera events demo + googleMap.cameraIdleEvents() + .compose(provider.bindToLifecycle()) + .subscribe { + Log.d(TAG, "Camera is idle") + } + + // Enable location if permission granted + checkPermissions() + } + } + + findViewById