com um clique
interacting-with-android-device
// Instructions for capturing UI state, comparing with mocks, and interacting with an Android device using MCP tools backed by ADB.
// Instructions for capturing UI state, comparing with mocks, and interacting with an Android device using MCP tools backed by ADB.
This skill should be used when implementing Android code in Bitwarden. Covers critical patterns, gotchas, and anti-patterns unique to this codebase. Triggered by "How do I implement a ViewModel?", "Create a new screen", "Add navigation", "Write a repository", "BaseViewModel pattern", "State-Action-Event", "type-safe navigation", "@Serializable route", "SavedStateHandle persistence", "process death recovery", "handleAction", "sendAction", "Hilt module", "Repository pattern", "implementing a screen", "adding a data source", "handling navigation", "encrypted storage", "security patterns", "Clock injection", "DataState", or any questions about implementing features, screens, ViewModels, data sources, or navigation in the Bitwarden Android app.
Android-specific code review checklist and MVVM/Compose pattern validation for Bitwarden Android — use this for any review task, even if the user doesn't explicitly ask for a "checklist". Detects change type automatically and loads the right review strategy (feature additions, bug fixes, UI refinements, refactoring, dependency updates, infrastructure). Triggered by "review PR", "review changes", "review this code", "check this code", "Android review", code review requests on Kotlin/ViewModel/Composable/Repository/Gradle files, or any time someone asks to look at a diff, PR, or code changes in bitwarden/android.
This skill should be used when writing or reviewing tests for Android code in Bitwarden. Triggered by "BaseViewModelTest", "BitwardenComposeTest", "BaseServiceTest", "stateEventFlow", "bufferedMutableSharedFlow", "FakeDispatcherManager", "expectNoEvents", "assertCoroutineThrows", "createMockCipher", "createMockSend", "asSuccess", "Why is my Bitwarden test failing?", or testing questions about ViewModels, repositories, Compose screens, or data sources in Bitwarden.
Build, test, lint, and deploy commands for the Bitwarden Android project. Use when running tests, building APKs/AABs, running lint/detekt, deploying, using fastlane, or discovering codebase structure. Triggered by "run tests", "build", "gradle", "lint", "detekt", "deploy", "fastlane", "assemble", "verify", "coverage".
Architecture design and phased implementation planning for Bitwarden Android. Use when planning implementation, designing architecture, creating file inventories, or breaking features into phases. Triggered by "plan implementation", "architecture design", "implementation plan", "break this into phases", "what files do I need", "design the architecture".
Requirements gap analysis and structured specification for Bitwarden Android. Use when refining requirements, analyzing specs, identifying gaps, or producing structured specifications from tickets or descriptions. Triggered by "refine requirements", "gap analysis", "spec review", "requirements analysis", "what's missing from this spec", "analyze this ticket".
| name | interacting-with-android-device |
| description | Instructions for capturing UI state, comparing with mocks, and interacting with an Android device using MCP tools backed by ADB. |
| allowed-tools | mcp__android-device__capture, mcp__android-device__find_element, mcp__android-device__tap_at, mcp__android-device__tap_element, mcp__android-device__navigate, mcp__android-device__input_text, Bash(adb:*), Bash(sleep:*), Bash(./gradlew install*:*), Read, Glob |
The android-device MCP server provides 6 tools for device interaction. These replace the previous shell scripts with proper XML parsing, structured dumpsys parsing, and native obstruction detection.
Available tools:
capture — Capture UI hierarchy XML and/or screenshot. Params: { xml?: boolean, screenshot?: boolean }. Default: both.find_element — Find element by text or content-desc, return coordinates with obstruction detection. Params: { text: string }. Returns JSON with coordinates, bounds, and obstruction status.tap_at — Tap at specific coordinates, wait, capture screenshot. Params: { x, y, waitSeconds? }.tap_element — Find, tap, and capture in one call (recommended). Params: { text, waitSeconds? }. Auto-adjusts coordinates when obstructed.navigate — Navigation actions: home, back, app-drawer. Params: { action, waitSeconds? }. Captures screenshot after action.input_text — Type text into the focused field. Params: { text, clear? }. Set clear: true to erase existing content first.Use these MCP tools instead of raw ADB commands to save tokens, get structured results, and benefit from automatic obstruction detection.
To understand what is currently on the device, use the capture tool:
view.xml (UI hierarchy) and screen.png (screenshot) to the working directoryview.xml to find coordinates (bounds) and properties (like text or resource-id) of UI elementsscreen.png for visual verification against design mocksFind and tap an element by text — use tap_element:
This finds the element, detects obstructions, taps (with adjusted coordinates if needed), and captures a screenshot — all in one call.
Tap at specific coordinates — use tap_at:
When you already have coordinates from find_element or manual inspection.
Navigate (home, back, app-drawer) — use navigate:
Performs the action and captures a screenshot.
Find element without tapping — use find_element:
Returns coordinates and full element info. Useful when you need to inspect before acting.
Type text into a field — use input_text:
Types text into the currently focused field. Set clear: true to erase existing content first. Tap the field before calling this if it isn't already focused.
adb shell input keyevent 4adb shell input keyevent 3adb shell input keyevent 66adb shell input swipe <x1> <y1> <x2> <y2> <duration_ms> where:
(x1, y1) = starting point(x2, y2) = ending pointduration_ms = duration in milliseconds (1000ms is typical; adjust for speed/distance)The find_element and tap_element tools automatically detect when another element would intercept the tap. This catches:
dumpsys window windows touchable regionsWhen obstruction is detected:
Follow these steps for a complete UI test:
./gradlew installDebug.capture to dump the UI hierarchy and take a screenshot.tap_element to tap a UI element by text. The tool handles coordinate calculation and obstruction detection automatically.capture again to confirm the UI has updated as expected (e.g., a new screen is shown, or a success message appeared).# Go to home screen
navigate({ action: "home" })
# Open app drawer
navigate({ action: "app-drawer" })
# Find and tap through settings
tap_element({ text: "Settings", waitSeconds: 2 })
tap_element({ text: "System", waitSeconds: 2 })
tap_element({ text: "Software updates", waitSeconds: 2 })
tap_element({ text: "Check for update", waitSeconds: 5 })
For swipe gestures not covered by the navigate tool, use raw ADB:
adb shell input swipe 672 2800 672 500 1000 && sleep 1 && adb shell screencap -p /sdcard/screen.png && adb pull /sdcard/screen.png .
find_element or tap_element over manual coordinate calculation — they handle bounds parsing, center computation, and obstruction detection automaticallyfind_element response to verify you're targeting the correct onecapture after interactions to confirm the UI changed as expectednavigate({ action: "back" }) to recover immediatelycontent-desc and text properties in the UI hierarchy to ensure the UI is accessible for screen readersIf tools report ADB errors:
adb devices to verify the device is visibleIf tools are not listed in /mcp:
.mcp.json at the project root.claude/mcp/android-device-server/ exists with package.jsoncd .claude/mcp/android-device-server && npm install && npm run build