Android AccessibilityService performAction() 方法无效

Android AccessibilityService performAction() method not working

我正在为 Android 开发无障碍服务。该服务调用一个应用程序,该应用程序有一个 RecyclerView。然后我想用 performAction(AccessibilityNodeInfo.ACTION_CLICK) 单击 RecyclerView 的一个元素,但它不起作用。我知道有几个类似的问题,但其中 none 对我有用。我还查看了官方文档中的 performAction 方法 https://developer.android.com/reference/android/view/accessibility/AccessibilityNodeInfo

的 class

这是我的代码:

@Override
public void onAccessibilityEvent(Accessibility event){
    AccessibilityNodeInfo source = event.getSource();
    if(source != null){
        List<AccessibilityNodeInfo> list = source.findAccessibilityNOdeInfosByText("mystring");

        list.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
    }
}

这是我的配置xml文件:

<accessibility-srvice xmlns...
    android:accessibilityFeedbackType = "feedbackGeneric"
    android:AccessibilityFlags = "flagDefault"
    android:canPerformGestures = "true"
    android:canRetrieveWIndowCOntent = "true"

我想我误解了什么,但我不知道是什么。感谢任何帮助。

编辑 2022 年 3 月 29 日

简单的答案是,虽然通过文本查找节点很好,但该特定节点不是具有所需 onClick 事件的节点。解决方法是调用

list.get(0).getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK)

澄清讨论如下


我认为.performAction(AccessibilityNodeInfo.ACTION_CLICK)是对的,但可能还有其他一些顾虑。抱歉发布为答案,但评论太少了。

  1. 您确定正在调用 onAccessibilityEvent 吗?我不认为这是正确的事件,但我不能确定。也许在那里放一个日志以确保它在您期望调用事件时调用事件。

  2. 此外,查看源代码可能会限制您的搜索,也许而不是 event.getSource() 尝试使用 rootInActiveWindow(我使用 Kotlin 所以它可能有一个方法,请参阅 https://developer.android.com/reference/android/accessibilityservice/AccessibilityService#getRootInActiveWindow(int))

编辑:2022 年 3 月 28 日

我在自己的无障碍服务中有 运行 这段代码,它确实点击了按钮。但是很容易溢出。

    var ranOnce = false // prevent overflow
    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
        if (event == null) return

        if (event.eventType == TYPE_WINDOW_STATE_CHANGED) return

        if (event.source != null && !ranOnce) {
            val nodeList = rootInActiveWindow.findAccessibilityNodeInfosByText("Menu")
            //event.source.findAccessibilityNodeInfosByText("Menu") // <-- always nothing in list

            Log.d("onAccessibilityEvent", "List of nodes: $nodeList")
            if (nodeList.size > 0) {
                android.util.Log.d("onAccessibilityEvent", "Node info: ${nodeList[0]}")
                ranOnce = true
                nodeList[0].performAction(AccessibilityNodeInfo.ACTION_CLICK) //<-- caused an infinite loop!
            } else {
                Log.d("onAccessibilityEvent", "No nodes found")
            }
        } else {
            Log.d("onAccessibilityEvent", "event.source is null!")
        }
    }