| name | android-screen |
| description | Capture annotated screenshots of a running Android app and translate UI element labels into actual tap coordinates, using `android screen capture` + `android screen resolve` and the structured `android layout` JSON. Use when the user wants to take a screenshot, automate UI interactions without hardcoding pixel coordinates, compare UI state before/after a change, or extract the view hierarchy. Triggers include "์คํฌ๋ฆฐ์ท", "screenshot", "๋ฒํผ ํด๋ฆญ ์๋ํ", "UI ์๋ํ", "tap", "view hierarchy", "layout ๋น๊ต", "์ด ๋ฒํผ ์ขํ". Do NOT use this skill for visual regression testing of release builds โ use Playwright/Espresso for that. |
android-screen
Three primitives, used in two main loops:
- Annotate-then-tap โ
screen capture --annotate produces a labeled image; screen resolve translates label numbers into (x, y); adb shell input tap performs the action.
- Layout diff โ
android layout produces a structured JSON snapshot of the on-screen view tree; --diff shows only what changed since the last snapshot.
This skill assumes a device is already connected (use android-emulator or android-deploy to get there).
Workflow A โ annotated tap automation
android screen capture --annotate -o ui.png
โ (user/agent picks a label)
android screen resolve --screenshot=ui.png --string="input tap #5"
โ (resolved to e.g. "input tap 540 1283")
adb shell <resolved>
Concrete sequence:
android screen capture --annotate -o ui.png
android screen resolve --screenshot=ui.png --string="input tap #5"
adb shell input tap 540 1283
The --string argument can interleave labels with literal text: "input swipe #3 #7" resolves both #3 and #7.
Critical rule: re-capture invalidates labels
The annotation numbering is generated at capture time. After any UI change (a tap that opens a new screen, a layout reflow, a snackbar appearing), the previous annotated image's label numbers no longer correspond to the same elements. Always re-capture before resolving if anything has changed since the last capture.
Workflow B โ layout diff debugging
android layout --pretty -o before.json
android layout --diff
Use cases:
- Tracking which views actually re-rendered after a state change.
- Confirming a Compose recomposition is or isn't reaching a target node.
- Investigating "why did this view appear / disappear".
The internal snapshot is updated each time android layout runs, so two consecutive calls without intervening UI changes will show no diff.
Operating rules
- Capture is cheap, re-capture before each resolve. Label numbers are not stable across captures.
- Resolve, then tap โ don't paste coordinates from the screenshot inspector. Hardcoded pixels break across devices and orientations.
- For repetitive automation, script the chain, don't run interactively. Example:
android screen capture --annotate -o /tmp/ui.png
adb shell $(android screen resolve --screenshot=/tmp/ui.png --string="input tap #2")
--annotate is required for resolve. A plain capture (without --annotate) has no labels to resolve against.
- Use
--pretty only for human reading. For diffs and automated parsing, the compact form is more efficient.
adb shell input for taps, not monkey. Monkey is for stress testing, not deterministic automation.
- Don't chain captures into git. Annotated PNGs are large and noisy; write them to
/tmp/ or build/ (gitignored) by default.
Decision matrix โ which tool for what
| Goal | Use | Don't use | Why |
|---|
| Find tap coordinates without measuring pixels | screen capture --annotate + resolve | manual inspection | Labels survive DPI / orientation differences |
| Detect what changed in the UI | layout --diff | screenshot diff | Structured, ignores anti-aliasing noise |
| Full view hierarchy for offline analysis | layout --pretty -o | adb shell uiautomator dump | JSON is structured and stable; uiautomator XML is verbose |
| Scripted button clicks in tests | Espresso / Compose UI test | this skill | Tests should not depend on pixel coordinates |
| Visual regression | Paparazzi / Roborazzi | this skill | Headless, hermetic, runs in CI |
| Pixel-perfect screenshot for marketing | Studio Device Screenshot | screen capture | This skill is for automation, not asset creation |
Anti-patterns
- โ Resolving against a stale
ui.png after taps have changed the screen.
- โ Hardcoding
input tap 540 1283 in a script โ different device โ wrong button.
- โ Capturing without
--annotate then trying to resolve โ fails silently with bad output.
- โ Using
android layout as a substitute for proper UI tests.
- โ Committing annotated screenshots to the repo.
- โ Calling this skill when no device is connected โ produces empty/error output. Pre-flight
adb devices.
Error recovery
| Error | Cause | Fix |
|---|
screen capture produces empty PNG | No connected device or screen off | adb devices; adb shell input keyevent KEYCODE_WAKEUP |
resolve returns the input unchanged | Label #N doesn't exist in screenshot | Re-run screen capture --annotate, look at fresh labels |
layout returns {} | App not in foreground | adb shell am start -n <pkg>/<activity> first |
| Coordinates feel "off" by a constant | Status bar / cutout offsets in fullscreen mode | Re-capture; coordinates account for current insets |