UI Inspection¶
Retrieving the current Android UI hierarchy (uiautomator dump) as inline
XML, and searching it by structured criteria (find_ui_elements,
wait_for_ui_element). For touch and key injection, see input.
dump_ui_hierarchy
¶
Retrieve the device's current UI hierarchy: uiautomator dump.
uiautomator dump only writes its result to a file on the device, so
this dumps to a temporary path under /data/local/tmp, reads the XML
back inline over adb shell (no host filesystem write, no local_root
needed — the caller never has to know or manage the device-side path),
and always removes the temporary file afterward. To search the
hierarchy without handling XML yourself, use find_ui_elements; this
module doesn't inject any input actions (see the input module for that).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
Returns:
| Type | Description |
|---|---|
UiHierarchyDumpResult
|
The serial, the full hierarchy xml (the raw |
Error handling
An unknown serial or unresponsive adb binary raises
DEVICE_NOT_FOUND/ADB_UNAVAILABLE. uiautomator dump itself failing
to run (e.g. the uiautomator binary is missing on this build)
raises UIAUTOMATOR_FAILED. The command running but finding no
inspectable window content right now (screen off, locked, or
otherwise no accessible root node) raises
UI_HIERARCHY_UNAVAILABLE — distinct from an empty-but-successful
hierarchy, which is returned as data with node_count=0, not raised.
A permission rejection raises PERMISSION_DENIED; the dumped temp
file vanishing before it could be read back raises
REMOTE_FILE_NOT_FOUND; any other failure raises a generic
BACKEND_ERROR.
Example
Called with serial="emulator-5554". A typical response:
{
"status": "success",
"message": "Dumped UI hierarchy (2 nodes) from emulator-5554.",
"data": {
"serial": "emulator-5554",
"xml": "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><hierarchy rotation=\"0\">...</hierarchy>",
"node_count": 2,
"success": true,
"output": "UI hierarchy dumped to: /data/local/tmp/adb_automation_mcp_ui_dump_....xml\n"
},
"error": null
}
find_ui_elements
¶
Search the current UI hierarchy for nodes matching structured criteria.
Captures the hierarchy the same way dump_ui_hierarchy does, then
filters <node> elements in Python and returns each match flattened to
the attributes callers act on (text, resource_id, class, bounds + the
bounds' center point, and the usual boolean state flags). At least one
criterion must be given; all supplied criteria are combined with AND.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
text
|
str | None
|
Match nodes whose |
None
|
text_contains
|
str | None
|
Match nodes whose |
None
|
resource_id
|
str | None
|
Match nodes by resource-id — either the full "package:id/name" or just the bare "name" (which also matches a Compose testTag surfaced as a prefix-less resource-id). |
None
|
content_desc
|
str | None
|
Match nodes whose |
None
|
class_name
|
str | None
|
Match nodes by class — either the fully-qualified name ("android.widget.Button") or just the final segment ("Button"). |
None
|
package
|
str | None
|
Match nodes whose |
None
|
clickable
|
bool | None
|
Match nodes whose |
None
|
enabled
|
bool | None
|
Match nodes whose |
None
|
limit
|
int
|
Maximum number of matched elements to return (1-500, default 50). match_count still reports the true total; truncated says whether the list was cut. |
50
|
Returns:
| Type | Description |
|---|---|
UiElementMatchResult
|
The serial, match_count (total matches), returned_count (how many are in elements), truncated, and elements — each an object with text / resource_id / class_name / package / content_desc, the boolean flags (clickable, enabled, focused, checkable, checked, selected, scrollable, long_clickable, password), and bounds ({left, top, right, bottom, center_x, center_y} or null). Zero matches is a normal success result. |
Error handling
No criteria at all, or a limit outside 1-500, is rejected before any device round-trip (INVALID_ARGUMENT). An unknown serial or unresponsive adb binary raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE; uiautomator failing raises UIAUTOMATOR_FAILED; no inspectable window content right now raises UI_HIERARCHY_UNAVAILABLE. A malformed / truncated hierarchy is treated as zero matches, not a crash. Other failures raise PERMISSION_DENIED / REMOTE_FILE_NOT_FOUND / BACKEND_ERROR as for dump_ui_hierarchy.
Example
Called with serial="emulator-5554", text="Phone". A typical response:
{
"status": "success",
"message": "1 UI element(s) matched on emulator-5554.",
"data": {
"serial": "emulator-5554",
"match_count": 1,
"returned_count": 1,
"truncated": false,
"elements": [
{
"text": "Phone",
"resource_id": "com.android.launcher3:id/icon",
"class_name": "android.widget.TextView",
"package": "com.android.launcher3",
"content_desc": "Phone",
"clickable": true,
"enabled": true,
"focused": false,
"checkable": false,
"checked": false,
"selected": false,
"scrollable": false,
"long_clickable": true,
"password": false,
"bounds": {"left": 100, "top": 200, "right": 300, "bottom": 400, "center_x": 200, "center_y": 300}
}
]
},
"error": null
}
wait_for_ui_element
¶
Poll the UI hierarchy until an element appears or disappears.
Re-captures the hierarchy every poll_interval_s and re-checks the same
structured criteria as find_ui_elements, until the condition holds or
timeout_s elapses. Replaces blind sleeps in automation. The loop is
always bounded — timeout_s is capped at 120s and poll_interval_s at
30s. At least one criterion must be given (AND-combined).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
serial
|
str
|
The target device's adb serial (see list_connected_devices). |
required |
condition
|
WaitCondition
|
"present" (default) waits until at least one node matches; "absent" waits until no node matches. |
'present'
|
timeout_s
|
float
|
Maximum seconds to keep polling (0 exclusive to 120). Default 10. |
10.0
|
poll_interval_s
|
float
|
Seconds between hierarchy captures (0.1 to 30). Default 1. |
1.0
|
text
|
str | None
|
Match nodes whose |
None
|
text_contains
|
str | None
|
Match nodes whose |
None
|
resource_id
|
str | None
|
Match by full "package:id/name" or bare "name". |
None
|
content_desc
|
str | None
|
Match nodes whose |
None
|
class_name
|
str | None
|
Match by fully-qualified class or final segment. |
None
|
package
|
str | None
|
Match nodes whose |
None
|
clickable
|
bool | None
|
Match nodes whose |
None
|
enabled
|
bool | None
|
Match nodes whose |
None
|
Returns:
| Type | Description |
|---|---|
UiWaitResult
|
The serial, condition, satisfied (always True on return), match_count and elements at the moment the condition held (for "absent" that's 0 / []), waited_s (roughly how long the loop ran), and poll_count (how many captures it took). |
Error handling
No criteria, an out-of-range timeout_s / poll_interval_s, or a bad condition is rejected before any device round-trip (INVALID_ARGUMENT). The condition never holding within timeout_s raises TIMEOUT (retryable), with the last seen match count in its details. An unknown serial / adb failure raises DEVICE_NOT_FOUND/ADB_UNAVAILABLE; uiautomator or hierarchy failures raise UIAUTOMATOR_FAILED / UI_HIERARCHY_UNAVAILABLE / PERMISSION_DENIED / BACKEND_ERROR as for dump_ui_hierarchy.
Example
Called with serial="emulator-5554", text="Success", timeout_s=5. A typical response:
{
"status": "success",
"message": "UI condition 'present' satisfied on emulator-5554 after 1.2s (2 check(s)).",
"data": {
"serial": "emulator-5554",
"condition": "present",
"satisfied": true,
"match_count": 1,
"waited_s": 1.2,
"poll_count": 2,
"elements": [{"text": "Success", "resource_id": "", "class_name": "android.widget.TextView", "package": "com.example.app", "content_desc": "", "clickable": false, "enabled": true, "focused": false, "checkable": false, "checked": false, "selected": false, "scrollable": false, "long_clickable": false, "password": false, "bounds": null}]
},
"error": null
}