| name | verify-on-emulator |
| description | Boot (or reuse) the TBox-Mock-Play AVD, install the debug APK, drive the launcher, and capture screenshots to verify UI changes on the head-unit geometry. |
| when_to_use | Verifying a UI change visually; "check it on the emulator", "screenshot the dashboard", "does it look right on the head unit". |
| argument-hint | [screen-or-area] |
| allowed-tools | ["Bash","Read"] |
Verifying on the TBox-Mock-Play emulator
Visual verification on the head-unit geometry. $ARGUMENTS names the
screen or area to drive to and screenshot; with no argument, verify
the home dashboard.
Environment
- Tools: resolve
adb / emulator from PATH first
(command -v adb; the Bash shell initializes from your profile —
the committed allowlist covers bare invocations). If not on PATH,
use $ANDROID_HOME/{platform-tools,emulator}, else the
conventional SDK root (~/Library/Android/sdk on macOS,
~/Android/Sdk on Linux); absolute-path invocations prompt unless
mirrored in .claude/settings.local.json. local.properties and
~/Library may be Read-denied — use ls/adb, not cat. Gradle
finds the SDK via local.properties regardless.
- AVD:
TBox-Mock-Play — 1280x720 @ 160 dpi (the 800x480 dp
head-unit geometry) with Google Play, so a signed-in account
provides real calendar events and media sessions. The definition
is committed in this skill directory: create-avd.sh writes
the AVD registry files directly from tbox-mock-play.config.ini
(no avdmanager / cmdline-tools needed; only the
android-33 google_apis_playstore system image for the host arch
must be installed). Google sign-in inside the AVD stays a one-time
manual step per machine — account state is not portable.
- App id:
io.github.seijikohara.femto (no debug suffix).
Procedure
-
Build the debug APK via the
verify-android-build skill
(the verification-procedure SSOT). The APK lands at
app/build/outputs/apk/debug/app-debug.apk.
-
Reuse or boot the emulator. More than one emulator may be
running, so resolve serials first: adb devices, then
adb -s <serial> emu avd name to identify each instance. If a
TBox-Mock-Play is already up, reuse it — installing onto the
instance the user is watching is the point; never touch an
unrelated instance. If none is running:
emulator -avd TBox-Mock-Play -no-audio -gpu host
Windowed on purpose — the user watches the verification live. In
a headless context (no display available) add
-no-window -gpu swiftshader_indirect instead of -gpu host. If
the AVD does not exist (emulator -list-avds), create it first:
.claude/skills/verify-on-emulator/create-avd.sh
Wait until adb -s <serial> shell getprop sys.boot_completed
reports 1 before installing. With multiple devices attached,
pass -s <serial> to every adb call below.
-
Install the APK:
adb -s <serial> install -r app/build/outputs/apk/debug/app-debug.apk
Note: connectedAndroidTest uninstalls the app afterward —
run :app:installDebug (or adb install -r) again before manual
screenshots. After a reinstall, am force-stop + restart the app
so the running process is the new code.
-
Pre-grant runtime permissions — the startup permission dialog
blocks the dashboard (MainActivity.requestRuntimePermissions()
pops a location dialog on first run; uiautomator shows
com.google.android.permissioncontroller). Pre-grant to skip it:
adb shell pm grant io.github.seijikohara.femto android.permission.{ACCESS_FINE_LOCATION,ACCESS_COARSE_LOCATION,READ_CALENDAR,READ_PHONE_STATE,BLUETOOTH_CONNECT}
then am force-stop + restart.
-
Drive the UI: uiautomator dump /sdcard/ui.xml + adb pull,
grep content-desc="Settings" for the dock button bounds (the
DashboardDock component, formerly called the footer), then
input tap. The settings ModalBottomSheet opens partially
expanded — input swipe up to fully expand, then swipe to
scroll.
-
Capture and inspect: Compose row text often does not appear as
discrete text= nodes (merged semantics), so confirm with a
screenshot — screencap -p + pull + Read the image:
adb shell screencap -p /sdcard/shot.png && adb pull /sdcard/shot.png
Notes and former limitations
- The LIVE map WebView renders on the emulator (verified 2026-07
under both
-gpu host and swiftshader_indirect); the old "GL
surface cannot present" limitation no longer reproduces. A blank
map is NOT expected — check the -gpu mode and logcat before
suspecting a regression.
- The Play system image has no
adb root; runtime grants via
pm grant still work.
Report
Report explicitly what was run and what was observed:
- "Ran
adb install -r app-debug.apk — Success."
- "Pre-granted permissions via
adb shell pm grant ...."
- "Captured
shot.png — the calendar card renders the 6-day strip."
Do not claim the UI "looks right" generically; cite the commands and
attach or describe the screenshots.