CLOUSD
Создать аккаунт
Тестирование

Тестирование приложения на разных версиях Android

Что меняется для вашего приложения от Android 12 до 17, версия за версией, как проверить поведение, привязанное к target, до того как поднимать targetSdkVersion, и чек-лист для каждого релиза.

Android выпускает крупный релиз каждый год, и каждый меняет поведение, на которое опирается ваше приложение. Тестировать приложение на разных версиях Android не значит поставить один и тот же APK на шесть телефонов и убедиться, что он открывается. Это значит знать, какие изменения касаются вас на каком релизе и почему одна и та же сборка может по-разному вести себя на двух из них.

В этом гайде Android с 12 по 17 разобран для разработчиков приложений: что меняется, как проверить каждое изменение через adb и как попробовать поведение, привязанное к target, до того как поднимать targetSdkVersion.

Две оси, а не одна

Каждое изменение поведения в Android относится к одной из двух групп. Изменения для всех приложений действуют, как только на устройстве стоит новый релиз, независимо от того, на что нацелено ваше приложение. Изменения, привязанные к target, действуют только тогда, когда ваш targetSdkVersion не ниже уровня API этого релиза.

Получаются две оси. Версия устройства определяет первую группу, ваш target определяет вторую. Почему важны обе, хорошо видно на примере разрешения на уведомления в Android 13. Приложение с target API 32 или ниже получает запрос от системы, как только у него появился канал уведомлений и оно запустило activity. Приложение с target 33 должно запросить разрешение само, в момент, который выберет само. Код один, а сценарии первого запуска разные.

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

Android с 12 по 17: краткая сводка

ВерсияУровень APIЧто чаще всего ломает приложения
1231 (у 12L — 32)явный android:exported; флаг изменяемости PendingIntent; запрет запускать foreground service из фона; приблизительная геолокация; системный splash screen
1333разрешение POST_NOTIFICATIONS; отдельные разрешения на медиа вместо чтения хранилища; системный выбор фото; язык для отдельного приложения
1434частичный доступ «Выбрать фото»; обязательные типы foreground service; точные будильники по умолчанию выключены для новых установок; флаг экспорта для ресиверов, зарегистрированных в коде; приложения с target ниже 23 не ставятся
1535обязательный edge-to-edge; устройства со страницами памяти 16 КБ; приложения с target ниже 24 не ставятся; анимации predictive back для приложений, которые их включили
1636отказ от edge-to-edge больше не работает; predictive back включён по умолчанию, onBackPressed() больше не вызывается; на больших экранах ограничения ориентации и размера окна игнорируются
1737Google сообщил, что временный отказ от правил для больших экранов, появившийся в 16, заканчивается со следующим релизом; прочитайте полный список изменений поведения, прежде чем поднимать target

Уведомления (Android 13)

На 13 и новее уведомления выключены, пока пользователь их не разрешит. Проверьте три пути: разрешить, запретить и запретить дважды, после чего система перестаёт показывать диалог, и приложению нужно отправлять пользователя в настройки. Затем проверьте на 12, где запроса нет вовсе, чтобы онбординг не просил разрешение, которого там не существует.

Переключайте разрешение между попытками:

adb shell pm revoke com.example.app android.permission.POST_NOTIFICATIONS
adb shell pm grant com.example.app android.permission.POST_NOTIFICATIONS
adb shell dumpsys package com.example.app | grep POST_NOTIFICATIONS

Если пользователь дважды отказал, отзыв разрешения не вернёт диалог первого запуска. Чтобы увидеть то, что видит новый пользователь, удалите приложение и поставьте заново.

Фото и медиа (Android 13 и 14)

Приложения с target 33 больше не могут читать медиа через READ_EXTERNAL_STORAGE. Вместо этого они запрашивают READ_MEDIA_IMAGES, READ_MEDIA_VIDEO или READ_MEDIA_AUDIO. Android 14 добавляет к запросу доступа к фото и видео третий ответ: пользователь может открыть только выбранные файлы. Тогда у приложения есть READ_MEDIA_VISUAL_USER_SELECTED, оно видит только эти файлы и должно давать способ изменить выбор, а не рассчитывать на всю галерею.

Чище путь через системный выбор фото: ему вообще не нужно разрешение. ActivityResultContracts.PickVisualMedia открывает системный picker там, где он есть, и переключается на ACTION_OPEN_DOCUMENT там, где его нет. На Android 11 и 12 picker приходит через системные обновления Google Play, поэтому на конкретном телефоне может оказаться любой из двух путей. Выводите в лог isPhotoPickerAvailable() на каждом телефоне и убедитесь, что сценарий работает в обоих вариантах.

Заполните галерею до начала теста, потому что пустой picker скрывает ошибки вёрстки:

adb push sample-photos/ /sdcard/Pictures/

Файлы, загруженные в общее хранилище, обычно появляются в MediaStore за секунды. Если нет, откройте picker заново.

Фоновая работа (Android 12, 14 и 15)

Из-за трёх изменений фоновые ошибки зависят от версии. С 12-й версии приложение в фоне больше не может запустить foreground service, кроме короткого списка исключений: вызов бросает ForegroundServiceStartNotAllowedException. С 14-й приложение с target 34 обязано указать foregroundServiceType для каждого foreground service и соответствующее разрешение, например FOREGROUND_SERVICE_DATA_SYNC, иначе запуск не пройдёт. С 15-й foreground service типа dataSync в приложении с target 35 получает примерно шесть часов в сутки, после чего срабатывает колбэк таймаута.

Изменились и точные будильники. SCHEDULE_EXACT_ALARM появилось в 12, а на 14 оно больше не выдаётся по умолчанию новым установкам приложений с target 13 и выше. Вызывайте canScheduleExactAlarms() и обрабатывайте ответ false.

Создавайте условия принудительно, а не ждите их. Первые три строки переводят телефон в doze, а приложение в низкую группу режима ожидания; прогоните сценарий и верните всё двумя последними:

adb shell dumpsys battery unplug
adb shell dumpsys deviceidle force-idle
adb shell am set-standby-bucket com.example.app rare
adb shell dumpsys deviceidle unforce
adb shell dumpsys battery reset

Edge-to-edge и навигация назад (Android 15 и 16)

Приложение с target 35 на Android 15 рисует под строкой состояния и панелью навигации, просило оно об этом или нет. Без учёта отступов (insets) тулбары уезжают под строку состояния, кнопки под полоску жестов, а текст под вырез экрана. Android 15 ещё учитывает атрибут, который от этого отказывается. На 16 приложения с target 36 этой возможности лишаются.

Проверяйте каждый экран в обоих режимах навигации, потому что трёхкнопочная навигация оставляет более высокую панель, под которую нужен отступ. На сборках на базе AOSP режим можно переключить через adb, в остальных случаях через Настройки → Система → Жесты:

adb shell cmd overlay enable-exclusive --category com.android.internal.systemui.navbar.threebutton
adb shell cmd overlay enable-exclusive --category com.android.internal.systemui.navbar.gestural

Predictive back прошёл похожий путь. На 13 и 14 он спрятан в параметрах разработчика. На 15 системные анимации работают для приложений, которые включили их через android:enableOnBackInvokedCallback. На 16 приложения с target 36 получают его по умолчанию, и onBackPressed() больше не вызывается. Пройдитесь поиском по коду, прежде чем поднимать target:

grep -rn "onBackPressed\|KEYCODE_BACK" app/src/main

Перенесите каждое совпадение на OnBackPressedCallback и проверьте жест «назад» с каждого экрана, включая диалоги и bottom sheet.

Android 16 меняет и большие экраны. На дисплеях с наименьшей шириной от 600 dp приложение с target 36 теряет блокировку ориентации и resizeableActivity="false". В Android 16 есть временный отказ от этого, и Google сообщил, что он исчезнет со следующим релизом, так что рассчитывайте, что при target 37 его уже не будет. Если ваше приложение зафиксировано в портретной ориентации, проверьте его на большом экране, прежде чем поднимать target.

Страницы памяти 16 КБ (Android 15)

Android 15 добавил поддержку устройств со страницами памяти 16 КБ вместо 4 КБ. Приложения с нативным кодом должны выравнивать под это свои библиотеки, а с ноября 2025 года Google Play требует поддержку 16 КБ для новых приложений и обновлений с target Android 15 и выше. Проверьте размер страницы на телефоне и свою сборку:

adb shell getconf PAGE_SIZE
zipalign -c -P 16 -v 4 app-release.apk
llvm-objdump -p lib/arm64-v8a/libfoo.so | grep LOAD

Сегменты LOAD должны показывать align 2**14. Android Gradle Plugin 8.5.1 и новее выравнивает несжатые библиотеки внутри APK, а NDK r28 и новее по умолчанию компилирует с выравниванием 16 КБ, так что виноваты обычно готовые сторонние библиотеки. Телефон с размером страницы 4096 ничего не скажет о поведении с 16 КБ: эту проверку запускайте на системном образе эмулятора с 16 КБ.

Проверьте изменения, привязанные к target, до повышения targetSdk

Чтобы увидеть большую часть такого поведения, поднимать targetSdkVersion не обязательно. Фреймворк совместимости Android позволяет включать отдельные изменения для отлаживаемой сборки:

adb shell dumpsys platform_compat | grep -i edge
adb shell am compat enable CHANGE_NAME com.example.app
adb shell am compat reset CHANGE_NAME com.example.app

Те же переключатели есть в параметрах разработчика, в разделе изменений совместимости приложений. Включайте по одному изменению и прогоняйте smoke-тест. Когда список чистый, поднимите target в отдельной ветке и прогоните всю матрицу.

Где запускать матрицу

Большинство команд используют три вида устройств. Системные образы эмулятора есть для каждого уровня API и ничего не стоят, поэтому подходят для инструментальных тестов и прогонов по API в CI. Облачные телефоны дают каждый релиз на моделях настоящих телефонов и сохраняют состояние между сеансами: Clousd запускает Android с 12 по 17 на 150+ моделях, а телефон между прогонами сбрасывается в чистое состояние. Физические телефоны остаются эталоном для камеры, датчиков, графики и поведения софта производителя.

В списке моделей видно, какие модели работают в облаке, а на странице о тестировании приложений показано, как встроить матрицу в CI. Впервые работаете с удалёнными телефонами? Начните с гайда о тестировании Android-приложения онлайн, а разницу между образами эмулятора и настоящими моделями разбирает статья об облачном эмуляторе Android.

Чек-лист для каждого релиза

  • Поставьте текущую сборку на новый релиз с текущим target: она ставится, запускается и переживает смерть процесса.
  • Прочитайте страницу «изменения поведения для всех приложений» и проверьте каждый пункт, который касается ваших функций.
  • Первый запуск без выданных разрешений, затем отказ в каждом разрешении по очереди.
  • Уведомления: момент запроса, отказ и ссылка в настройки.
  • Медиа: системный выбор фото, частичный доступ, пустая галерея.
  • Фон: foreground service, точные будильники, doze и группы режима ожидания.
  • Вёрстка: отступы в обоих режимах навигации, вырезы экрана, размер шрифта 1.3, тёмная тема.
  • Назад: жест «назад» с каждого экрана, диалога и bottom sheet.
  • Нативный код: выравнивание 16 КБ у каждой библиотеки.
  • Поднимите target в ветке, прочитайте «изменения поведения для приложений с target» нового уровня и повторите.

Читайте также

Все гайды

Готовы запустить
свой первый облачный телефон?

Попробовать 30 минут бесплатно

Карта не нужна