8 лет назад 13 июля 2016 в 19:58 4229

Дмитрий Мячин

Блог автора

    И вот оно, самое-самое. Я расскажу о некоторых, самых популярных командах и ключах команд для Android Debug Bridge. Они используются с частотой от несколько раз в месяц до несколько раз в час.

Ключи Android Debug Bridge

    Сам ADB можно запустить с ключами -d, -e и -s <id>. Это полезно, если у вас подключены либо реальное устройство и эмулятор одновременно, либо больше чем одно устройство или/и эмулятор.

Ключ -d означает «device» и сообщает ADB, что команда, которая идёт далее, должна быть выполнена на реальном устройстве, а не на эмуляторе. То есть если у вас подключено одно реальное устройство и сколько угодно эмуляторов, то adb -d «command» отправит «command» на реальное устройство.

Ключ -e, наоборот, говорит, что нужно выбрать эмулятор.

Ключом -s можно указать конкретное устройство. Если у вас их подключено одновременно 10 штук, и вам нужно перезагрузить конкретный LG, у которого его id, скажем, 12345, то выполните команду adb -s 12345 reboot. У эмуляторов коды тоже есть и они выглядят как emulator-55XX, где 55XX — это порт подключения эмулятора для ADB. Как узнать id? Читайте ниже

Основные команды ADB

Основных команд три: deviceshelp и version. Вам часто нужна будет команда devices. Команда «adb devices» возвращает список устройств по id и их состоянию.

    На скриншоте выше 036969c40935bf1a device означает, что это реальное устройство (device) и его id — 036969c40935bf1a. Состояние «emulator» означало бы, что это эмулятор. Состояние «offline» обычно означает, что устройство подключено, но подключение этого компьютера не разрешено ещё на самом устройстве. Хотя иногда это означает, что подключение зависло — ADB сервер на компьютере и демон на устройстве не могут установить связь между собой. Зная id, вы можете использовать ключ -s для запуска ADB: adb -s 036969c40935bf1a reboot
    Что значат help и version я понятия не имею. Думаю, вы можете посмотреть это в справке, но я не знаю, как её вызвать. Также в новых версиях могут добавляться новые команды, но как посмотреть версию ADB я тоже не знаю. Парам-парам-пам, фью!

Отладочные

    Важных команд здесь две: logcat и bugreport.

adblogcat. Выводит системный лог в реальном времени в stdout. Прям бери и перенаправляй вывод в файл, чтобы предоставить лог разработчику (ниже покажу, как правильно это сделать), или парси сам в поисках ключевых строк. Утилита monitor показывает именно вывод logcat. Практически всё тестирование завязано на чтение логов, если это не тестирование графического интерфейса. Хотя и тут тоже лог часто нужен.

    Так как в лог может попадать приватная информация, показ которой недопустим, то запись в лог делают только дебажные версии продуктов. В коде обычно есть явная проверка флага debug и, если это истина, действия логгируются. Безусловно, если в конкретных участках кода вообще добавлено логгирование. Следовательно, очень большой кусок функционального и регрессионного тестирования проводится на дебажных сборках, а приёмочное — только на боевых. Каждая строчка продукта в logcat для боевой сборки — причина оформить баг в багтрекер. Вплоть до блокирования релиза, если это реально очень критичная в плане приватности строка! Здесь проблема в том, что читать системный лог могут приложения, установленные на самом устройстве (к счастью, только на не современных версиях Android). Троян может парсить лог и искать там интересные записи.
    Логгирование — процесс, в общем-то, бесконечный. Потому его нужно вручную прерывать при воспроизведении проблемы. Очень хорошо то, что логи хранятся в буфере до его заполнения. Если баг воспроизвёлся, а устройство не было подключено, то можно сразу подключить его и перенаправить лог в файл. Информация соберётся не с момента выполнения команды, а ещё и за последние несколько минут (или даже часов!). Потому у logcat есть полезный ключ -d, который выводит содержимое буфера, и выполнение команды завершается, ждать ничего не нужно.
    К сожалению простое выполнение ADB logcat даёт не так много информации, как хотелось бы. Нет PIDов процессов, например, не тот уровень логгирования. Потому, если хотите собрать максимально полезный лог, используйте подобные команды:

— adb logcat -v threadtime *V > file.txt

— adb logcat -f /sdcard/file.txt -v threadtime *V

    Они обе будут сохранять одинаковый лог, только первая — на вашем компьютере (так что после > напишите полный путь к файлу), а вторая — на карте памяти. Вторая полезна, если вы подключены к устройству через, скажем, SSH. 

adb bugreport выводит сборную информацию от команд dumpsysdumpstateи logcat. Полезно, если устройство не ваше, вам его принесли со словами «вот, только что опять». Вы собираете эту информацию и возвращаете устройство владельцу.

Работа с данными

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

— adb install «file.apk». Команда install устанавливает apk на устройство и возвращает Success, если всё нормально и текст ошибки, если что-то не так. Чаще всего «не так» бывают «приложение уже установлено», и значит нужно либо его удалить, либо использовать ключ -r (install -r), чтобы сделать upgrade (или даже -d, чтобы сделать даунгрейд; но такое не нужно почти никогда); «невалидная цифровая подпись» — значит приложение нужно переподписать; «цифровые подписи не совпадают», когда вы пытаетесь сделать install -r, но у уже установленного приложения и этой apk разные подписи; или, уже очень редко на современных устройствах, «нет места».

— adb uninstall «packagename». Чтобы деинсталлировать установленное приложение, нужно знать его внутреннее имя, packagename (которое легко узнать, имея в руках утилиту AAPT).

— adb push «local_file remote_file». Команда push отправляет local_file с вашего компьютера на устройство. Скажем, adb push d:\test\qqq.tmp.

— adb pull remote_file local. Команда pull, напротив, копирует файл с устройства вам на компьютер.

Скриптовые

    Для упрощения написания сценариев автоматизации есть три команды:

— adb get-serialno. Если к компьютеру подключено одно устройство, то команда вернёт его id. В любой другой ситуации будет возвращена ошибка. Это то, что написано в первом столбце для команды adb devices, но только для одного устройства.

adb get-state возвращает состояние устройства, если оно одно подключено и ошибку в иных случаях. Это то, что написано во втором столбце для команды adb devices. Можно их обе и не использовать, а парсить только вывод adb devices, но ситуации бывают разные.

adb-wait-for-device «other_command» ожидает, пока ADB-серверу не ответит хотя бы один демон и тут же выполнит other_command. Скажем, вам нужно установить приложение на все подключаемые устройства. Вы пишите бесконечный цикл, который содержит только одну важную строку: adb wait-for-device install application.apk.

Управление сервером

    Здесь всего две команды, и я говорил про них выше. Они нужны, потому что подключение между сервером и демоном нет-нет, а зависает, особенно на не очень качественных прошивках. adb kill-server останавливает ADB-сервер, а adb start-server запускает его.


    Главная сложность в том, что остановка сервера означает отвал всех устройств, и прерывание записи лога, если у вас выполнялась всё это время adb logcat. И никакой adb -s <id> не поможет, так как перезапускается весь сервис, так что помните это.
    Впервые мне пришлось использовать перезапуск сервиса на каждой итерации автотеста, когда устройство One Plus One стало мгновенно проходить автотест, причём проваливая его. При отладке своего скрипта, суть которого сводилась к парсингу вывода logcat, выяснилось, что команда logcat вываливала содержимое буфера за последние несколько часов, а не с момента старта. Вообще, чтобы затирать старые записи и писать лог строго с текущего момента, у команды logcat есть ключ -c, от «clear». Проверил руками — и действительно, adb logcat -c просто не отрабатывала, не возвращая никаких ошибок. После перезапуска сервиса всё заработало, поработало и сломалось точно также на очередной итерации. Пришлось вносить изменения в автотест, добавив перезапуск сервиса.

Shell

    Команды, которые должны быть выполнены внутри самого Android, выполняются из шелла. Этих команд довольно много и без них жить трудно. Скажем, напечатать текст в поле ввода, если там стоит курсор, можно командой «input text», выполненной в шелле. А скопировать файл из места А в место Б можно средствами cp.
    Строго говоря, сама команда shell — это команда ADB. Таким образом можно работать в шелле, будто бы подключившись по SSH или telnet, выполнив — adbshell и нажав Enter, а можно выполнять по одной команде shell’а, делая это из ADB. В первом случае вам доступны инструменты и возможности Linux и Android, во втором — инструменты и возможности консоли, в которой вы работаете. В Windows это cmd или, скажем, PowerShell.
    Я приведу в пример несколько команд, доступных из shell, но их гораздо больше. Нужно просто понимать, что примерно можно делать в шелле.

Monkey

   Monkey — это утилита, которая генерирует заданное количество псевдослучайных событий для вашего приложения. Она не используется для реального тестирования пользовательских сценариев. Безусловно, с её помощью будут обнаруживаться падения, но подавляющее большинство этих падений никогда не будет обнаружено пользователями из-за, например, совершенно неожиданного или даже невозможного сценария.
    Для чего очень полезен Monkey — так это обнаруживать утечки памяти. Просишь её сгенерировать несколько десятков тысяч событий и смотришь на потребление памяти. По завершению работы Monkey должен запуститься джавовский сборщик мусора и освободить память. Конечное, значение используемой памяти не должно сильно отличаться от начального значения.

Activity Manager

Для управления активити приложений используется команда «am». То есть, если мы говорим о выполнении отдельных команд из ADB, то целиком строка будет adb shell am command.

Можно запустить активити или сервис вашего приложения, послав нужный Intent

Можно остановить приложение. Это очень полезно, когда вы работаете с реальными вредоносами, к примеру. Можно остановить так выполнение любой заразы, если антивирус провалил тест. Конечно, из шелла можно и kill сделать, но это обычно бесполезно. Можно послать бродкаст.

Package Manager

Для работы с пакетами, то есть с конечными приложениям, а не их модулями, используется команда pm. Package Manager используется в повседневности даже чаще, чем активити-менеджер.

Можно получить список всех установленных приложений. Самое простое — я фильтрую выдачу по тем, которые принадлежат нам, чтобы проверить, нужно ли их удалять

Можно получить путь к установленному приложению, зная его имя пакета. И затем, например, скопировать командой обычным cp -r. Я использую эту возможность именно чтобы получить нужное приложение с целевого устройства. Скажем, человек подозревает, что у него установлено вредоносное приложение. Я даю ему скрипт, который собирает приложения с телефона и он отдаёт мне их.

Установить и деинсталлировать приложение. Так как в целом писать adb shell pm install и adb shell pm uninstall дольше, чем просто adb install и adb uninstall, то эта возможность почти не используется. С другое стороны, если вы уже в шелле, то можно не запускать другой сеанс cmd. Также через pm uninstall  можно немного рулить разрешениями для Android 6.

Можно чистить данные приложения. Очень полезная операция, недоступная без root-привилегий на самом устройстве. Если вы тестируете приложение, которое защищается от удаления правами администратора устройства, то это уже само по себе создаёт неудобства, так как деинсталлировать через ADB его нельзя. А если оно ещё и блокирует устройство паролем при попытке забрать права, то это вообще нудно. Когда-то я тестировал такое приложение, причём код блокировки был случайным и генерировался на каждой инсталляции. Тогда я написал скрипт из пары строк, который останавливал приложение и чистил его данные. Дальше вручную снимал права администратора устройства, и никаких блокировок не происходило, так как с точки зрения приложения его только что установили, и оно не было настроено. Полезно это ещё для длинных автотестов, где требуется, чтобы приложение запускалось будто только после инсталляции. У меня есть скрипт для тестирования производительности, который, конкретно в этом случае, в цикле запускает приложение, считает время, за которое оно запустилось, останавливает его, чистит ему данные и запускает снова. Ещё это очень полезно, если есть активное заражение системы и нужно приструнить вредонос.

Завершить этот текст я решил демонстрацией того, что я имел в виду, говоря: «В первом случае вам доступны инструменты и возможности Linux и Android, во втором — инструменты и возможности консоли, в которой вы работаете». На скриншоте ниже я проделаю одно и тоже — получу список установленных приложений через пакетный менеджер и отфильтрую вывод по названиям, в которых есть явное упоминание LG. В cmd у меня есть findstr, а в shell — grep.

 

 

Никто не прокомментировал материал. Есть мысли?