onAccessibilityEvent Action_click无效

时间:2017-07-30 09:37:01

标签: java android accessibilityservice

好的,所以我正在开发一个自动接受lyft请求的应用程序,但我的代码没有使用performAction(AccessibilityNodeInfo.ACTION_CLICK);正确。

public class AutoService extends AccessibilityService {
private static LyftAdapter lyftAdapter = new LyftAdapter();

// Automated Service (onAccessibilityEvent)
@TargetApi(16)
@Override
public void onAccessibilityEvent(AccessibilityEvent event)
{
    AccessibilityNodeInfo source = event.getSource();
    String lyftPackage = "com.lyft.android.driver";
    String packageName = Tools.getPackage(source);

    if (!packageName.equals(lyftPackage))
    {
        event.recycle();
        return;
    }

    if (source == null)
    {
        event.recycle();
        return;
    }

    processUI(event.getSource());
}

public void processUI(AccessibilityNodeInfo source)
{
    source = getRootInActiveWindow();

    if (Tools.getPackage(source).equals("com.lyft.android.driver") || Tools.getPackage(source).equals("me.lyft.android"))
    {
        if (!Lyft_Status.equals("OFFLINE"))
        {
            lyftAdapter.processEvent(source);
        }
        else
        {
            Log.v(TAG, "Can't process UI: " + Lyft_Status);
        }
    }

    if (source != null)
        source.recycle();
}
}

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

        if (string == null)
        {
            Log.v(TAG, "String is NULL");
            return;
        }

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

// PROCESS SECONDARY EVENT
private 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(Tools.getText(source));
        sb.append("\n");
        final int childCount = source.getChildCount();

        for (int j = 0; j < childCount; ++j) {
            final AccessibilityNodeInfo child = source.getChild(j);
            processSubEvent(child, n + 1, sb);
            if (child != null) {
                child.recycle();
            }
        }
    }
}

// CLICK THE SCREEN
protected void clickScreen(AccessibilityNodeInfo source, final String text)
{
    final AccessibilityNodeInfo s = source;

    new Handler().postDelayed(new Runnable() {
        List<AccessibilityNodeInfo> list = s.findAccessibilityNodeInfosByText(text);
        @Override
        public void run() {
            for (final AccessibilityNodeInfo node : list) {
                node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }
    }, 1000);
}
}

public class LyftAdapter
    extends RideshareAdapter
{
// LYFT ADAPTER
protected void processUIText(AccessibilityNodeInfo source, String text)
{        
    // RIDE REQUEST
    if (text.contains("tap here to accept"))
    {
        clickScreen(source, "Tap here to accept");
    {  
}         

The string comes out as (Just like it is shown):
Lyft
11 mins
away
Passenger Name
New
Tap here to accept 

但出于某种原因,它触发了它会点击“点击此处接受”textview,但它实际上从未实现过。有什么建议吗?

1 个答案:

答案 0 :(得分:0)

说实话,你的帖子很难阅读。您拥有的功能纯粹是出于组织目的而定义的,而不是因为它们是要重复使用的。这使得在StackOverflow帖子的过程中解析和理解变得非常困难......但是你没有提供足够的东西来复制和粘贴并在Android Studio中理解。

当您在StackOverflow上发布代码时,您应该选择最小的复制示例,并且您绝对应该删除随机日志调用。您可能需要它们来帮助您了解发生了什么,但希望我们不会这样做:)它们只会使事情变得混乱并使您的代码更难以阅读。这就是说,请允许我专注于一点,

  

请注意,我已经清理了一些糟糕的样式和调试语句。答案在代码注释中!

protected void clickScreen(final AccessibilityNodeInfo source, final String text)
{
new Handler().postDelayed(new Runnable() {
    //Find ALL of the nodes that match the "text" argument.
    List<AccessibilityNodeInfo> list = source.findAccessibilityNodeInfosByText(text);
    @Override
    public void run() {
        //Non discrliminintly click them, whether they're buttons, or text fields or links... just click them and hope they do something.
        for (final AccessibilityNodeInfo node : list) {
            node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
    }
//Delay it for a second AFTER the function has been called for no particularly good reason besides perhaps invalidating all of the nodes in the heirarchy... GOOD CALL!
}, 1000);
}

鉴于上述问题和上述通用代码质量问题,很难提供简明的答案。这篇文章留下了太多潜在的问题。任何提供的答案都会在黑暗中被刺伤。我觉得问题很可能在我的代码注释中有所涉及,但它绝对可能在其他地方。此外,我为sass道歉!

所有这些,你可以试试这个版本的功能!

static void clickFirstMatchingNode(AccessibilityService service, final String text) {
    final List<AccessibilityNodeInfo> list = service.getRootInActiveWindow().findAccessibilityNodeInfosByText(text);

    for (AccessibilityNodeInfo node : list) {

       //Check if the action completely successfully. Also, only click one of them. This is kind of an assumption, it also simplifies the logic. You can certainly write a version of this that clicks everything that matches!
        if (node.performAction(AccessibilityNodeInfo.ACTION_CLICK)) return;

    }

    //If no node is successfully clicked Log some stuff!
    Log.wtf(YourService.class.getName(), "Failed to click any nodes! WTF?: " + text);
}

注意:以上均未提及您使用辅助功能API的任何内容!我认为这很有趣。