AccessibilityNodeInfo 的生命周期是怎样的?

问题描述 投票:0回答:2

我正在开发一个 Android 应用程序,其中包含一个辅助功能服务,允许用户创建“宏”,可以快速、自动地执行他们经常使用他们已经使用的第三方应用程序执行的任务(而不必与他们使用的某些对讲服务进行交互)等待事情被列出,然后必须在一个非常缓慢的过程中一遍又一遍地说出他们想要做的每件事)。我的问题是,我似乎无法找到有关 AccessibilityNodeInfo 对象生命周期的详细文档。例如,如果宏设置为“打开此应用程序并单击“执行”按钮,然后列出所有结果”,我可能需要等待并收集应用程序中的增量更新,因为结果可能会跨多个 WINDOW_CONTENT_CHANGED 事件出现,其中每个仅包含应用程序正在构建的总结果列表的子集。我可以使用 findViewById 之类的东西来获取我想要的元素,但是将它们保留在多个事件中是一个坏主意,因为 android 操作系统可以随时使它们无效/更改它们?我想知道是否有任何我错过的文档/示例可以更清楚地说明如何最好地交互accessibilityNodeInfo对象,以及如何/是否可以随着时间的推移缓存或收集它们以获得更完整和一致的内容的了解应用程序的布局。

我看过有关accessibilitynodeinfo的其他帖子,例如(Android AccessibilityNodeInfo刷新()和回收()),但这仍然不能回答诸如节点何时无效或如果我不回收节点并尝试会发生什么等问题稍后使用它(特别是如果该元素已被应用程序删除)。我想要回答的问题属于下面代码中的类型:

//for caching nodes... bad idea?
HashMap<String,AccessibilityNodeInfo> cachedNodes = new HashMap<>();

//gets fired for lots of reasons, can contain arbitrary subsets of the total app layout hierarchy (appears upper bounded by what is visible on the screen)
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    // my accessibility service is listening to all event types
    AccessibilityNodeInfo nodeInfo = event.getSource();
    //sometimes the node is just totally null... why??
    if(nodeInfo != null){
        //what is this really doing? Why is this node sometimes different from traversing up the hierarchy with getParent() manually?
        rootNode = getRootInActiveWindow();
        if(rootNode == null) {
            rootNode = nodeInfo;
            AccessibilityNodeInfo parent = nodeInfo.getParent();
            while(parent != null){
                rootNode = parent;
                parent = rootNode.getParent();
            }
        }
        //It appears this method returns all matches in the event hierarchy regardless of which node you call it on?
        List<AccessibilityNodeInfo> nodesOfInterest = rootNode.findAccessibilityNodeInfosByViewId("package.name/id_of_nodes_i_want");
        for(AccessibilityNodeInfo node: nodesOfInterest){
            //my accessibility service is set up to be able to get view ids and retrieve window content, but view ids are not unique
            // may have to compose an ID based on the view type lineage of the node?
            if(!cachedNodes.containsKey(getUniqueID(node)){
                cachedNodes.put(getUniqueID(node),node);
            }
        }
    }

}
java android accessibilityservice
2个回答
0
投票

AccessibilityNodeInfo or AccessibilityNodeInfoCompat
(用于后台兼容性) 不是视图。

当您打开手机的任何屏幕时,其称为窗口的内容,该内容以可访问性节点信息树的形式呈现。

有时你会得到

AccessibilityNodeInfo
为 null,但刷新后,你可以获得该特定节点的值。

accessibilityNodeInfo.refresh();

使用它所代表的视图的最新状态刷新此信息。

您可以访问此获取更多信息。辅助功能节点信息


0
投票

当您处理 Android Accessibility Service 层时,需要记住一件最重要的事情。

  1. 几乎所有内容都是为了性能而构建。

包括创建一个 AccessibilityNodeInfos 池,以便这些东西可以在内存中彼此相邻,等等。

因此,要回答有关生命周期的大问题......不要认为节点具有生命周期。或者更确切地说,您不拥有内存,并且在任何函数之外,无论您喜欢与否,节点属性对您来说都毫无意义:)。

现在,关于一些评论问题。

有时节点完全为空......为什么?

您正在收听 EVENT_TYPE_ALL...并非所有事件都有有意义的来源。例如:不知从何而来的通知事件、公告事件等

这到底是做什么的?为什么这个节点有时与手动使用 getParent() 向上遍历层次结构不同?

您几乎总是会期望:

event.getSource() != getRootInActiveWindow()

因为辅助事件的来源是视图层次结构的根视图的情况非常罕见。

看来这个方法会返回事件层次结构中的所有匹配项,无论您在哪个节点上调用它?

我不相信函数在大多数情况下会做任何有意义的事情。我不认为你所比较的“ID”意味着你认为的意思。您可能只想与

AccessibilityNodeInfo.packageName
属性进行比较。

如果这对于您的用例来说不是一个好的解决方案,恐怕另一种选择是没有适合您的用例的解决方案,因为您无权访问所需的 ID。

© www.soinside.com 2019 - 2024. All rights reserved.