Skip to content

For Each Element In Screen

Summary

  • Internal name: ForEachElementInScreen
  • Category: Android UI
  • Purpose: Run a nested sub-workflow once per accessibility node currently on screen, exposing each node's text, content description, center position, and clickable flags in loop variables.
  • Task type: Connector - see Tasks Overview > Connector Tasks for what this means before reading further.

Compatibility

  • Minimum AndroMate version: 1.1.0
  • Maximum AndroMate version: 1.1.0
  • Minimum Android: Android 13 (API 33)
  • Maximum Android tested: Android 16 (API 36)
  • Supported manufacturers:

    • Samsung (One UI 6.x / 7.x / 8.x)
    • Other manufacturers - not supported yet (Xiaomi HyperOS and Google Pixel are being adapted)
    • Required permissions:
    • ACCESSIBILITY_SERVICE (plus whatever tasks are placed inside "do" require)

Detailed description

The For Each Element In Screen task walks the accessibility tree of the active window in traversal order (the same order as Get Screen Elements) and runs the sub-workflow embedded under "do" once per node - the screen-element counterpart to ForEachElement's list iteration.

Each of the six output variables is independent and optional: leave a "*_variable_input" field empty (or omit it) to skip that one - e.g. if you only care about position, don't set text_variable_input. Unlike ForEachElement, an unset variable name is never an error; it simply means "don't expose this one."

In the outer graph, ForEachElementInScreen behaves like a normal task - one incoming link, one outgoing "to" link, followed once every node has been processed.


Input parameters

Parameter Type Required Possible values Android Compatibility AndroMate Compatibility Default
text_variable_input String No A $variable name, or empty to skip Android 13 (API 33) -> Android 16 (API 36) 1.1.0 -> 1.1.0 ""
contentDescription_variable_input String No A $variable name, or empty to skip Android 13 (API 33) -> Android 16 (API 36) 1.1.0 -> 1.1.0 ""
x_variable_input String No A $variable name, or empty to skip Android 13 (API 33) -> Android 16 (API 36) 1.1.0 -> 1.1.0 ""
y_variable_input String No A $variable name, or empty to skip Android 13 (API 33) -> Android 16 (API 36) 1.1.0 -> 1.1.0 ""
isClickable_variable_input String No A $variable name, or empty to skip Android 13 (API 33) -> Android 16 (API 36) 1.1.0 -> 1.1.0 ""
isLongClickable_variable_input String No A $variable name, or empty to skip Android 13 (API 33) -> Android 16 (API 36) 1.1.0 -> 1.1.0 ""
do Object (sub-workflow) Yes A nested workflow object - see Iterate's The do sub-workflow for the shape (identical here) Android 13 (API 33) -> Android 16 (API 36) 1.1.0 -> 1.1.0 -

Output parameters

The For Each Element In Screen task itself produces no outputs. Any variable written by a task inside "do" updates the shared workflow context normally, as if that task ran directly in the outer graph. The six *_variable_input fields are per-iteration loop variables (see Output parameter details), not persistent task outputs.


Exceptions

Code Exception Name Description
SCREEN-AUTOMATOR-ERROR-010 Screen Automator Service Not Connected The AndroMate accessibility service isn't enabled/connected.
CONNECTOR-TASK-ERROR-001 No Sub Tasks The "do" field is missing or empty - a connector task must contain a sub-workflow to run.

Note: an unset *_variable_input is not an error - that output is simply skipped for every iteration. An empty screen (no nodes) is also not an error - the loop simply runs zero times.


Execution flowchart

flowchart TD
    Start([ForEachElementInScreen]) --> CheckConnected{Accessibility service\nconnected?}
    CheckConnected -->|No| E1[SCREEN-AUTOMATOR-ERROR-010\nSERVICE_NOT_CONNECTED]
    CheckConnected -->|Yes| CheckDo{do sub-workflow\npresent?}
    CheckDo -->|No| E2[CONNECTOR-TASK-ERROR-001\nNO_SUB_TASKS]
    CheckDo -->|Yes| Walk["Walk accessibility tree\n(traversal order)"]
    Walk --> CheckNode{More nodes?}
    CheckNode -->|No| Continue[Follow outer 'to' link]
    CheckNode -->|Yes| SetVars[Set any defined\n*_variable_input for this node]
    SetVars --> RunSub[Run do sub-workflow]
    RunSub --> CheckNode

    Continue --> Success([VoidResult])
    E1 --> Error([Exception])
    E2 --> Error

    style Start fill:#e3f2fd
    style Success fill:#c8e6c9
    style Error fill:#ffcdd2
    style RunSub fill:#fff9c4
    style SetVars fill:#c8e6c9
    style Walk fill:#f3e5f5

How it works:

  1. Check connection: fails fast with SERVICE_NOT_CONNECTED if the accessibility service isn't enabled.
  2. Check do: raises CONNECTOR-TASK-ERROR-001 if the sub-workflow is missing or empty.
  3. Walk: visits every node of the active window, in traversal order.
  4. Per node: sets whichever of the six *_variable_input fields are non-empty (text, contentDescription, center x/y, isClickable, isLongClickable - as strings, isClickable/isLongClickable as "true"/"false"), then runs the "do" sub-workflow to completion.
  5. Continue: once every node has been processed (or immediately, if the screen has none), the engine follows the outer "to" link.

Code examples

Example 1 - Log every clickable element's text

{
  "Start": [
    {
      "id": "0",
      "variables": [
        { "variableName": "$text", "variableValue": "", "is_kpi": false },
        { "variableName": "$clickable", "variableValue": "", "is_kpi": false }
      ]
    }
  ],
  "ForEachElementInScreen": [
    {
      "id": "1",
      "title": "Log clickable elements",
      "text_variable_input": "$text",
      "isClickable_variable_input": "$clickable",
      "do": {
        "StartSubTask": [{ "id": "sub-0" }],
        "TextReport": [
          { "id": "sub-1", "texte": "$text", "texte_type": "Info Text" }
        ],
        "End": [{ "id": "sub-100" }],
        "Links": [
          { "from": "sub-0", "to": "sub-1" },
          { "from": "sub-1", "to": "sub-100" }
        ]
      }
    }
  ],
  "End": [{ "id": "100" }],
  "Links": [
    { "from": "0", "to": "1" },
    { "from": "1", "to": "100" }
  ]
}

Input parameter details

1-6. Input parameters: text_variable_input, contentDescription_variable_input, x_variable_input, y_variable_input, isClickable_variable_input, isLongClickable_variable_input

Each names a $variable to receive one piece of data about the current node, on every iteration. All six are independent - set only the ones you need.

Example

"text_variable_input": "$text",
"x_variable_input": "$x",
"y_variable_input": "$y"

7. Input parameter: do

The embedded sub-workflow, run once per node. See Iterate's The do sub-workflow for its shape.


Output parameter details

This task has no persistent output of its own. Per iteration, before running "do", it writes into whichever of these variables you named:

Variable Value
text_variable_input The node's visible text, or empty if none.
contentDescription_variable_input The node's content description, or empty if none.
x_variable_input The center X of the node's screen bounds (the point you'd feed into Click In (x, y)).
y_variable_input The center Y of the node's screen bounds.
isClickable_variable_input "true" or "false" (AndroMateContext has no boolean type - stored as a string).
isLongClickable_variable_input "true" or "false", same as above.

Complete JSON example

Clicks the first element whose text is exactly "Allow", found while iterating every element on screen:

{
  "Start": [
    {
      "id": "0",
      "variables": [
        { "variableName": "$text", "variableValue": "", "is_kpi": false },
        { "variableName": "$x", "variableValue": "", "is_kpi": false },
        { "variableName": "$y", "variableValue": "", "is_kpi": false }
      ]
    }
  ],
  "ForEachElementInScreen": [
    {
      "id": "1",
      "title": "Find and click Allow",
      "text_variable_input": "$text",
      "x_variable_input": "$x",
      "y_variable_input": "$y",
      "do": {
        "StartSubTask": [{ "id": "sub-0" }],
        "CompareStrings": [
          { "id": "sub-1", "var_x": "$text", "var_y": "Allow", "compare_type": "exactText" }
        ],
        "ClickInXY": [
          { "id": "sub-2", "ClickInXY_X": "$x", "ClickInXY_Y": "$y" }
        ],
        "End": [{ "id": "sub-100" }],
        "Links": [
          { "from": "sub-0", "to": "sub-1" },
          { "from": "sub-1", "to": "sub-2", "condition": "true" },
          { "from": "sub-1", "to": "sub-100", "condition": "false" },
          { "from": "sub-2", "to": "sub-100" }
        ]
      }
    }
  ],
  "End": [{ "id": "100" }],
  "Links": [
    { "from": "0", "to": "1" },
    { "from": "1", "to": "100" }
  ]
}