# EXTRACT_TEXT 与 EXTRACT > [返回动作目录](README.md) · [统一选择器](../selector.md) · [值与输出](../values-and-outputs.md) ## 1. EXTRACT_TEXT **[已实现]** ~~~json { "id": "read-status", "action": "EXTRACT_TEXT", "packageName": "com.example.target", "selector": { "resourceId": "com.example.target:id/status" }, "outputField": "status", "timeoutMs": 3000 } ~~~ 当前行为: - 等待 selector 匹配唯一节点。 - 优先读取 text,空时读取 contentDescription。 - trim 后为空则继续等待。 - 把非空文字追加到 `outputField` 对应的字符串列表。 - 不自动滚动。 ## 2. EXTRACT **[提案]** EXTRACT 用于读取一个或多个节点的明确字段: ~~~json { "id": "read-items", "action": "EXTRACT", "packageName": "com.example.target", "selector": { "className": "android.widget.TextView", "state": { "visible": true } }, "cardinality": "MANY", "fields": [ { "name": "text", "source": "TEXT", "type": "TEXT", "trim": true } ], "outputField": "items", "timeoutMs": 5000 } ~~~ 首批字段来源: - `TEXT` - `CONTENT_DESCRIPTION` - `RESOURCE_ID` - `CLASS_NAME` - `BOUNDS` - `CHECKED`、`SELECTED`、`ENABLED` 首批类型只需 `TEXT`、`INTEGER`、`DECIMAL` 和 `BOOLEAN`。转换失败明确返回错误,不使用默认值代替。 `cardinality` 支持 `ONE` 和 `MANY`。MANY 按控件树顺序输出;排序、去重和复杂对象分组等到实际需求出现时再增加。 ## 3. 执行规则 1. 等待包名、Activity 和 selector。 2. 按 cardinality 校验数量。 3. 从同一页面快照读取声明字段。 4. 完成 trim 和简单类型转换。 5. 所有值都成功后一次性发布 output。 EXTRACT 不点击、不滚动、不读取未声明字段,也不保存完整控件树。 ## 4. 结果码 见[结果码总表](README.md#结果码总表)。EXTRACT 使用 `OK`、`TARGET_NOT_FOUND`、`TARGET_AMBIGUOUS` 和 `ACTION_FAILED`(文本为空、字段缺失或类型转换失败)。 字段缺失与类型转换失败是否需要独立码,等 EXTRACT 实现时按实际排查需要决定,不提前登记。 ## 5. 兼容方式 EXTRACT_TEXT 保留现有字符串列表结果。实现 EXTRACT 后,可以在内部把 EXTRACT_TEXT 转换为 ONE + TEXT 读取,但对外结果结构保持不变。 ## 6. 测试 覆盖 text、contentDescription 回退、空文本、多个节点、MANY、字段缺失、类型转换、总超时和不自动滚动。