Основные сведения

В этой главе представлены базовые знания по автоматизации Android. Пожалуйста, обязательно прочитайте её, далее эти сведения повторно подробно не разбираются. Автоматизация Android сильно отличается от обычной веб-автоматизации, но у них есть и много общего. При обычной веб-автоматизации можно просто открыть инструменты разработчика F12, посмотреть структуру страницы, идентификаторы элементов и другую информацию, а затем с помощью XPath получить элементы для кликов, ожиданий и т. д. В среде Android логика аналогична: вы также можете выбирать элементы с помощью так называемых селекторов и выполнять клики, проверки и другие операции, поэтому не беспокойтесь, что начать будет сложно.

Сходства и различия мобильной и веб-автоматизации

Между мобильной автоматизацией и веб-автоматизацией много общего, но есть и немало различий. Возьмём в качестве примера Selenium: обычно для управления браузером с помощью Selenium нужны три составляющие: во-первых, браузер; во-вторых, WebDriver; в-третьих, Selenium. В мобильной среде аналогично: телефон соответствует браузеру, FIRERPA соответствует WebDriver, а клиентская библиотека Python lamda для FIRERPA соответствует Selenium. Их цели совпадают — выполнять имитацию действий пользователя для тестирования, сбора данных или автоматического выполнения задач. Все они управляются сценариями, выполняют локализацию элементов, клики, создание снимков экрана, проверки и другие операции. Поэтому они действительно довольно похожи.

Но у них есть и отличия. Во-первых, для мобильной автоматизации нужны телефон и компьютер, тогда как веб-автоматизацию можно выполнять на вашем же компьютере. Во-вторых, используются разные наборы инструментов. Для веба распространены Selenium, Puppeteer, Playwright; для мобильных устройств обычно применяются FIRERPA, AutoJS, Appium, uiautomator2 и другие.

Для веба распространённый способ локализации основан прежде всего на XPath или CSS-селекторах по структуре HTML DOM, иерархия элементов относительно наглядна. Для мобильной среды распространённым способом локализации являются селекторы; конечно, интерфейс Android-приложений также использует XML-разметку, поэтому можно выполнять выборку через XPath и по XML. Обычно при веб-автоматизации не нужно слишком беспокоиться о совместимости: в большинстве случаев достаточно зафиксировать версию браузера и разрешение запуска, чтобы решить проблемы совместимости, вызванные различиями устройств. Но на Android из-за различий брендов, моделей, размеров экрана, версий системы и т. п. может возникать влияние на совместимость кода автоматизации. Однако не беспокойтесь: влияние есть, но оно ограничено.

Различия между инструментами автоматизации

Выше упоминалось, что между несколькими распространёнными инструментами автоматизации Android, которые мы привели в качестве примеров, также есть большие различия. Сразу обозначим позицию: FIRERPA — самый стабильный, самый функциональный, самый мощный из всех инструментов автоматизации и лучше всего подходит для проектного управления и применения.

Примечание

Наша позиция не является предвзятой: она сформирована в результате шести лет непрерывных исследований и оптимизации. Пути, которые вы проходили, и грабли, на которые вы наступали, мы в основном уже прошли.

Распространённый AutoJS и его производные относятся к типу «управление собой из себя»: необходимо установить APK на устройство и писать сценарии на JavaScript. AutoJS обычно может выполнять только автоматизацию; его преимущество — низкий порог входа, подходит новичкам или для любительского использования. Однако сама архитектура не подходит для масштабного управления, администрирования и обновления сценариев: она децентрализована и не управляется, поэтому точное массовое управление невозможно.

Основной процесс автоматизации

Обычно сначала нужно предварительно проработать схему: будет ли это только обычная автоматизация или одновременно с автоматизацией нужно получать данные о работе приложения? Обычно есть два способа получения данных: первый — перехват HTTP/S-трафика через промежуточный узел (MITM); второй — перехват данных с помощью хуков. Способ с промежуточным узлом проще и подходит для обычного использования, но для некоторых приложений может не работать. Схема с хуками требует серьёзных знаний реверс-инжиниринга, сложна для начала, не подходит новичкам и применяется в крайних случаях.

Получение данных через промежуточный узел

Схема с промежуточным узлом довольно проста: достаточно найти в документации разделы Установка сертификата промежуточного узла и Настройка прокси и использовать их вместе с mitmproxy. Если что-то непонятно, можно обратиться к официальному скрипту startmitm.py — в нём уже написана вся логика, которую можно скопировать или использовать повторно.

Получение данных с помощью хуков

Для схемы с хуками требуется как минимум начальный уровень реверс-инжиниринга; если вы с ним ещё не знакомы, можно пока её не рассматривать. В целом схема с хуками заключается в написании скриптов Frida, перехвате вызовов нужных функций, получении параметров или возвращаемых значений, их передаче и последующем внедрении в приложение и т. д. Простой демонстрационный пример и способы использования можно найти в разделе Использование Frida для отправки данных.

Код автоматизации

Код автоматизации также незаменим, поскольку именно через автоматизацию вы запускаете нужную логику. Написание кода автоматизации обычно строится по следующему процессу. Сначала откройте удалённый рабочий стол FIRERPA — вы увидите следующий интерфейс.

Удалённый рабочий стол

Теперь откройте приложение, которое хотите автоматизировать, затем нажмите на иконку «глаз» в правом верхнем углу удалённого рабочего стола — вы увидите интерфейс, показанный ниже. Выберите элемент, с которым нужно работать, и щёлкните по нему, чтобы просмотреть информацию об элементе.

Совет

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

Выбор элемента

Справа вы можете увидеть информацию об элементе, например text, resourceId и т. д. Предположим, что нам нужно кликнуть по этому элементу. Можно написать следующий код; он означает «кликнуть по элементу с text, равным “同意”».

d(text="同意").click()

Примечание

Это лишь пример. Способов записи селектора много, здесь показан самый простой.

Хорошо, самый простой вариант вы уже знаете. Теперь добавьте управляющую логику if/else и используйте такие методы, как exists, — и вы сможете реализовать целый процесс автоматизации. Видите, это не так уж сложно.

Инспектирование макета интерфейса

В обычной ситуации написание кода автоматизации невозможно без инспектирования макета интерфейса — это единственный способ получить условия для селектора. Сначала откройте удалённый рабочий стол устройства в браузере. Затем нажмите на иконку глаза в правом верхнем углу удалённого рабочего стола, чтобы войти в режим инспектирования макета. Теперь можно щёлкать по пунктирным рамкам на экране слева и просматривать информацию о соответствующих элементах, чтобы использовать их атрибуты в качестве параметров селектора. Повторное нажатие на иконку глаза закроет инспектирование макета. Обратите внимание: инспектор макета не обновляется автоматически при изменении страницы — он зафиксирован на том макете экрана, который был в момент входа в инспектор; для обновления вручную нажмите сочетание клавиш Ctrl + R.

Инспектирование элемента

Подсказка

В режиме инспектирования макета можно также нажимать клавишу Tab, чтобы последовательно просматривать все элементы.

Селектор интерфейса

Селектор интерфейса (Selector) используется для работы с элементами Android. Его можно понимать как правила XPath: механизм другой, но назначение похожее. В FIRERPA класс селектора называется Selector, и в большинстве случаев вам не нужно напрямую с ним работать. Вы уже видели его использование выше. Полный Selector содержит следующие необязательные параметры.

Тип сопоставленияОписание
textПолное совпадение текста
textContainsТекст содержит
textStartsWithТекст начинается с
classNameСовпадение по имени класса
descriptionПолное совпадение описания
descriptionContainsОписание содержит
descriptionStartsWithОписание начинается с
clickableМожно кликнуть
longClickableМожно долго нажимать
scrollableПрокручиваемый
resourceIdСовпадение по resourceId

В большинстве случаев в качестве параметров используются только resourceId, text, description, textContains и т. п. Если у элемента есть корректный resourceId, следует в первую очередь использовать его в Selector, например d(resourceId="com.xxx:id/mobile_signal"); иначе можно использовать text, например d(text="点击进入"), или более размыто d(textContains="点击"). description аналогичен text, но используется реже.

Подсказка

Selector составляется вами из основных параметров, полученных с помощью описанного выше инспектирования макета интерфейса.

Определение координат экрана

В процессе автоматизации неизбежно возникают ситуации, когда нужно работать по точным координатам или координатам области. Возможно, вы ещё не знакомы с понятием координат, поэтому здесь мы расскажем о координатах экрана Android. Экран, как и изображение, имеет разрешение. Для экрана Android, независимо от альбомной или портретной ориентации и автоповорота, левый верхний угол всегда считается началом координат (0,0), ось X направлена вправо, ось Y — вниз; так образуется система координат, как показано на рисунке.

Координаты экрана

Из рисунка видно, что координаты левого верхнего угла экрана — (0,0), правого верхнего — (1080,0), левого нижнего — (0,1920), правого нижнего — (1080,1920). На основе этой информации можно вычислить координаты любой точки экрана.

Примечание

Независимо от того, является ли экран исходно портретным или альбомным, а также при автоповороте, началом координат всегда считается левый верхний угол текущей ориентации.

Точка на экране

В FIRERPA некоторые операции (например, клик или создание снимка экрана) требуют указать область или координаты. Для обычной координатной точки используется следующее определение; оно представляет точку на экране с координатами (100,100).

Point(x=100, y=100)

Определение области

Область — это прямоугольная область на экране. Её определение немного сложнее, пожалуйста, прочитайте внимательно. Область на экране мы обозначаем через Bound, и нужно указать четыре параметра: top, left, bottom, right. Возможно, это вызовет вопросы, дальше обязательно разберитесь: top — это расстояние в пикселях от верхней границы прямоугольника до верхней границы экрана, left — расстояние от левой границы прямоугольника до левой границы экрана, right — расстояние от правой границы прямоугольника до левой границы экрана, bottom — расстояние от нижней границы прямоугольника до верхней границы экрана. Короче говоря, все расстояния отсчитываются по осям X/Y от начала координат в левом верхнем углу экрана. Рисунок ниже помогает понять: экран телефона по-прежнему 1080x1920, текущая ориентация — портретная.

Область экрана

Теперь предположим, что экран разделён на четыре равные части, и нам нужно получить определения двух областей, показанных на рисунке: левой верхней и правой нижней. По правилам, область 1: расстояние от верха прямоугольника до верха экрана — 0 пикселей, от левой границы до левой границы экрана — 0 пикселей, от низа до верха экрана — 960 пикселей (1920 ÷ 2), от правой границы до левой границы экрана — 540 пикселей (1080 ÷ 2), поэтому её определение:

Bound(top=0, left=0, right=540, bottom=960)

Аналогично, область 2: расстояние от верха прямоугольника до верха экрана — 960 пикселей, от левой границы до левой границы экрана — 540 пикселей, от правой границы до левой границы экрана — 1080 пикселей, от низа до верха экрана — 1920 пикселя, её определение:

Bound(top=960, left=540, right=1080, bottom=1920)

Данные Android-приложений

У каждого Android-приложения на устройстве есть собственный каталог данных. Обычно данные приложений хранятся в каталоге /data. Вы можете получить каталог данных приложения, вызвав интерфейс d.application("com.example").info(). В большинстве случаев можно также сразу выполнить cd в каталог /data/user/0/com.example.test, чтобы перейти в пользовательский каталог. Помимо /data, некоторые приложения хранят мультимедийные и другие файлы в каталоге /sdcard/Android.

Просмотр базы данных SMS

Иногда вы хотите узнать, где хранятся принятые SMS на устройстве. Это очень просто: можно даже написать расширение (extension), чтобы напрямую читать содержимое и получать его в реальном времени через HTTP-интерфейс! Мы рассмотрим это по обычной логике Android; если в вашем случае всё иначе, действуйте по аналогии. В Android имя пакета приложения SMS обычно com.android.mms, поэтому можно перейти в каталог /data/user/0/com.android.mms. Выполнив приведённые ниже команды, вы увидите, что в каталоге databases есть несколько баз данных, среди которых mmssms.db — то, что нам нужно.

 λ 10:12 /data/user/0/com.android.mms ➥ ls -la
total 82
drwx------    7 u0_a78   u0_a78        3452 Jan  2  2021 .
drwxrwx--x  381 system   system       53248 May  2 16:46 ..
drwxrws--x    3 u0_a78   u0_a78_c      3452 Jan  2  2021 cache
drwxrws--x    2 u0_a78   u0_a78_c      3452 Jan  2  2021 code_cache
drwxrwx--x    2 u0_a78   u0_a78        3452 Jan  2  2021 databases
drwxrwx--x    7 u0_a78   u0_a78       24576 Feb 26 13:43 files
drwxrwx--x    2 u0_a78   u0_a78        3452 May  4 10:12 shared_prefs
 λ 10:12 /data/user/0/com.android.mms ➥ ls -l databases/
total 504
-rw-rw----    1 u0_a78   u0_a78       24576 Jan  2  2021 dynamic_bubble
-rw-------    1 u0_a78   u0_a78           0 Jan  2  2021 dynamic_bubble-journal
-rw-rw----    1 u0_a78   u0_a78      491520 Feb 27 04:18 mmssms.db
-rw-------    1 u0_a78   u0_a78           0 Jan  2  2021 mmssms.db-journal
 λ 10:12 /data/user/0/com.android.mms ➥

Читать очень просто, потому что базы данных обычных Android-приложений обычно являются SQLite. Однако приложения с повышенной безопасностью часто шифруют базу данных. FIRERPA достаточно мощный: кроме обычного SQLite, он поддерживает чтение в реальном времени зашифрованных баз данных, таких как WeChat (SqlCipher) AES-256, корпоративный WeChat AES-128, базы экосистемы Alibaba SqlCrypto (AES-128) и др. (при условии, что вы сами найдёте ключ). Ниже мы просто продемонстрируем чтение содержимого системных SMS — достаточно одной команды, но вы также можете написать расширение для чтения.

sqlite3 databases/mmssms.db .dump

Вывод может быть большим, но вы можете быстро найти таблицу с нужными данными и затем самостоятельно написать SQL-запрос. Этот метод подходит для 98% Android-приложений; оставшиеся 2% — это зашифрованные базы данных.

Просмотр зашифрованных баз данных

Для зашифрованных баз данных вам нужно самостоятельно найти ключ базы данных или способ его получения. Ниже кратко описано, как читать базы данных соответствующих приложений, и только как использовать PRAGMA для задания ключа. Если вам непонятно, что это такое, сначала изучите SQLite.

WeChat (sqlcipher)

PRAGMA cipher = "sqlcipher";
PRAGMA legacy = 1;
PRAGMA key = "database-key";

Корпоративный WeChat (wxsqlite)

PRAGMA cipher = "aes128cbc";
PRAGMA hexkey = "database-key"

Экосистема Alibaba (sqlcrypto)

PRAGMA cipher = "sqlcrypto";
PRAGMA key = "database-key"

Подсказка

Обратите внимание: база данных Android-приложения не обязательно находится только в каталоге databases.

Просмотр других данных

Разумеется, в каталоге данных приложения есть не только базы данных, но и параметры приложения, конфигурация, кэш, файлы и т. д., например shared_prefs (XML-файлы). Мы не будем подробно останавливаться на этом — вы можете изучить самостоятельно.

Вспомогательные меры автоматизации

В задачах автоматизации не все приложения удобно локализовать с помощью селекторов. Некоторые интерфейсы (например, игры) из-за рендеринга в реальном времени не имеют макета страницы на уровне Android. Для таких приложений можно различать элементы только с помощью OCR или сопоставления изображений. Конкретные интерфейсы и способы использования см. в разделах Распознавание текста и Сопоставление изображений.