是否可以使用adb命令通过查找其ID来点击视图?

and*_*per 8 android adb android-view

假设我有一个应用程序(在调试/发布版本中,由我自己制作),它具有特定视图的ID.

是否可以调用adb命令单击此视图?

我知道可以点击特定的坐标,但是可以使用ID吗?

我问这个是因为我知道"布局检查器"工具(可通过Android Studio获得)和"查看层次结构"工具(可通过"Android设备监视器"获得,以前通过DDMS使用)可以显示视图的ID(和甚至他们的坐标和边界框),所以也许它可以是一个更好的方法来模拟执行一些自动测试时的触摸.

如果需要,我可以使用root方法.


编辑:我设置了一个赏金,万一有一个比我自己的答案更容易/更好的方式,这是解析"adb shell dumpsys活动顶部"的结果.

我想知道是否可以获得屏幕上显示的视图坐标(以及当然的大小),包括关于它们的更多信息(以识别每个).这也应该可以通过设备实现.也许某些东西与"监视器"工具提供的输出数据相同:

在此输入图像描述

请注意它如何获取视图的基本信息,包括文本,id和每个视图的边界.

正如我所读到的,这可能是通过AccessibilityService实现的,但遗憾的是我无法理解它是如何工作的,它的功能是什么,如何触发它,它的要求是什么等等......

and*_*per 5

使用@pskink在上面的评论中解释的内容,这是我如何实现这一点:

首先,我运行了这个命令:

adb shell dumpsys activity top
Run Code Online (Sandbox Code Playgroud)

然后,我使用此代码来解析它:

public class ViewCoordsGetter {
    public static Rect getViewBoundyingBox(String viewIdStr) {
        final List<String> viewHierarchyLog = //result of the command
        for (int i = 0; i < viewHierarchyLog.size(); ++i) {
            String line = viewHierarchyLog.get(i);
            if (line.contains(":id/" + viewIdStr + "}")) {
                Rect result = getBoundingBoxFromLine(line);
                if (i == 0)
                    return result;
                int currentLineStart = getStartOfViewDetailsInLine(line);
                for (int j = i - 1; j >= 0; --j) {
                    line = viewHierarchyLog.get(j);
                    if ("View Hierarchy:".equals(line.trim()))
                        break;
                    int newLineStart = getStartOfViewDetailsInLine(line);
                    if (newLineStart < currentLineStart) {
                        final Rect boundingBoxFromLine = getBoundingBoxFromLine(line);
                        result.left += boundingBoxFromLine.left;
                        result.right += boundingBoxFromLine.left;
                        result.top += boundingBoxFromLine.top;
                        result.bottom += boundingBoxFromLine.top;
                        currentLineStart = newLineStart;
                    }
                }
                return result;
            }
        }
        return null;
    }

    private static int getStartOfViewDetailsInLine(String s) {
        int i = 0;
        while (true)
            if (s.charAt(i++) != ' ')
                return --i;
    }

    private static Rect getBoundingBoxFromLine(String line) {
        int endIndex = line.indexOf(',', 0);
        int startIndex = endIndex - 1;
        while (!Character.isSpaceChar(line.charAt(startIndex - 1)))
            --startIndex;
        int left = Integer.parseInt(line.substring(startIndex, endIndex));
        startIndex = endIndex + 1;
        endIndex = line.indexOf('-', startIndex);
        endIndex = line.charAt(endIndex - 1) == ',' ? line.indexOf('-', endIndex + 1) : endIndex;
        int top = Integer.parseInt(line.substring(startIndex, endIndex));
        startIndex = endIndex + 1;
        endIndex = line.indexOf(',', startIndex);
        int right = Integer.parseInt(line.substring(startIndex, endIndex));
        startIndex = endIndex + 1;
        //noinspection StatementWithEmptyBody
        for (endIndex = startIndex + 1; Character.isDigit(line.charAt(endIndex)); ++endIndex)
            ;
        int bot = Integer.parseInt(line.substring(startIndex, endIndex));
        return new Rect(left, top, right, bot);
    }
}
Run Code Online (Sandbox Code Playgroud)