Automation API

Android device automation

AndroidNodeFilter

Interface

Builder pattern for complex node queries

AndroidNodeFilter provides a fluent builder interface for constructing complex queries to find nodes in the accessibility tree. All methods are chainable and return the filter instance.

Basic Usage
TypeScript
// Find a submit button
const button = screen.findAdvanced(f => f.isButton().hasText("Submit"));
// Find all editable text fields
const inputs = screen.filterAdvanced(f => f.isEditText().isEditable());
// Complex query with multiple conditions
const node = screen.findAdvanced(f =>
f.isClickable()
.hasPackageName("com.example.app")
.anyParent(p => p.hasId("com.example:id/main_container"))
);

Class Matchers

Match nodes based on their Android class type.

isButton()

TypeScript
isButton(): AndroidNodeFilter

Matches nodes with className 'android.widget.Button'.

Examples

TypeScript
const buttons = screen.filterAdvanced(f => f.isButton());

isText()

TypeScript
isText(): AndroidNodeFilter

Matches nodes with className 'android.widget.TextView'.

Examples

TypeScript
const labels = screen.filterAdvanced(f => f.isText());

isImage()

TypeScript
isImage(): AndroidNodeFilter

Matches nodes with className 'android.widget.ImageView'.

Examples

TypeScript
const images = screen.filterAdvanced(f => f.isImage());

isEditText()

TypeScript
isEditText(): AndroidNodeFilter

Matches nodes with className 'android.widget.EditText' (text input fields).

Examples

TypeScript
const inputs = screen.filterAdvanced(f => f.isEditText());

isCheckBox()

TypeScript
isCheckBox(): AndroidNodeFilter

Matches nodes with className 'android.widget.CheckBox'.

Examples

TypeScript
const checkboxes = screen.filterAdvanced(f => f.isCheckBox());

isRadioButton()

TypeScript
isRadioButton(): AndroidNodeFilter

Matches nodes with className 'android.widget.RadioButton'.

Examples

TypeScript
const radios = screen.filterAdvanced(f => f.isRadioButton());

isSwitch()

TypeScript
isSwitch(): AndroidNodeFilter

Matches nodes with className 'android.widget.Switch'.

Examples

TypeScript
const switches = screen.filterAdvanced(f => f.isSwitch());

isSeekBar()

TypeScript
isSeekBar(): AndroidNodeFilter

Matches nodes with className 'android.widget.SeekBar'.

Examples

TypeScript
const sliders = screen.filterAdvanced(f => f.isSeekBar());

isViewGroup()

TypeScript
isViewGroup(): AndroidNodeFilter

Matches nodes with className 'android.view.ViewGroup' (container elements).

Examples

TypeScript
const containers = screen.filterAdvanced(f => f.isViewGroup());

is()

TypeScript
is(className: string): AndroidNodeFilter

Matches nodes with a custom className.

Parameters

NameTypeDescription
classNamestringFull Android class name to match

Examples

TypeScript
const recyclers = screen.filterAdvanced(f => f.is("androidx.recyclerview.widget.RecyclerView"));

State Matchers

Match nodes based on their current state.

isClickable()

TypeScript
isClickable(): AndroidNodeFilter

Matches nodes that are clickable.

Examples

TypeScript
const clickables = screen.filterAdvanced(f => f.isClickable());

isScrollable()

TypeScript
isScrollable(): AndroidNodeFilter

Matches nodes that are scrollable.

Examples

TypeScript
const scrollView = screen.findAdvanced(f => f.isScrollable());
if (scrollView) {
await scrollView.performAction(agent.constants.ACTION_SCROLL_DOWN);
}

isSelected()

TypeScript
isSelected(): AndroidNodeFilter

Matches nodes that are currently selected.

Examples

TypeScript
const selectedItem = screen.findAdvanced(f => f.isSelected());

isEditable()

TypeScript
isEditable(): AndroidNodeFilter

Matches nodes that allow text editing.

Examples

TypeScript
const editableInputs = screen.filterAdvanced(f => f.isEditText().isEditable());

Content Matchers

Match nodes based on their text content.

hasText()

TypeScript
hasText(text: string): AndroidNodeFilter

Matches nodes with exact text content.

Parameters

NameTypeDescription
textstringExact text to match

Examples

TypeScript
const submitBtn = screen.findAdvanced(f => f.isButton().hasText("Submit"));

text()

TypeScript
text(condition: (text: string | undefined) => boolean): AndroidNodeFilter

Matches nodes based on a custom text condition.

Parameters

NameTypeDescription
condition(text: string | undefined) => booleanFunction to test the text

Examples

Contains
TypeScript
const priceNodes = screen.filterAdvanced(f => f.text(t => t?.includes("$") ?? false));
Starts with
TypeScript
const items = screen.filterAdvanced(f => f.text(t => t?.startsWith("Item") ?? false));

hasDescription()

TypeScript
hasDescription(description: string): AndroidNodeFilter

Matches nodes with exact content description (accessibility label).

Parameters

NameTypeDescription
descriptionstringExact description to match

Examples

TypeScript
const closeBtn = screen.findAdvanced(f => f.hasDescription("Close"));

descriptionContains()

TypeScript
descriptionContains(part: string): AndroidNodeFilter

Matches nodes whose description contains the given text.

Parameters

NameTypeDescription
partstringText to search for in description

Examples

TypeScript
const icons = screen.filterAdvanced(f => f.isImage().descriptionContains("icon"));

description()

TypeScript
description(condition: (desc: string | undefined) => boolean): AndroidNodeFilter

Matches nodes based on a custom description condition.

Parameters

NameTypeDescription
condition(desc: string | undefined) => booleanFunction to test the description

Examples

TypeScript
const nodes = screen.filterAdvanced(f =>
f.description(d => d?.toLowerCase().includes("button") ?? false)
);

hasChildWithText()

TypeScript
hasChildWithText(text: string): AndroidNodeFilter

Matches nodes that have a direct child with the specified text.

Parameters

NameTypeDescription
textstringText to find in children

Examples

TypeScript
// Find containers that have a "Settings" label inside
const settingsSection = screen.findAdvanced(f =>
f.isViewGroup().hasChildWithText("Settings")
);

Identity Matchers

Match nodes based on their identity attributes.

hasId()

TypeScript
hasId(id: string): AndroidNodeFilter

Matches nodes with the specified viewId.

Parameters

NameTypeDescription
idstringView ID to match (e.g., 'com.example:id/button')

Examples

TypeScript
const header = screen.findAdvanced(f => f.hasId("com.example:id/header_title"));

hasPackageName()

TypeScript
hasPackageName(packageName: string): AndroidNodeFilter

Matches nodes belonging to the specified package.

Parameters

NameTypeDescription
packageNamestringPackage name to match

Examples

TypeScript
// Only match nodes from a specific app
const appNodes = screen.filterAdvanced(f =>
f.hasPackageName("com.example.myapp")
);

hasChildWithId()

TypeScript
hasChildWithId(id: string): AndroidNodeFilter

Matches nodes that have a direct child with the specified viewId.

Parameters

NameTypeDescription
idstringView ID to find in children

Examples

TypeScript
// Find containers with specific child elements
const container = screen.findAdvanced(f =>
f.hasChildWithId("com.example:id/item_icon")
);

Logical Operators

Combine multiple conditions using logical operators.

and()

TypeScript
and(filterBuilder: (f: AndroidNodeFilter) => void): AndroidNodeFilter

Combines with another filter using AND logic. The node must match both filters.

Parameters

NameTypeDescription
filterBuilder(f: AndroidNodeFilter) => voidFunction to build the additional filter

Examples

TypeScript
// Find clickable buttons with specific text
const btn = screen.findAdvanced(f =>
f.isButton().and(a => a.isClickable().hasText("Submit"))
);

or()

TypeScript
or(filterBuilder: (f: AndroidNodeFilter) => void): AndroidNodeFilter

Combines with another filter using OR logic. The node must match either filter.

Parameters

NameTypeDescription
filterBuilder(f: AndroidNodeFilter) => voidFunction to build the alternative filter

Examples

Match buttons OR clickable images
TypeScript
const clickables = screen.filterAdvanced(f =>
f.isButton().or(o => o.isImage().isClickable())
);
Match multiple text options
TypeScript
const node = screen.findAdvanced(f =>
f.hasText("OK").or(o => o.hasText("Confirm")).or(o => o.hasText("Yes"))
);

Hierarchy Matchers

Match nodes based on their position in the node hierarchy.

parent()

TypeScript
parent(filterBuilder: (f: AndroidNodeFilter) => void): AndroidNodeFilter

Matches nodes whose immediate parent matches the given filter.

Parameters

NameTypeDescription
filterBuilder(f: AndroidNodeFilter) => voidFunction to build the parent filter

Examples

TypeScript
// Find text views inside a specific container
const labels = screen.filterAdvanced(f =>
f.isText().parent(p => p.hasId("com.example:id/header"))
);

anyParent()

TypeScript
anyParent(filterBuilder: (f: AndroidNodeFilter) => void): AndroidNodeFilter

Matches nodes that have any ancestor matching the given filter.

Parameters

NameTypeDescription
filterBuilder(f: AndroidNodeFilter) => voidFunction to build the ancestor filter

Examples

Find items inside a specific list
TypeScript
const listItems = screen.filterAdvanced(f =>
f.isText().anyParent(p => p.hasId("com.example:id/user_list"))
);
Find clickables inside a dialog
TypeScript
const dialogButtons = screen.filterAdvanced(f =>
f.isClickable().anyParent(p => p.is("android.app.Dialog"))
);

Complex Examples

Find login button in a specific form
TypeScript
const loginBtn = screen.findAdvanced(f =>
f.isButton()
.hasText("Login")
.isClickable()
.anyParent(p => p.hasId("com.example:id/login_form"))
);
Find all product prices
TypeScript
const prices = screen.filterAdvanced(f =>
f.isText()
.text(t => /^\$\d+/.test(t || ""))
.anyParent(p => p.hasId("com.example:id/product_card"))
);
for (const price of prices) {
console.log("Price:", price.text);
}
Find first empty input field
TypeScript
const emptyInput = screen.findAdvanced(f =>
f.isEditText()
.isEditable()
.text(t => !t || t.length === 0)
);
if (emptyInput) {
await emptyInput.performAction(agent.constants.ACTION_CLICK);
await agent.actions.writeText("Hello");
}
Find any confirmation button
TypeScript
const confirmBtn = screen.findAdvanced(f =>
f.isButton()
.isClickable()
.or(o => o.hasText("OK"))
.or(o => o.hasText("Confirm"))
.or(o => o.hasText("Yes"))
.or(o => o.hasText("Accept"))
);