From af8a6bd955698382013095b3eaf0ca07510714d9 Mon Sep 17 00:00:00 2001
From: dkhawk <107309+dkhawk@users.noreply.github.com>
Date: Mon, 2 Feb 2026 17:43:53 -0700
Subject: [PATCH 1/3] fix: Resolve WearOS crash and add regression tests
Fixes NoClassDefFoundError by adding org.apache.http.legacy. Adds AppLaunchTest regression test. Updates verify_all.sh with --connected flag.
---
ApiDemos/project/java-app/build.gradle.kts | 1 +
WearOS/Wearable/build.gradle.kts | 13 ++++
.../com/example/wearosmap/AppLaunchTest.kt | 63 +++++++++++++++++++
WearOS/Wearable/src/main/AndroidManifest.xml | 3 +
scripts/verify_all.sh | 35 ++++++++++-
5 files changed, 113 insertions(+), 2 deletions(-)
create mode 100644 WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt
diff --git a/ApiDemos/project/java-app/build.gradle.kts b/ApiDemos/project/java-app/build.gradle.kts
index 9187a69e4..9c1e72613 100644
--- a/ApiDemos/project/java-app/build.gradle.kts
+++ b/ApiDemos/project/java-app/build.gradle.kts
@@ -81,6 +81,7 @@ dependencies {
androidTestImplementation(libs.junit)
androidTestImplementation(libs.espresso.core)
androidTestImplementation(libs.truth)
+ androidTestImplementation(libs.ext.junit)
}
secrets {
diff --git a/WearOS/Wearable/build.gradle.kts b/WearOS/Wearable/build.gradle.kts
index 229d6bcb8..eac685661 100644
--- a/WearOS/Wearable/build.gradle.kts
+++ b/WearOS/Wearable/build.gradle.kts
@@ -29,6 +29,7 @@ android {
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 1
versionName = libs.versions.versionName.get()
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
@@ -77,6 +78,13 @@ dependencies {
// This dependency is necessary for ambient mode
implementation(libs.wear)
+
+ // Android Test Dependencies
+ androidTestImplementation(libs.ext.junit)
+ androidTestImplementation(libs.espresso.core)
+ androidTestImplementation(libs.uiautomator)
+ androidTestImplementation(libs.truth)
+ androidTestImplementation(libs.junit)
// If your project does not use a version catalog, you can use the following dependencies instead:
//
@@ -84,6 +92,11 @@ dependencies {
// implementation("com.google.android.support:wearable:2.9.0")
// implementation("com.google.android.gms:play-services-maps:20.0.0")
// implementation("androidx.wear:wear:1.3.0")
+ // androidTestImplementation("androidx.test.ext:junit:1.1.5")
+ // androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
+ // androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0")
+ // androidTestImplementation("com.google.truth:truth:1.4.2")
+ // androidTestImplementation("junit:junit:4.13.2")
}
// [END maps_wear_os_dependencies]
diff --git a/WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt b/WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt
new file mode 100644
index 000000000..a145d08db
--- /dev/null
+++ b/WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt
@@ -0,0 +1,63 @@
+package com.example.wearosmap
+
+import androidx.test.core.app.ActivityScenario
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiSelector
+import com.example.wearosmap.kt.MainActivity
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class AppLaunchTest {
+
+ @Test
+ fun appLaunchesSuccessfully() {
+ // Launch the activity
+ ActivityScenario.launch(MainActivity::class.java).use { scenario ->
+ scenario.onActivity { activity ->
+ assertThat(activity).isNotNull()
+ }
+ }
+ }
+
+ @Test
+ fun mapContainerIsDisplayed() {
+ // Launch the activity
+ ActivityScenario.launch(MainActivity::class.java).use {
+ val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+
+ // Wait for the map container to appear
+ val mapContainer = device.findObject(UiSelector().resourceId("com.example.wearos:id/map_container"))
+ assertThat(mapContainer.waitForExists(5000)).isTrue()
+ }
+ }
+
+ @Test
+ fun markerTitleIsDisplayed() {
+ // Launch the activity
+ ActivityScenario.launch(MainActivity::class.java).use {
+ val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
+
+ // Wait for the marker title "Sydney Opera House" to appear
+ // Note: This relies on the Google Map rendering the marker and it being visible/accessible.
+ // In a real device/emulator, this might need more robust waiting logic or accessibility settings.
+ val markerTitle = device.findObject(UiSelector().descriptionContains("Sydney Opera House"))
+
+ // Allow some time for map loading and rendering
+ if (!markerTitle.exists()) {
+ markerTitle.waitForExists(10000)
+ }
+
+ // Verify if found (Bonus check, might flake on some emulators if map doesn't render)
+ // We use a softer check here or assertion if we are confident.
+ // For now, let's assert it exists if we want to be strict, or just log if we want to be lenient.
+ // Given the requirement "Verify Map and Marker presence (Bonus)", we'll try to assert.
+ assertThat(markerTitle.exists()).isTrue()
+ }
+ }
+}
diff --git a/WearOS/Wearable/src/main/AndroidManifest.xml b/WearOS/Wearable/src/main/AndroidManifest.xml
index b49353796..d69f72d9a 100644
--- a/WearOS/Wearable/src/main/AndroidManifest.xml
+++ b/WearOS/Wearable/src/main/AndroidManifest.xml
@@ -32,6 +32,9 @@
android:name="com.google.android.wearable.standalone"
android:value="true" />
+
+
+
diff --git a/scripts/verify_all.sh b/scripts/verify_all.sh
index dab8c3df2..60be42269 100755
--- a/scripts/verify_all.sh
+++ b/scripts/verify_all.sh
@@ -52,6 +52,13 @@ MODULES=(
":tutorials:kotlin:Polygons"
)
+# Parse arguments
+RUN_CONNECTED=false
+if [[ "$1" == "--connected" ]]; then
+ RUN_CONNECTED=true
+ echo "Running with Connected Android Tests..."
+fi
+
# Function to run verification for a module
verify_module() {
local module=$1
@@ -60,6 +67,7 @@ verify_module() {
local assembleTask=":assembleDebug"
local testTask=":testDebugUnitTest"
local lintTask=":lintDebug"
+ local connectedTask=""
if [[ "$module" == ":snippets:app" ]]; then
assembleTask=":assembleGmsDebug"
@@ -67,8 +75,31 @@ verify_module() {
lintTask=":lintGmsDebug"
fi
- # Run assemble, lint, and test
- if ./gradlew "$module$assembleTask" "$module$testTask" "$module$lintTask"; then
+ # Define connected test task if enabled
+ if [ "$RUN_CONNECTED" = true ]; then
+ if [[ "$module" == ":snippets:app" ]]; then
+ connectedTask=":connectedGmsDebugAndroidTest"
+ else
+ connectedTask=":connectedDebugAndroidTest"
+ fi
+
+ # Check if the module actually has this task (simple heuristic or hardcode for known modules)
+ # For now, we know WearOS has it. We can try running it and ignore if task not found?
+ # Or better, just run it for all and iterate.
+ # But some modules might not have android tests setups.
+ # Let's rely on the list.
+ fi
+
+ # Build command
+ local cmd="./gradlew $module$assembleTask $module$testTask $module$lintTask"
+
+ if [ -n "$connectedTask" ]; then
+ cmd="$cmd $module$connectedTask"
+ fi
+
+ # Run assemble, lint, and test (and connected if requested)
+ echo "Running: $cmd"
+ if $cmd; then
echo -e "${GREEN}SUCCESS: $module verified.${NC}"
else
echo -e "${RED}FAILURE: $module failed verification.${NC}"
From 1972edef63fddf7a66d30b2a4d432cebf3183552 Mon Sep 17 00:00:00 2001
From: dkhawk <107309+dkhawk@users.noreply.github.com>
Date: Mon, 2 Feb 2026 17:52:17 -0700
Subject: [PATCH 2/3] docs: Document verify_all.sh usage and flags
Adds --help, --connected-wear, and --connected-mobile flags to verify_all.sh. Updates README.md with usage instructions.
---
README.md | 10 ++++++++
scripts/verify_all.sh | 58 ++++++++++++++++++++++++++++++++++---------
2 files changed, 56 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index 72d660fca..732f33b08 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,16 @@ To verify that all samples build and pass tests, run:
./scripts/verify_all.sh
```
+To run instrumentation tests on a connected device or emulator, use:
+
+```bash
+# For Wear OS devices/emulators
+./scripts/verify_all.sh --connected-wear
+
+# For Mobile (Handheld) devices/emulators
+./scripts/verify_all.sh --connected-mobile
+```
+
Alternatively, use the `gradlew build` command to build the project directly or download an APK
under [releases](https://github.com/googlemaps/android-samples/releases).
diff --git a/scripts/verify_all.sh b/scripts/verify_all.sh
index 60be42269..7f47067ee 100755
--- a/scripts/verify_all.sh
+++ b/scripts/verify_all.sh
@@ -53,11 +53,48 @@ MODULES=(
)
# Parse arguments
-RUN_CONNECTED=false
-if [[ "$1" == "--connected" ]]; then
- RUN_CONNECTED=true
- echo "Running with Connected Android Tests..."
-fi
+RUN_CONNECTED_WEAR=false
+RUN_CONNECTED_MOBILE=false
+
+print_usage() {
+ echo "Usage: $0 [OPTIONS]"
+ echo ""
+ echo "Verifies all Android modules in the project by running assemble, test, and lint."
+ echo ""
+ echo "Options:"
+ echo " -h, --help Show this help message and exit"
+ echo " --connected-wear Run connected instrumentation tests for Wear OS modules"
+ echo " --connected-mobile Run connected instrumentation tests for Mobile (Handheld) modules"
+ echo " --connected Run ALL connected tests (Wear OS + Mobile) - Warning: Requires multiple emulators"
+ echo ""
+}
+
+for arg in "$@"; do
+ case $arg in
+ -h|--help)
+ print_usage
+ exit 0
+ ;;
+ --connected-wear)
+ RUN_CONNECTED_WEAR=true
+ echo "Running with Connected Wear OS Tests..."
+ ;;
+ --connected-mobile)
+ RUN_CONNECTED_MOBILE=true
+ echo "Running with Connected Mobile Tests..."
+ ;;
+ --connected)
+ RUN_CONNECTED_WEAR=true
+ RUN_CONNECTED_MOBILE=true
+ echo "Warning: Running ALL connected tests. This requires multiple simultaneous emulators (Wear + Handheld) or may fail."
+ ;;
+ *)
+ echo "Unknown option: $arg"
+ print_usage
+ exit 1
+ ;;
+ esac
+done
# Function to run verification for a module
verify_module() {
@@ -76,19 +113,16 @@ verify_module() {
fi
# Define connected test task if enabled
- if [ "$RUN_CONNECTED" = true ]; then
+ if [ "$RUN_CONNECTED_WEAR" = true ] && [[ "$module" == ":WearOS:Wearable" ]]; then
+ connectedTask=":connectedDebugAndroidTest"
+ elif [ "$RUN_CONNECTED_MOBILE" = true ] && [[ "$module" != ":WearOS:Wearable" ]]; then
if [[ "$module" == ":snippets:app" ]]; then
connectedTask=":connectedGmsDebugAndroidTest"
else
connectedTask=":connectedDebugAndroidTest"
fi
-
- # Check if the module actually has this task (simple heuristic or hardcode for known modules)
- # For now, we know WearOS has it. We can try running it and ignore if task not found?
- # Or better, just run it for all and iterate.
- # But some modules might not have android tests setups.
- # Let's rely on the list.
fi
+ # Note: If both flags are set, both types run (for their respective modules).
# Build command
local cmd="./gradlew $module$assembleTask $module$testTask $module$lintTask"
From fdcab9f8c59575b867a1cf436b77ac4758700325 Mon Sep 17 00:00:00 2001
From: dkhawk <107309+dkhawk@users.noreply.github.com>
Date: Mon, 2 Feb 2026 17:53:46 -0700
Subject: [PATCH 3/3] fix: Add missing copyright header to AppLaunchTest.kt
---
.../java/com/example/wearosmap/AppLaunchTest.kt | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt b/WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt
index a145d08db..1e03b7d72 100644
--- a/WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt
+++ b/WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt
@@ -1,3 +1,19 @@
+/*
+ * 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.
+ */
+
package com.example.wearosmap
import androidx.test.core.app.ActivityScenario