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/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/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..1e03b7d72
--- /dev/null
+++ b/WearOS/Wearable/src/androidTest/java/com/example/wearosmap/AppLaunchTest.kt
@@ -0,0 +1,79 @@
+/*
+ * 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
+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..7f47067ee 100755
--- a/scripts/verify_all.sh
+++ b/scripts/verify_all.sh
@@ -52,6 +52,50 @@ MODULES=(
":tutorials:kotlin:Polygons"
)
+# Parse arguments
+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() {
local module=$1
@@ -60,6 +104,7 @@ verify_module() {
local assembleTask=":assembleDebug"
local testTask=":testDebugUnitTest"
local lintTask=":lintDebug"
+ local connectedTask=""
if [[ "$module" == ":snippets:app" ]]; then
assembleTask=":assembleGmsDebug"
@@ -67,8 +112,28 @@ 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_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
+ 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"
+
+ 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}"