AccessibilityNodeInfo.ACTION_CLICK 不工作

AccessibilityNodeInfo.ACTION_CLICK not working

所以我是新手,一直在玩 onAccessibilityEvent 并阅读 TextViews 屏幕上来自其他应用程序的内容,效果很好,但现在我希望能够使用AccessibilityNodeInfo.ACTION_CLICK 点击其中一些。我的问题是来自其他应用程序的这些 TextView 中的大多数都没有打开可点击功能,但它们有一个位于 android.widget.LinearLayoutandroid.widget.FrameLayout 中的可点击弹出窗口。但我的代码似乎并没有点击它们。有什么建议吗?

public class AutoService extends AccessibilityService 
{
          @TargetApi(16)
          @Override
          public void onAccessibilityEvent(AccessibilityEvent event)
          {
                 AccessibilityNodeInfo source = event.getSource();
                 myAdapter.processEvent(source);
          }
}

public class myAdapter
{
    public static void processEvent(final AccessibilityNodeInfo source)
    {
         final StringBuilder sb = new StringBuilder();
         processSubEvent(source, 0, sb);
         final String string = sb.toString();

         if (string == null)
         {
            return;
         }

         clickScreen(source, string.toLowerCase());
    }

private static void processSubEvent(final AccessibilityNodeInfo source, final int n, final StringBuilder sb) {
    for (int i = 0; i < n; ++i) {
        sb.append("\t");
    }

    if (source != null)
    {
        sb.append(source.getText());
        sb.append("\n");
        final int childCount = source.getChildCount();

        for (int i = 0; i < childCount; i++)
        {
            AccessibilityNodeInfo child = source.getChild(i);
            processSubEvent(child, n + 1, sb);

            if (child != null)
            {
                child.recycle();
            }
        }
    }
}

private static void clickScreen(final AccessibilityNodeInfo source, final String text)
{
     List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByText(text);

    for (final AccessibilityNodeInfo node : list)
    {
        node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
    }
}
}

我认为您同意我的看法,问题出在:

List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByText(text); 

as this method returns a "List", may come to mind at first glance that it returns all the nodes which mentioned in this string. In fact, it scans the string and returns all the nodes that contains, not a part, but the whole string.

在你的程序中,给"clickScreen"的字符串包含了视图的所有文本。所以,你可以:

  • 每当您通过以下方式与其中一位会面时单击视图:

    if(child.isClickable()){
        child.performAction(AccessibilityNodeInfo.ACTION_CLICK);
    }
    

    如果你想点击一个特定的视图,你必须事先知道它的文本或部分内容(注意"OK"和"Cancel",因为它会关闭屏幕):

    child.getText().toString().toLowerCase().contains()("your text");
    
  • 或者全部放在ArrayList里面,以后点你要的:

    1. 填充ArrayList:

      //create new ArrayList
      public  ArrayList<AccessibilityNodeInfo> clickableViews = new ArrayList<>();
      
      private static void processSubEvent(final AccessibilityNodeInfo source, final int n, final StringBuilder sb) {
          ...
      if (child != null)
      {
          //fill the ArrayList with clickable views(make sure to put the origin reference because you will recycle child later)
          if(child.isClickable()) {
              clickableViews.add(source.getChild(i));
          }
          ...
      }
      
    2. 迭代列表并单击:

       for (AccessibilityNodeInfo view : clickableViews) {
          //We only want to click one view per function call! Clicking multiple 
          //views in rapid succession is error prone and functionally ambiguous 
          //meaning it might work in some use cases, and throw exceptions in others.
          if(view.performAction(AccessibilityNodeInfo.ACTION_CLICK)) break;
       }