Можно ли использовать команды adb, чтобы щелкнуть мышью по просмотру, найдя его идентификатор?

Предположим, что у меня есть приложение (в сборке debug/release, сделанное мной или нет), у которого есть идентификатор для определенного вида.

Можно ли вызвать команду adb, чтобы щелкнуть это представление?

Я знаю, что можно щелкнуть по определенной координате, но можно ли использовать идентификатор?

Я спрашиваю об этом, потому что я знаю, что инструмент "Макет Инспектор" (доступный через Android Studio) и инструмент "Иерархия просмотра" (доступный через "Android Device Monitor", ранее используемый через DDMS), может показывать идентификаторы (и даже их координаты и ограничивающая рамка), поэтому, возможно, это может быть лучший способ имитировать штрихи при выполнении некоторых автоматических тестов.

При необходимости я могу использовать корневой метод.


EDIT: я установил щедрость, если есть более простой/лучший способ, чем то, что я написал в своем собственном ответе, который должен был проанализировать результат "adb shell dumpsys activity top".

Я хотел бы знать, можно ли получить координаты представлений (и размеры конечно), которые показаны на экране, включая как можно больше информации о них (чтобы идентифицировать их каждый). Это должно быть возможно и через устройство. Возможно, что-то, что имеет одинаковые выходные данные того, что доступно с помощью "монитора":

введите описание изображения здесь

Обратите внимание, как он может получить основную информацию о представлениях, включая текст, идентификатор и границы каждого из них.

Как я читал, это может быть возможно через AccessibilityService, но, к сожалению, я не могу понять, как все это работает, каковы его возможности, как его запускать, каковы его требования и т.д.

Ответ 1

Используя то, что @pskink объяснено в комментариях выше, вот как я достиг этого:

Сначала я выполнил эту команду:

adb shell dumpsys activity top

Затем я использовал этот код для его анализа:

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