onAccessibilityEvent Action_click 不工作

onAccessibilityEvent Action_click Not working

好的,所以我正在开发一个可以自动接受 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 

但出于某种原因,它会触发说它将要单击 "Tap here to accept" textview,但它从未真正执行过。有什么建议吗?

老实说,您的 post 很难读懂。您拥有纯粹出于组织目的而定义的功能,而不是因为它们要被重用。这使得在 Whosebug post 的过程中很难解析和理解...但是你没有提供足够的内容让我在 Android Studio 中复制和粘贴并理解。

当您 post 在 Whosebug 上编写代码时,您应该选择一个最小的复制示例,并且您绝对应该删除您的随机 Log 调用。您可能需要它们来帮助您了解正在发生的事情,但希望我们不需要 :) 它们只会让事情变得混乱并使阅读代码变得更加困难。话虽如此,请允许我专注于一点,

Note that I have cleaned up some of the poor style and debugging statements. Answers are in the code comments!

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);
}

鉴于上述问题和前面提到的通用代码质量问题,很难提供一个简洁的答案。这 post 留下了太多潜在的问题。任何提供的答案都将是在黑暗中刺伤。我发现问题很可能已在我的代码注释中涵盖,但它肯定存在于其他地方。另外,我为 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);
}

注意:None 以上提到的任何内容都与您对辅助功能 API 的使用有关!我觉得这很有趣。