Управление Activity и Intent (am)

Рейтинг: 64.6% · 12 голосов
Полный курс по Android Debug Bridge: установка, подключение, shell, логи, dumpsys, автоматизация, root, беспроводная отладка. Уроки по главам с обсуждением.
Ответить
Аватара пользователя
android_roman
Сообщения: 45
Зарегистрирован: 11 май 2026, 05:31

Управление Activity и Intent (am)

Сообщение android_roman »

АкадемияADB: Android Debug BridgeГлава 12 из 29
Оглавление курса (29)
  1. Введение в Android Debug Bridge
  2. Установка и настройка рабочей среды
  3. Подключение устройства (проводное и беспроводное)
  4. Базовые команды ADB и управление сервером
  5. Команды состояния и перезагрузки
  6. Навигация по файловой системе
  7. Управление пакетами приложений
  8. Логирование с помощью logcat
  9. Системные дампы и диагностика (dumpsys)
  10. Анализ производительности в реальном времени
  11. Эмуляция ввода (input)
  12. Управление Activity и Intent (am) (вы здесь)
  13. Работа с оконным менеджером (wm)
  14. Захват экрана и запись видео
  15. Root-доступ и его применение
  16. Модификация системных настроек через settings
  17. Команды для поставщиков контента (content)
  18. Резервное копирование и восстановление (backup)
  19. Проброс портов и туннелирование
  20. Беспроводная отладка (Wi-Fi)
  21. Взаимодействие с эмуляторами
  22. Написание скриптов на Bash/CMD/PowerShell
  23. ADB в языках программирования
  24. Автоматизация тестирования с ADB
  25. Безопасность и лучшие практики
  26. ADB на Android TV, Wear OS и IoT
  27. Восстановление и низкоуровневые операции
  28. Расширенные возможности оболочки и инструменты
  29. Отладка самого ADB и устранение неполадок
am (Activity Manager) - это шелл-интерфейс к одноимённому системному сервису, который в Android отвечает за жизненный цикл приложений: запуск Activity и сервисов, доставку broadcast, остановку процессов. Начиная с Android 8 команда am на устройстве является тонкой обёрткой над cmd activity, поэтому

Код: Выделить всё

adb shell am start
и

Код: Выделить всё

adb shell cmd activity start-activity
делают одно и то же. Имена пакетов, которые мы научились находить через pm в главе 7, здесь понадобятся постоянно: почти всё в am адресуется пакетом или компонентом.

Запуск Activity по компоненту:

Самая частая операция. Синтаксис компонента: пакет/класс. Если класс лежит в корне пакета, его можно сократить до точки с именем класса.

Код: Выделить всё

adb shell am start -n com.android.settings/.Settings
Starting: Intent { cmp=com.android.settings/.Settings }
Это открывает настройки практически на любом устройстве. Полная форма той же записи: com.android.settings/com.android.settings.Settings. Узнать стартовую Activity чужого приложения можно так:

Код: Выделить всё

adb shell cmd package resolve-activity --brief com.example.app
com.example.app/com.example.app.ui.MainActivity
Если выяснять компонент лень, запускайте приложение по имени пакета через monkey, одним событием с категорией LAUNCHER:

Код: Выделить всё

adb shell monkey -p com.example.app -c android.intent.category.LAUNCHER 1
У am start есть три флага, без которых я не живу. -S останавливает приложение перед запуском, -W ждёт окончания запуска и печатает тайминги, --user запускает от имени конкретного пользователя (актуально для рабочих профилей).

Код: Выделить всё

adb shell am start -S -W -n com.example.app/.ui.MainActivity
Stopping: com.example.app
Starting: Intent { cmp=com.example.app/.ui.MainActivity }
Status: ok
LaunchState: COLD
Activity: com.example.app/.ui.MainActivity
TotalTime: 734
WaitTime: 761
Complete
TotalTime - время холодного старта в миллисекундах, мы уже опирались на него в главе 10 при замерах производительности.

Intent без явного компонента:

Флаг -a задаёт action, -d передаёт data URI, -c добавляет категорию. Система сама подберёт обработчик, как при обычном неявном Intent.

Код: Выделить всё

adb shell am start -a android.intent.action.VIEW -d https://cyberlake.ru
Starting: Intent { act=android.intent.action.VIEW dat=https://cyberlake.ru/... }
Откроется браузер по умолчанию (или приложение, верифицировавшее этот домен через App Links). Многоточие в выводе нормально, Intent.toString с некоторых версий обрезает URI в логе. Категория уточняет выбор получателя, например

Код: Выделить всё

-c android.intent.category.BROWSABLE
оставит только компоненты, объявившие эту категорию в манифесте.

Классическая ловушка: символы ? и & в URL. Команда уходит во второй шелл на устройстве, и без кавычек & оборвёт её, отправив остаток в фон. Оборачивайте либо весь remote-кусок, либо сам URL:

Код: Выделить всё

adb shell "am start -a android.intent.action.VIEW -d 'https://cyberlake.ru/search?q=adb&page=2'"
Передача extras:

Строка кладётся через -e или его полный синоним --es, boolean через --ez, int через --ei. Есть и остальные типы: --el (long), --ef (float), --eu (URI), --esa (массив строк через запятую), --eia (массив int).

Код: Выделить всё

adb shell am start -n com.example.app/.DebugActivity --es env staging --ez mock_api true --ei retry_count 3
Starting: Intent { cmp=com.example.app/.DebugActivity (has extras) }
В коде приложения это читается обычными getIntent().getStringExtra("env"), getBooleanExtra("mock_api", false) и так далее. Со строками с пробелами та же история, что и с URL: локальный шелл снимает первый слой кавычек, поэтому нужен второй:

Код: Выделить всё

adb shell am start -n com.example.app/.NoteActivity --es title '"Отчет за июнь"'
Сервисы:

Сервис запускается через am start-service (историческое написание startservice тоже работает):

Код: Выделить всё

adb shell am start-service -n com.example.app/.SyncService
Starting service: Intent { cmp=com.example.app/.SyncService }
Если компонент не найден, получите

Код: Выделить всё

Error: Not found; no service started.
С Android 8 действуют фоновые ограничения: когда приложение в фоне, обычный start-service падает с ошибкой вида

Код: Выделить всё

Error: app is in background uid UidRecord{...}
. Обход - start-foreground-service, но тогда сервис обязан быстро вызвать startForeground, иначе система уронит его с ForegroundServiceDidNotStartInTimeException. На Android 14/15 вдобавок требуется объявленный foregroundServiceType в манифесте.

Код: Выделить всё

adb shell am start-foreground-service -n com.example.app/.SyncService
Broadcast:

Код: Выделить всё

adb shell am broadcast -a com.example.app.ACTION_DEBUG -n com.example.app/.DebugReceiver --ez verbose true --ei level 3
Broadcasting: Intent { act=com.example.app.ACTION_DEBUG flg=0x400000 cmp=com.example.app/.DebugReceiver (has extras) }
Broadcast completed: result=0
flg=0x400000 - это FLAG_RECEIVER_FROM_SHELL, система помечает им все broadcast из шелла автоматически. Два ограничения. Первое: с Android 8 манифестные ресиверы не получают большинство неявных broadcast, поэтому всегда указывайте получателя через -n. Второе: защищённые системные broadcast шелл слать не может:

Код: Выделить всё

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED
java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.BOOT_COMPLETED from pid=12345, uid=2000
uid=2000 - это shell. С root (глава 15) такое уходит, без него никак. Практичный легальный пример - демо-режим статусбара для чистых скриншотов (пригодится в главе 14):

Код: Выделить всё

adb shell settings put global sysui_demo_allowed 1
adb shell am broadcast -a com.android.systemui.demo -e command enter
adb shell am broadcast -a com.android.systemui.demo -e command clock -e hhmm 1000
adb shell am broadcast -a com.android.systemui.demo -e command exit
Остановка приложений:

force-stop убивает все процессы пакета и снимает его задачи:

Код: Выделить всё

adb shell am force-stop com.example.app
Вывода нет, это нормально. Нюанс, о который спотыкаются: после force-stop пакет попадает в stopped state и перестаёт получать broadcast (включая пуши), пока его не запустят заново. am kill мягче: он убивает только те процессы, которые безопасно убить, то есть фоновые. Приложению на экране kill ничего не сделает.

Код: Выделить всё

adb shell am kill com.example.app
adb shell am kill-all
kill-all снимает все фоновые процессы разом, удобно перед честным замером холодного старта.

Что сейчас запущено:

Код: Выделить всё

adb shell am stack list
RootTask id=1 bounds=[0,0][1080,2400] displayId=0 userId=0 visible=true
  taskId=74: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.android.settings/.Settings }
На Android 12+ строки начинаются с RootTask, на более старых версиях писалось Stack id=. Если нужен только текущий экран, надёжнее dumpsys (подробно о нём была глава 9):

Код: Выделить всё

adb shell dumpsys activity activities | grep -i resumedactivity
    topResumedActivity=ActivityRecord{a1b2c3 u0 com.android.settings/.Settings t74}
Живые процессы пакета смотрим обычным ps:

Код: Выделить всё

adb shell ps -A | grep com.example.app
u0_a217  14233  876  15234500 189456 0  0 S com.example.app
Готовые рецепты:

Звонок. DIAL открывает номеронабиратель с подставленным номером, CALL начинает вызов сразу: у shell есть разрешение CALL_PHONE, так что звонок реально пойдёт. Аккуратнее с короткими и платными номерами.

Код: Выделить всё

adb shell am start -a android.intent.action.DIAL -d tel:+74951234567
adb shell am start -a android.intent.action.CALL -d tel:+74951234567
SMS. SENDTO открывает приложение сообщений с готовым текстом, отправка остаётся за человеком:

Код: Выделить всё

adb shell am start -a android.intent.action.SENDTO -d sms:+79091234567 --es sms_body '"Тестовое сообщение с ADB"'
Настройки, сразу нужный экран:

Код: Выделить всё

adb shell am start -a android.settings.SETTINGS
adb shell am start -a android.settings.WIFI_SETTINGS
adb shell am start -a android.settings.BLUETOOTH_SETTINGS
adb shell am start -a android.settings.APPLICATION_DETAILS_SETTINGS -d package:com.example.app
adb shell am start -a android.settings.APPLICATION_DEVELOPMENT_SETTINGS
Четвёртая команда открывает карточку конкретного приложения (там очистка данных и разрешения), последняя - меню разработчика.

Частые ошибки:

Error type 3:

Код: Выделить всё

Error type 3
Error: Activity class {com.example.app/com.example.app.MainActivity} does not exist.
Причины: опечатка в компоненте, приложение не установлено, либо установлено у другого пользователя (рабочий профиль, второй юзер). Проверяйте

Код: Выделить всё

pm list packages --user 10 | grep example
и запускайте с

Код: Выделить всё

am start --user 10 -n ...
.

Permission Denial при запуске чужой внутренней Activity:

Код: Выделить всё

java.lang.SecurityException: Permission Denial: starting Intent { cmp=com.example.app/.InternalActivity } from null (pid=12345, uid=2000) not exported from uid 10217
Activity без android:exported="true" снаружи не запускается, и без root это не обходится. Для своих приложений решение простое: в debug-сборке экспортируйте отладочные экраны.

Третья по частоте проблема - кавычки, мы её разобрали выше: если extras или URL внезапно обрезаются, почти наверняка локальный шелл съел ваши кавычки или & ушёл в фон.

На этом с ActivityManager всё. В следующей главе займёмся его соседом, оконным менеджером wm: размеры, плотность, дисплеи.
👍5 ❤️2 🔥2 😄 🤔1
✔ Лучший ответ сформирован автоматически — regex_nerd
android_roman писал(а):CALL начинает вызов сразу: у shell есть разрешение CALL_PHONE, так что звонок реально пойдёт подтверждаю, проверил на Pixel 8 (Android 15), набирает без всяких подтверждений. чуть не позвонил клиенту в два ночи, когда отлаживал скрипт. тестируйте на второй симке или на номере коллеги, который не спит
Перейти к ответу →
Аватара пользователя
regex_nerd
Сообщения: 1
Зарегистрирован: 13 май 2026, 10:09

Re: Управление Activity и Intent (am)

Сообщение regex_nerd »

✔ Лучший ответ — сформирован автоматически
android_roman писал(а):CALL начинает вызов сразу: у shell есть разрешение CALL_PHONE, так что звонок реально пойдёт
подтверждаю, проверил на Pixel 8 (Android 15), набирает без всяких подтверждений. чуть не позвонил клиенту в два ночи, когда отлаживал скрипт. тестируйте на второй симке или на номере коллеги, который не спит
👍1 ❤️2 🔥 😄 🤔
Аватара пользователя
tw1x
Сообщения: 2
Зарегистрирован: 15 май 2026, 15:06

Re: Управление Activity и Intent (am)

Сообщение tw1x »

а как заставить -a VIEW -d открыть ссылку в конкретном браузере, а не в том что по умолчанию? у меня на тестовом самсунге дефолтный их родной интернет, а мне надо в хроме проверять
👍1 ❤️1 🔥 😄 🤔
Аватара пользователя
elastic2
Сообщения: 2
Зарегистрирован: 12 май 2026, 05:14

Re: Управление Activity и Intent (am)

Сообщение elastic2 »

спасибо за --user, два часа ловил Error type 3 на устройстве с рабочим профилем, пакет точно стоял, pm list packages его показывал. оказалось приложение было только в профиле user 10, с am start --user 10 всё взлетело
👍2 ❤️2 🔥 😄 🤔
Аватара пользователя
borya2003
Сообщения: 3
Зарегистрирован: 21 май 2026, 22:02

Re: Управление Activity и Intent (am)

Сообщение borya2003 »

android_roman писал(а):после force-stop пакет попадает в stopped state и перестаёт получать broadcast (включая пуши), пока его не запустят заново
так вот почему у тестировщиков FCM молчит после остановить в настройках... а am kill в этом плане безопасен, пуши после него приходят? или тоже stopped state?
👍1 ❤️ 🔥 😄 🤔
Ответить
← Предыдущая глава
Эмуляция ввода (input)
Следующая глава →
Работа с оконным менеджером (wm)

Все главы курса «ADB: Android Debug Bridge»

Поделиться темой: ✈ Telegram VK
  • Похожие темы

Вернуться в «ADB: Android Debug Bridge»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость