如何检测系统对话框中的所有视图和文本?

How to detect all Views and text inside a system dialog?

假设我有类似的情况:

我正在使用无障碍服务,以便在出现此对话框时与我的 TTS 引擎对话,但我唯一能够检测到的是可选择的视图(箭头所指的视图)。 有什么方法可以检测对话框中的标题和(更重要的)整个文本吗?

是的。我认为您很可能是从专注于单个节点的可访问性事件中获取这些项目。您要做的是查看整个视图层次结构。您可以通过以下两种方式之一执行此操作。首先要注意的是,可访问性节点是一棵树。就像视图层次结构是一棵树一样。事实上,这棵树与视图层次结构几乎是 1 比 1 匹配。开发人员可以强制某个元素不包含在视图层次结构中,尽管在实践中并不经常这样做。即使他们这样做了,您仍然可以获得这些信息。假设我们需要此信息。我们要做的第一件事是确保它包含在内。

protected void onServiceConnected() {
    super.onServiceConnected();

    AccessibilityServiceInfo tempInfo = getServiceInfo();
    tempInfo.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
    setServiceInfo(tempInfo);

}

您很可能可以跳过此步骤,但以防万一!

之后就很简单了。首先,为了让您可以看到这些信息在哪里,让我们编写一个可爱的小日志功能。

public static void logNodeHeirarchy(AccessibilityNodeInfo nodeInfo, int depth) {

    if (nodeInfo == null) return;

    String logString = "";

    for (int i = 0; i < depth; ++i) {
        logString += " ";
    }

    logString += "Text: " + nodeInfo.getText() + " " + " Content-Description: " + nodeInfo.getContentDescription();

    Log.v(LOG_TAG, logString);

    for (int i = 0; i < nodeInfo.getChildCount(); ++i) {
        logNodeHeirarchy(nodeInfo.getChild(i), depth + 1);
    }
}

此函数应记录可访问性节点的整个树。将其作为静态函数添加到您的辅助功能服务中。现在我们只需要在根节点上调用它。您可以轻松更改记录的属性。我发现文本、内容描述和视图 ID 是最有用的。

@Override
public void onAccessibilityEvent(AccessibilityEvent e) {

    switch (e.getEventType()) {
        case AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED: {
            logNodeHeirarchy(getRootInActiveWindow(), 0);
        }
    }
}

这应该能让您看到信息的位置。您所要做的就是弄清楚如何解析它。注意:您也可以使用 getParent() 从叶节点向上爬取。