因此,我是新手,并且一直在玩onAccessibilityEvent
并从其他应用程序中读取屏幕上的TextViews
,效果很好,但现在我希望能够使用AccessibilityNodeInfo.ACTION_CLICK
单击其中的一些。我的问题是,来自其他应用程序的大多数这些TextView
都没有打开可点击的控件,但是它们的弹出窗口位于可点击的android.widget.LinearLayout
或android.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);
当此方法返回“列表”时,乍一看可能会想到
它返回此字符串中提到的所有节点。实际上,
扫描字符串并返回包含而不是一部分的所有节点,
但是整个字符串。
在您的程序中,赋予“ clickScreen”的字符串包含所有视图文本。因此,您是否可以:
每当您与其中一个人碰面时,请点击视图:
if(child.isClickable()){
child.performAction(AccessibilityNodeInfo.ACTION_CLICK);
}
如果要单击特定视图,则必须事先知道其文本或部分视图(请注意“确定”和“取消”,因为它会关闭屏幕):
child.getText().toString().toLowerCase().contains()("your text");
或将它们全部放入ArrayList中,然后单击您想要的内容:
填充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));
}
...
}
迭代列表,然后单击:
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;
}