Agent skill

Cross App Tests With Uiautomator

by skydoves in skydoves/android-testing-skills

A skill your agent uses to drive cross-app and system-UI flows from instrumentation tests using UiAutomator 2.3.0 — UiDevice, BySelector / UiObject2 (modern), UiSelector / UiObject (legacy), Until…

Apache-2.0Auto-check passedMobile

Install Cross App Tests With Uiautomator

skills CLI
$ npx skills add skydoves/android-testing-skills --skill cross-app-tests-with-uiautomator -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install skydoves/android-testing-skills cross-app-tests-with-uiautomator --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/skydoves/android-testing-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/instrumentation/uiautomator/cross-app-tests-with-uiautomator .claude/skills/cross-app-tests-with-uiautomator && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
cross-app-tests-with-uiautomator
GitHub stars
334
Token cost
~4.6k tokens
SKILL.md length
1,133 words
Files
1
Skills in repo
50
Repo updated
First seen
Licence
Apache-2.0

At a glance

A skill your agent uses to drive cross-app and system-UI flows from instrumentation tests using UiAutomator 2.3.0 — UiDevice, BySelector / UiObject2 (modern), UiSelector / UiObject (legacy), Until…

  • Drive cross-app and system-UI flows from instrumentation tests using UiAutomator 2.3.0 — UiDevice
  • SKILL.md covers When to use this skill, When NOT to use this skill, Prerequisites and Workflow, plus 4 more sections
  • Reaches schemas.android.com
  • BySelector / UiObject2 (modern)

What it does

Cross App Tests With Uiautomator is an agent skill from skydoves/android-testing-skills. Use this skill to drive cross-app and system-UI flows from instrumentation tests using UiAutomator 2.3.0 — UiDevice, BySelector / UiObject2 (modern), UiSelector / UiObject (legacy), Until conditions, and Configurator global timeouts. Covers the singleton acquisition (UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())), pressBack/pressHome/pressRecentApps, device.findObject(By...) cached-node refresh and StaleObjectException recovery, the executeShellCommand @Discouraged path vs…

Its SKILL.md is about 4.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Mobile, covering Mobile testing and debugging. It works with Android. The repository describes itself as: ⚡️ A set of skills for Android testing: Compose UI, AndroidX Test, JVM unit tests, and ADB. The licence is Apache-2.0.

When your agent uses it

  • Drive cross-app and system-UI flows from instrumentation tests using UiAutomator 2.3.0 — UiDevice
  • BySelector / UiObject2 (modern)
  • UiSelector / UiObject (legacy)
  • Until conditions

Example prompts

  • “how do I open Settings from a test”
  • “toggle Wi-Fi”
  • “dismiss notification shade”
  • “/cross-app-tests-with-uiautomator”

What it can do on your machine

Read from SKILL.md and the folder at commit 8665ed5. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are kotlin and xml).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    Hosts in commands or code, which the agent is likely to contact:

    • schemas.android.com

    Also links to:

    • developer.android.com

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Cross App Tests With Uiautomator loads about 4.6k tokens when it runs. Until then it costs about 221 tokens; SKILL.md has 1,133 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~221
When it runs · the whole SKILL.md, loaded when a task matches
~4.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from skydoves/android-testing-skills at commit 8665ed5, republished under its Apache-2.0 licence (© skydoves). 1,133 words, ~4,623 tokens.

Download SKILL.mdSave it as .claude/skills/cross-app-tests-with-uiautomator/SKILL.md (or your agent's skills folder).
name
cross-app-tests-with-uiautomator
description
Use this skill to drive cross-app and system-UI flows from instrumentation tests using UiAutomator 2.3.0 — `UiDevice`, `BySelector` / `UiObject2` (modern), `UiSelector` / `UiObject` (legacy), `Until` conditions, and `Configurator` global timeouts. Covers the singleton acquisition (`UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())`), `pressBack/pressHome/pressRecentApps`, `device.findObject(By...)` cached-node refresh and `StaleObjectException` recovery, the `executeShellCommand` `@Discouraged` path vs `Context.startActivity` plus `<queries>`, and the full `By` factory catalog. Use when the user reports `StaleObjectException`, `Espresso InjectEventSecurityException`, `findObject returns null`, asks "how do I open Settings from a test", "toggle Wi-Fi", "dismiss notification shade", or "test that spans my app and another".
license
Apache-2.0. See LICENSE for complete terms.
metadata.author
Jaewoong Eum (skydoves)
metadata.keywords
uiautomator, UiDevice, BySelector, UiObject2, UiSelector, Until, Configurator, StaleObjectException, cross-app-test, system-ui-test, pressHome…

Cross-App Tests with UiAutomator — Drive System UI and Other Apps

UiAutomator is the only AndroidX test framework that can drive UI across process boundaries — Settings, the dialer, system notifications, another app's activity. Espresso refuses (InjectEventSecurityException) when an event would cross to a foreign window. UiAutomator works against the platform AccessibilityNodeInfo tree, so it sees every window. This skill encodes the modern BySelector / UiObject2 API, the singleton acquisition, the StaleObjectException recovery pattern, and the cross-app launch path.

When to use this skill

  • The test must drive system UI (Settings, dialer, system notifications, quick settings, recents).
  • The test spans the developer's app and another app (share sheet, contacts picker, camera).
  • Espresso threw InjectEventSecurityException because the test reached a foreign window.
  • The user reports StaleObjectException and is debugging cached-node lifetime.
  • The user asks how to send the device home, press recents, or toggle airplane mode in a test.
  • The user mixes BySelector and UiSelector in the same test and is confused which is current.

When NOT to use this skill

  • The UI is entirely inside the developer's app — Espresso (Views) or Compose tests are faster and more reliable. See ../../espresso/writing-espresso-tests/SKILL.md for Views.
  • The runner stack is not yet set up — start with ../../runner/running-instrumented-tests-with-androidjunit4/SKILL.md.
  • The user only needs to push device-side state changes (animations off, intent stub) — see ../../../adb/control/injecting-input-and-state/SKILL.md.
  • The test only needs to scrape logs after a run — see ../../../adb/observability/extracting-logs-with-logcat/SKILL.md.

Prerequisites

  • Runner stack from ../../runner/running-instrumented-tests-with-androidjunit4/SKILL.md.
  • androidTestImplementation("androidx.test.uiautomator:uiautomator:2.3.0").
  • A real or virtual Android device with the accessibility_service available (the default).
  • For Context.startActivity to a foreign package on API 30+, a <queries> entry in the test APK manifest naming the target package or intent action.

Workflow

  • 1. Acquire UiDevice once per test, via the singleton with explicit instrumentation. The no-arg getInstance() is @Deprecated (R4 lines 56-58) — it throws IllegalStateException if not previously initialized:
kotlin
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice

private lateinit var device: UiDevice

@Before fun setUp() {
    device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
}
  • 2. Send hard keys and global actions via UiDevice methods. Source: R4 lines 88-104.
kotlin
device.pressBack()
device.pressHome()
device.pressMenu()
device.pressRecentApps()                                // GLOBAL_ACTION_RECENTS
device.pressKeyCode(KeyEvent.KEYCODE_VOLUME_DOWN)
device.openNotification()                                // GLOBAL_ACTION_NOTIFICATIONS
device.openQuickSettings()                               // GLOBAL_ACTION_QUICK_SETTINGS
device.wakeUp()                                          // power-on if off
device.sleep()                                           // power-off if on
  • 3. Find UI elements with BySelector (modern) via the By factory. Selectors are immutable-ish builders; the package-private constructor enforces use of the static factories. Criteria are joined as implicit AND. Source: R4 lines 185-258.
kotlin
import androidx.test.uiautomator.By

By.text("Submit")                              // exact, case-sensitive
By.textContains("ubmi")                        // case-sensitive substring
By.textMatches("Sub.*")                        // Pattern.compile regex
By.desc("Open menu")                           // content description
By.res("com.example.app", "submit_btn")        // package + res id
By.res("com.example.app:id/submit_btn")        // qualified res id
By.clazz("android.widget.Button")              // fully-qualified, or ".widget.Button" auto-prefixed with "android"
By.clazz(android.widget.Button::class.java)
By.pkg("com.android.settings")
By.depth(2)                                    // depth from window root
By.checkable(true)
By.hasChild(By.text("Inner"))                  // sugar for hasDescendant(child, 1)
By.hasDescendant(By.text("anywhere"))
By.hasParent(By.clazz("...LinearLayout"))
By.hasAncestor(By.res("...container"))
  • 4. Resolve to UiObject2 via device.findObject(...) and act. findObject returns null when no match (NEVER throws). For interactions, prefer device.wait(Until.findObject(By...), timeoutMillis) so the lookup is robust to slow renders:
kotlin
import androidx.test.uiautomator.Until

val submit = device.wait(Until.findObject(By.res("com.example", "submit")), 5_000)
    ?: error("Submit not found within 5s")

submit.click()
submit.longClick()
submit.setText("hello")
submit.clear()
submit.swipe(Direction.LEFT, 0.8f)            // percent ∈ [0,1]
submit.scroll(Direction.DOWN, 1.0f)
submit.scrollUntil(Direction.DOWN, Until.findObject(By.text("Bottom")))
submit.pinchOpen(0.5f)
submit.pinchClose(0.5f)

UiObject2 caches an AccessibilityNodeInfo. Each action calls getAccessibilityNodeInfo() which calls device.waitForIdle() then mCachedNode.refresh(); on failure it runs registered UiWatchers, retries once, and on a second failure throws StaleObjectException (R4 lines 281-286, 622-637).

  • 5. Wait for asynchronous UI states with Until conditions. Three condition flavors per R4 lines 495-540:
kotlin
// SearchCondition (consume the device tree)
device.wait(Until.hasObject(By.text("Loaded")), 5_000)
device.wait(Until.gone(By.text("Loading")), 5_000)
val obj: UiObject2? = device.wait(Until.findObject(By.text("OK")), 5_000)
val list: List<UiObject2>? = device.wait(Until.findObjects(By.clazz("...Button")), 3_000)

// UiObject2Condition (consume a UiObject2 — for state predicates)
val checked = button.wait(Until.checked(true), 5_000)

// EventCondition (consume AccessibilityEvents — for window transitions)
val newWindowFired = device.performActionAndWait(
    { button.click() }, Until.newWindow(), 10_000,
)
  • 6. Recover from StaleObjectException by re-finding. StaleObjectException extends RuntimeException — unchecked, must be handled when holding a long-lived UiObject2:
kotlin
fun clickRetry(selector: BySelector, timeoutMillis: Long = 5_000) {
    val obj = device.wait(Until.findObject(selector), timeoutMillis)
        ?: error("Not found: $selector")
    try {
        obj.click()
    } catch (e: StaleObjectException) {
        device.wait(Until.findObject(selector), timeoutMillis)?.click()
            ?: throw e
    }
}

Better: re-look-up before each interaction instead of holding a long-lived reference. Common causes: activity transition, Compose recomposition replacing semantic nodes, RecyclerView recycle, configuration change (R4 lines 639-645).

  • 7. Launch foreign packages — prefer Context.startActivity over executeShellCommand. executeShellCommand is @Discouraged per R4 lines 147-151 (UiDevice.java:1432); the Javadoc recommends UiAutomation.executeShellCommandRwe for stdin/stderr. For routine app launches, use the in-process intent route plus a <queries> manifest entry on API 30+:
xml
<!-- src/androidTest/AndroidManifest.xml -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <queries>
        <package android:name="com.android.settings" />
        <intent>
            <action android:name="android.settings.SETTINGS" />
        </intent>
    </queries>
    <!-- ... -->
</manifest>
kotlin
val ctx = ApplicationProvider.getApplicationContext<Context>()
ctx.startActivity(
    Intent(android.provider.Settings.ACTION_WIFI_SETTINGS)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
)
device.wait(Until.hasObject(By.pkg("com.android.settings").depth(0)), 10_000)

If the user really needs the shell route (e.g. a deep-link no Intent resolves):

kotlin
device.executeShellCommand("am start -n com.android.settings/.Settings")
device.wait(Until.hasObject(By.pkg("com.android.settings")), 5_000)
  • 8. Tune Configurator global timeouts when needed; restore on teardown. Settings are process-wide. Defaults (R4 lines 550-558): wait-for-idle 10s, wait-for-selector 10s (legacy UiObject only), action-acknowledgment 3s, scroll-event-wait 1s.
kotlin
import androidx.test.uiautomator.Configurator

@Before fun setUp() {
    val c = Configurator.getInstance()
    originalIdle = c.waitForIdleTimeout
    c.waitForIdleTimeout = 5_000   // tighter for fast tests
}

@After fun tearDown() {
    Configurator.getInstance().waitForIdleTimeout = originalIdle
}

setKeyInjectionDelay is @Deprecated ("This parameter is no longer used (text is set directly rather than by key)." — R4 lines 575-577). Do not call it.

  • 9. Recognize when to fall back to legacy UiSelector / UiObject. UiSelector re-resolves the node on every action via Configurator.getWaitForSelectorTimeout(), so it cannot go stale, but every call is more expensive and uses the checked UiObjectNotFoundException. The modern BySelector / UiObject2 is the recommended default. Use legacy only for interop with old test code or when re-resolution semantics are mandatory. R4 lines 594-619.

  • 10. Never call findObject(By.text("...")) immediately after launch and assume it sees the target window. By.text matches whatever is on screen now, which may be a transient splash or the previous app. Always combine with By.pkg(...) or wait explicitly:

kotlin
device.pressHome()
ctx.startActivity(Intent(Settings.ACTION_SETTINGS).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
device.wait(Until.hasObject(By.pkg("com.android.settings")), 5_000)   // gate on package
device.wait(Until.findObject(By.text("Network & internet")), 5_000)?.click()

Patterns

Pattern: WRONG vs RIGHT — driving Settings without waiting on package transition
kotlin
// WRONG
device.findObject(By.text("Settings")).click()
// WRONG because: at the moment of the call, By.text("Settings") matches whatever text reads
// "Settings" anywhere on the current screen — that might be a launcher tile, a notification,
// or a previous-app menu item. The test silently navigates to the wrong place.
kotlin
// RIGHT
device.pressHome()
device.executeShellCommand("am start -a android.settings.SETTINGS")
device.wait(Until.hasObject(By.pkg("com.android.settings")), 5_000)
device.wait(Until.findObject(By.text("Network & internet")), 5_000)?.click()
Show full SKILL.md (450 more words)Show less
Pattern: WRONG vs RIGHT — UiDevice.getInstance() no-arg
kotlin
// WRONG
val device = UiDevice.getInstance()
// WRONG because: UiDevice.java:344 — the no-arg getInstance() is @Deprecated and throws
// IllegalStateException if the singleton has not been previously initialized with the
// instrumentation argument. Setting it implicitly via androidTest is unreliable across
// runner versions.
kotlin
// RIGHT
val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
Pattern: WRONG vs RIGHT — long-lived UiObject2 across a transition
kotlin
// WRONG
val tile = device.wait(Until.findObject(By.descContains("Wi-Fi")), 5_000)
device.openQuickSettings()
tile.click()                            // throws StaleObjectException — quick settings replaced the layout
kotlin
// RIGHT — re-acquire after the transition
device.openQuickSettings()
val tile = device.wait(Until.findObject(By.descContains("Wi-Fi").clickable(true)), 5_000)
tile?.click()
device.pressBack()
Pattern: dismissing all notifications
kotlin
device.openNotification()
val shade = device.wait(
    Until.findObject(By.res("com.android.systemui:id/notification_stack_scroller")),
    5_000,
) ?: error("Notification shade not visible")

for (n in shade.findObjects(By.res("com.android.systemui:id/notification_layout"))) {
    n.swipe(Direction.RIGHT, 1.0f)
}
device.pressBack()
Pattern: launching the app under test from a clean state
kotlin
@Before fun launchAppFromHome() {
    device.pressHome()
    val ctx = ApplicationProvider.getApplicationContext<Context>()
    val launch = ctx.packageManager.getLaunchIntentForPackage("com.example.app")!!
        .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
    ctx.startActivity(launch)
    device.wait(Until.hasObject(By.pkg("com.example.app").depth(0)), 5_000)
}

Mandatory rules

  • MUST acquire UiDevice via UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()). The no-arg getInstance() is @Deprecated and unreliable.
  • MUST prefer BySelector / UiObject2 over UiSelector / UiObject for new tests. Legacy is for interop only.
  • MUST wait on a transition with device.wait(Until.hasObject(By.pkg("...")), timeout) before resolving inner elements after a cross-window change. Bare findObject runs against the current window without gating.
  • MUST handle StaleObjectException (re-find via device.wait(Until.findObject(By...), timeout)) when keeping a UiObject2 reference across recompose, transition, or recyclerview recycle.
  • MUST restore Configurator settings in @After if a test mutated them. Settings are process-wide and leak across tests.
  • MUST NOT call Configurator.setKeyInjectionDelay — @Deprecated and a no-op.
  • MUST NOT rely on executeShellCommand for routine app launches — it is @Discouraged. Use Context.startActivity plus a <queries> manifest entry on API 30+.
  • MUST NOT use device.findObject(By.text("...")) without gating on package — text matches the current window contents, which may be a transient splash.
  • PREFERRED: wrap any single interaction in a device.wait(Until.findObject(...), timeout)?.click() rather than calling findObject then click two lines apart. The two-step form races with rendering.
  • PREFERRED: add <queries> for any foreign package the test launches — silent failures on API 30+ otherwise.

Verification

  • No source file calls UiDevice.getInstance() with no arguments.
  • No source file calls Configurator.setKeyInjectionDelay.
  • Every long-lived UiObject2 reference has a try { ... } catch (StaleObjectException) around its action — or the test re-finds before each interaction.
  • Tests that launch foreign packages have a <queries> entry for that package or its intent action in src/androidTest/AndroidManifest.xml.
  • ./gradlew :<module>:connectedDebugAndroidTest runs without IllegalStateException from UiDevice.getInstance() and without unhandled StaleObjectException propagating to the test result.
  • No findObject(By.text(...)) is called immediately after a cross-window transition without a preceding device.wait(Until.hasObject(By.pkg(...)), ...).
  • If Configurator was mutated in @Before, an @After restores the original values.

References

  • Android Developers — UiAutomator overview: https://developer.android.com/training/testing/other-components/ui-automator
  • AndroidX Test (UiAutomator) release notes: https://developer.android.com/jetpack/androidx/releases/test
  • UiAutomator API reference: https://developer.android.com/reference/androidx/test/uiautomator/package-summary
  • androidx/test/uiautomator/UiDevice.java — the singleton entry point. Lines 344 (@Deprecated no-arg getInstance), 357 (current getInstance(Instrumentation)), 1432 (@Discouraged executeShellCommand).
  • androidx/test/uiautomator/By.java — static factory for BySelector. Source for text/desc/res/clazz/pkg/depth/checkable/hasChild/hasDescendant/hasParent/hasAncestor.
  • androidx/test/uiautomator/BySelector.java (838 lines) — full criteria catalog. Lines 128 (auto-prefix .widget.Button with android), 198/211/224 (regex / contains / starts-with conventions), 605-650 (maxDepth), 660 (displayId).
  • androidx/test/uiautomator/UiObject2.java (1152 lines) — click, setText, swipe, scroll, scrollUntil, pinchOpen/Close, fling. Line 1031 — getAccessibilityNodeInfo() throws StaleObjectException after refresh failure + watcher retry.
  • androidx/test/uiautomator/Until.java lines 43-456 — hasObject, gone, findObject, findObjects, newWindow, scrollFinished, plus UiObject2Condition predicates.
  • androidx/test/uiautomator/Configurator.java lines 36 (warning to restore), 108 (waitForSelector legacy-only), 163 (actionAcknowledgment legacy-only), 189 (setKeyInjectionDelay @Deprecated), 295 (setDefaultDisplayId).
  • androidx/test/uiautomator/StaleObjectException.java — extends RuntimeException.
  • tasks/research/R4-uiautomator.md — full UiAutomator 2.3.0 deep-dive. Lines 56-58 (deprecated singleton), 185-258 (BySelector catalog), 268-369 (UiObject2 actions), 495-540 (Until conditions), 594-619 (modern vs legacy table), 622-662 (StaleObjectException recovery).
  • docs/CORPUS.md Section H.6 — UiAutomator essentials and the StaleObjectException recovery summary.

© skydoves, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in instrumentation/uiautomator/cross-app-tests-with-uiautomator of skydoves/android-testing-skills.

Open the folder on GitHubat commit 8665ed5

Compare with similar skills

Cross App Tests With Uiautomator next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Cross App Tests With Uiautomator compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Cross App Tests With Uiautomator this skillskydoves/android-testing-skills334—~4.6kAutomated safety check: PassApache-2.0
Phone HarnessShawnPana/phone-harness3.2k—~4.3kAutomated safety check: PassMIT
Mobile QAtloncorp/tlon-apps107—~2.4kAutomated safety check: PassMIT
Androidyang1ming/android-harness176—~259Automated safety check: PassMIT
Debug Receiverstimusus/Shuttle2229—~1.9kAutomated safety check: PassApache-2.0
Debug Bridgegetknit/knit133—~2.3kAutomated safety check: PassGPL-3.0

Similar skills

  • Phone Harness

    ShawnPana/phone-harness

    Control the user's phone — an iPhone through the Mac's iPhone Mirroring window, an Android over adb, or a rented cloud Android: open apps, tap, type, swipe, read the screen.

    3.2k GitHub stars~4.3k tokensUpdated today
    MobileAuto-check passed
  • Mobile QA

    tloncorp/tlon-apps

    Run a mobile QA checklist on a physical Android device over adb for tlon-apps, then triage what fails into fixes.

    107 GitHub stars~2.4k tokensUpdated today
    MobileAuto-check passed
  • Android

    yang1ming/android-harness

    Direct Android device control through ADB. An agent skill from yang1ming/android-harness.

    176 GitHub stars~259 tokensUpdated 2 mo ago
    MobileAuto-check passed
  • Debug Receivers

    timusus/Shuttle2

    Drive the S2 debug build's playback and queue over ADB broadcasts — play the whole library, play/pause, skip, seek, remove a queue item, toggle shuffle/repeat, dump playback state as JSON, reimport…

    229 GitHub stars~1.9k tokensUpdated today
    MobileAuto-check passed
  • Debug Bridge

    getknit/knit

    Drive and verify Knit on a device or emulator through the headless debug bridge (am broadcast to app.getknit.knit.debug.<ACTION, replies as JSON) — send a message on one phone and confirm it landed…

    133 GitHub stars~2.3k tokensUpdated today
    MobileAuto-check passed
  • Android Emulator Skill

    Moustachauve/WLED-Android

    Production-ready scripts for Android app testing, building, and automation.

    169 GitHub starsUsed in 1 repo~911 tokens
    MobileAuto-check passed

More from skydoves/android-testing-skills

All 50 skills in this repo
  • Asserting Bounds And Dimensions

    skydoves/android-testing-skills

    A skill your agent uses to verify Compose layout measurements from a UI test using assertWidthIsEqualTo, assertHeightIsEqualTo, assertWidthIsAtLeast, assertHeightIsAtLeast…

    334 GitHub stars~3.3k tokensUpdated 4 mo ago
    Auto-check passed
  • Asserting Node State And Text

    skydoves/android-testing-skills

    A skill your agent uses to verify a Compose semantics node's properties from a UI test using assertExists, assertDoesNotExist, assertIsDisplayed, assertIsNotDisplayed, assertIsDeactivated…

    334 GitHub stars~3.6k tokensUpdated 4 mo ago
    Auto-check passed
  • Capturing Preview Screenshots In CI

    skydoves/android-testing-skills

    A skill your agent uses to render every Jetpack Compose @Preview as a screenshot on a real Android device or emulator and publish a browsable HTML catalog from CI.

    334 GitHub stars~4.5k tokensUpdated 4 mo ago
    Auto-check: notes
  • Capturing Screenshots And Screenrecord

    skydoves/android-testing-skills

    A skill your agent uses to capture visual artefacts from a device for test failures, golden image generation, QA repro, and demo videos.

    334 GitHub stars~3.7k tokensUpdated 4 mo ago
    Auto-check passed
  • Choosing Test Rule Vs Runtest

    skydoves/android-testing-skills

    A skill your agent uses to pick the correct Compose UI test entry point.

    334 GitHub stars~4.5k tokensUpdated 4 mo ago
    Auto-check passed
  • Choosing What To Test

    skydoves/android-testing-skills

    A skill your agent uses to pick which behaviors to cover in an Android test suite using Google's five-category state vocabulary plus the explicit "what NOT to test" list from…

    334 GitHub stars~4.6k tokensUpdated 4 mo ago
    Auto-check passed

Works with

Categories

Questions about Cross App Tests With Uiautomator

What does Cross App Tests With Uiautomator do?

A skill your agent uses to drive cross-app and system-UI flows from instrumentation tests using UiAutomator 2.3.0 — UiDevice, BySelector / UiObject2 (modern), UiSelector / UiObject (legacy), Until…. Cross App Tests With Uiautomator is an agent skill from skydoves/android-testing-skills.0 — UiDevice, BySelector / UiObject2 (modern), UiSelector / UiObject (legacy), Until conditions, and Configurator global timeouts.

When should I use Cross App Tests With Uiautomator?

Cross App Tests With Uiautomator fits situations like: drive cross-app and system-UI flows from instrumentation tests using UiAutomator 2.3.0 — UiDevice; bySelector / UiObject2 (modern); uiSelector / UiObject (legacy); until conditions.

How do I install Cross App Tests With Uiautomator in Claude Code?

Run `npx skills add skydoves/android-testing-skills --skill cross-app-tests-with-uiautomator -a claude-code`. Or copy the skill folder (instrumentation/uiautomator/cross-app-tests-with-uiautomator in skydoves/android-testing-skills) into .claude/skills/cross-app-tests-with-uiautomator in your project. Claude Code loads it when a task matches its description.

How do I install Cross App Tests With Uiautomator in Codex?

Run `npx skills add skydoves/android-testing-skills --skill cross-app-tests-with-uiautomator -a codex`. Or copy the skill folder (instrumentation/uiautomator/cross-app-tests-with-uiautomator in skydoves/android-testing-skills) into .agents/skills/cross-app-tests-with-uiautomator in your project. Codex loads it when a task matches its description.

Can I use Cross App Tests With Uiautomator in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add skydoves/android-testing-skills --skill cross-app-tests-with-uiautomator -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/cross-app-tests-with-uiautomator, .gemini/skills/cross-app-tests-with-uiautomator, .github/skills/cross-app-tests-with-uiautomator and .opencode/skills/cross-app-tests-with-uiautomator in your project.

What does Cross App Tests With Uiautomator need to run?

SKILL.md names no scripts, command-line tools or credentials: Cross App Tests With Uiautomator is instructions for the agent only.

Does Cross App Tests With Uiautomator access the network?

SKILL.md names 2 domains. In commands or code: schemas.android.com; the agent is likely to contact it when it follows the instructions. As links in the text: developer.android.com. This is read from the text; nothing was executed.

Is Cross App Tests With Uiautomator safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Cross App Tests With Uiautomator use?

Cross App Tests With Uiautomator is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Cross App Tests With Uiautomator use?

About 4.6k tokens (SKILL.md is roughly 18k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Cross App Tests With Uiautomator?

Skills that share tags, products or a category with Cross App Tests With Uiautomator: Phone Harness (ShawnPana/phone-harness, 3.2k stars), Mobile QA (tloncorp/tlon-apps, 107 stars), Android (yang1ming/android-harness, 176 stars) and Debug Receivers (timusus/Shuttle2, 229 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Cross App Tests With Uiautomator?

skydoves (a GitHub user) maintains it in skydoves/android-testing-skills, which has 334 GitHub stars. The repository holds 50 skills in this directory. The repository was last updated on May 25, 2026.

Source: skydoves/android-testing-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.