Skip to content

Helper Functions

Functions

Standalone, globally-available utility functions for working with AndroidNode trees. Available alongside the methods on AndroidNode instances.

Overview
// All helper functions are globally available
declare function getAllNodes(rootNode: AndroidNode | null | undefined): AndroidNode[];
declare function buildNodePath(rootNode: AndroidNode | null | undefined, targetNode: AndroidNode | null | undefined): AndroidNode[];
declare function findNodesById(rootNode: AndroidNode | null | undefined, id: string): AndroidNode[];
declare function findNodesByText(rootNode: AndroidNode | null | undefined, text: string): AndroidNode[];
declare function findParentOf(rootNode: AndroidNode | null | undefined, targetNode: AndroidNode | null | undefined): AndroidNode | null;

getAllNodes

Signature
getAllNodes(rootNode: AndroidNode | null | undefined): AndroidNode[]

Returns all nodes in the tree as a flat array. Equivalent to calling rootNode.allNodes() but handles null/undefined input safely.

ParameterTypeDescription
rootNodeAndroidNode | null | undefinedRoot node of the tree to flatten

Returns AndroidNode[]Flat array of all nodes in the tree, or empty array if input is null/undefined

Example
const screen = await agent.actions.screenContent();
const allNodes = getAllNodes(screen);

const buttonCount = allNodes.filter(n =>
  n.className === "android.widget.Button"
).length;

console.log("Total nodes:", allNodes.length);
console.log("Buttons:", buttonCount);
Safe handling of null
// Returns empty array instead of throwing
const nodes = getAllNodes(null); // []

buildNodePath

Signature
buildNodePath(rootNode: AndroidNode | null | undefined, targetNode: AndroidNode | null | undefined): AndroidNode[]

Builds the path from the root node to the target node as an array of nodes. Useful for understanding the hierarchy or debugging.

ParameterTypeDescription
rootNodeAndroidNode | null | undefinedRoot of the tree
targetNodeAndroidNode | null | undefinedTarget node to find path to

Returns AndroidNode[]Array of nodes from root to target, or empty array if path not found

Example
const screen = await agent.actions.screenContent();
const button = screen.findTextOne("Submit");

if (button) {
  const path = buildNodePath(screen, button);
  path.forEach((node, i) => {
    const indent = "  ".repeat(i);
    console.log(indent + (node.className || "unknown"));
  });
}
Debug node location
const target = screen.findByIdOne("com.example:id/hidden_button");
if (target) {
  const path = buildNodePath(screen, target);
  console.log("Button is", path.length, "levels deep");
  console.log("Parent classes:", path.map(n => n.className).join(" > "));
}

findNodesById

Signature
findNodesById(rootNode: AndroidNode | null | undefined, id: string): AndroidNode[]

Finds all nodes with the matching viewId. Equivalent to rootNode.findById(id) but handles null/undefined input.

ParameterTypeDescription
rootNodeAndroidNode | null | undefinedRoot of the tree to search
idstringView ID to search for (e.g., 'com.example:id/button')

Returns AndroidNode[]Array of matching nodes, or empty array if none found

Example
const screen = await agent.actions.screenContent();
const buttons = findNodesById(screen, "com.example:id/action_button");

console.log("Found", buttons.length, "action buttons");
for (const button of buttons) {
  console.log("Button text:", button.text);
}

findNodesByText

Signature
findNodesByText(rootNode: AndroidNode | null | undefined, text: string): AndroidNode[]

Finds all nodes containing the specified text in their text, description, or hintText properties. Case-insensitive search.

ParameterTypeDescription
rootNodeAndroidNode | null | undefinedRoot of the tree to search
textstringText to search for

Returns AndroidNode[]Array of matching nodes, or empty array if none found

Example
const screen = await agent.actions.screenContent();
const submitNodes = findNodesByText(screen, "Submit");

const errorNodes = findNodesByText(screen, "error");
if (errorNodes.length > 0) {
  console.log("Found error message:", errorNodes[0].text);
}

findParentOf

Signature
findParentOf(rootNode: AndroidNode | null | undefined, targetNode: AndroidNode | null | undefined): AndroidNode | null

Finds the parent of the target node within the tree. Alternative to accessing targetNode.parent directly, with null-safe handling.

ParameterTypeDescription
rootNodeAndroidNode | null | undefinedRoot of the tree
targetNodeAndroidNode | null | undefinedNode to find parent of

Returns AndroidNode | nullParent node, or null if not found or target is root

Example
const screen = await agent.actions.screenContent();
const button = screen.findTextOne("Submit");

if (button) {
  const parent = findParentOf(screen, button);
  if (parent) {
    console.log("Parent class:", parent.className);
    console.log("Parent has", parent.children.length, "children");
  }
}
Find containing form
const input = screen.findAdvanced(f => f.isEditText());
if (input) {
  let current = input;
  let parent = findParentOf(screen, current);

  while (parent) {
    if (parent.viewId?.includes("form")) {
      console.log("Found form container:", parent.viewId);
      break;
    }
    current = parent;
    parent = findParentOf(screen, current);
  }
}

Helper Functions vs Instance Methods

Use helper functions when the root node might be null/undefined, when you want consistent null-safe behavior, prefer a functional style, or work with nodes from potentially failed operations. Use instance methods when you have a guaranteed non-null AndroidNode, are chaining operations fluently, need the advanced filter builder pattern, or want more concise code.
Comparison
// Using helper functions (null-safe)
const allNodes = getAllNodes(screen);
const byId = findNodesById(screen, "com.example:id/btn");
const byText = findNodesByText(screen, "Submit");

// Using instance methods (requires non-null node)
const allNodes2 = screen.allNodes();
const byId2 = screen.findById("com.example:id/btn");
const byText2 = screen.findText("Submit");

// Instance methods also provide advanced filtering
const filtered = screen.filterAdvanced(f => f.isButton().isClickable());