Что важно знать разработчику при адаптации под Android 12
Кратко: Android 12 (API 31) вводит новые runtime‑разрешения (новые Bluetooth‑права, approximate location), строгие требования к PendingIntent и android:exported, ограничивает запуск foreground‑служб из фона и добавляет поведение авто‑сброса прав — всё это требует правок манифеста, кода и тестов перед релизом.
Ключевые изменения, влияющие на совместимость
-
PendingIntent: теперь обязательно указывать FLAG_IMMUTABLE или FLAG_MUTABLE. По умолчанию используйте FLAG_IMMUTABLE и ставьте FLAG_MUTABLE только когда действительно изменяете intent (например, inline reply).
- Пример: PendingIntent.getActivity(ctx, id, intent, PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT)
-
android:exported: для Activity/Service/BroadcastReceiver с intent‑filter нужно явно указать android:exported="true" или "false". Иначе сборка/установка при targetSdk 31 провалится.
-
Foreground‑сервисы: запрещён запуск startForegroundService из фона для приложений, таргетирующих S+. Для срочных задач используйте WorkManager (expedited work) или exact alarm + запуск сервиса в момент выполнения.
-
Разрешения локации: появилась опция approximate location — UX должен предугадывать, что пользователь может дать только ACCESS_COARSE_LOCATION. Запрашивайте и обрабатывайте оба варианта.
-
Bluetooth: старые BLUETOOTH/BLUETOOTH_ADMIN заменены на BLUETOOTH_SCAN, BLUETOOTH_CONNECT, BLUETOOTH_ADVERTISE с новыми ограничениями для фонового сканирования.
-
App hibernation и auto‑reset permissions: система может сбрасывать runtime‑permissions и останавливать фоновые процессы для неиспользуемых приложений — добавьте сценарии повторного получения прав и восстановления состояния.
-
Нотификации и trampoline: ограничено использование "трамплинов" для запуска Activity из фоновых компонентов; проверьте ваши уведомления и deeplink‑обработку.
-
Мультимедиа и WebView: платформа добавляет AVIF и транс‑кодирование, WebView ужесточил SameSite cookies — проверьте сценарии авторизации через встроенные вебы.
Большинство изменений применяются именно к приложениям с targetSdkVersion = 31. Если пока не обновляете target, всё равно тестируйте на Android 12-устройствах.
Практический чек‑лист перед релизом
- Обновить compileSdkVersion = 31 и targetSdkVersion = 31 в Gradle, собрать проект и исправить ошибки сборки.
- Найти и исправить все PendingIntent — добавить FLAG_IMMUTABLE/FLAG_MUTABLE.
- Пройти mergedManifest и явно указать android:exported для всех компонентов с intent‑filter.
- Переработать фоновые задачи: заменить неразрешённый startForegroundService на WorkManager/expedited work или exact alarm.
- Заменить старые Bluetooth‑perm на новые и реализовать runtime‑запросы для BLUETOOTH_SCAN/CONNECT/ADVERTISE.
- Обработать approximate location в логике и запросах разрешений.
- Перейти на SplashScreen API, если используете кастомные сплэш‑решения.
- Добавить UX для восстановления прав после app hibernation (информирование и повторный запрос).
- Обновить сторонние SDK (push, аналitika, платежи) до версий, совместимых с API 31.
- Прогнать smoke‑tests: permissions flows, BLE сценарии, уведомления, foreground‑work, WebView auth, воспроизведение/загрузка медиа.
Тестируйте сначала с targetSdk 31 в debug‑сборке и включайте режимы совместимости в Developer options — это помогает локализовать причины сбоев быстрее.
Тестирование и распространённые проблемы (и как их решать)
- Ошибка "requires FLAG_IMMUTABLE" → найти все вызовы PendingIntent и указать флаг. Используйте статический анализатор или grep по проекту.
- Manifest merger: "android:exported needs to be explicitly specified" → проверьте зависимости и плагины, обновите/патчьте манифесты библиотек.
- Crash при Bluetooth‑сканировании → убедитесь в наличии BLUETOOTH_SCAN + runtime‑запросах, обработайте отказ пользователя и ограничения фонового сканирования.
- ForegroundServiceStartNotAllowedException → замените логику запуска на WorkManager/expedited work или поднимайте foreground‑сервис только из пользовательского контекста (взаимодействие UI).
- WebView SameSite/авторизация ломает флоу → тестируйте входы через встроенный браузер, при необходимости реализуйте fallback на внешние браузеры или web auth flows.
Обновление только compileSdk без проработки поведенческих изменений часто вызывает runtime‑краши на устройствах с Android 12. Проверяйте не только сборку, но и реальные сценарии.
Частые ошибки
- Забыт FLAG_IMMUTABLE в PendingIntent.
- Не указано android:exported в компонентах из библиотек.
- Ожидание, что BLE‑поведение осталось прежним — фоновые сканы теперь строже.
- Нет UX для восстановления прав после hibernation — потеря функциональности без объяснения пользователю.
FAQ
-
Нужно ли срочно менять targetSdk на 31?
- Менять стоит планово: сначала в debug‑ветку, исправить все ошибки сборки и поведенческие регрессии, затем выпускать обновление. Play Console может требовать обновлённый target для новых публикаций.
-
Как быстро найти все PendingIntent в коде?
- Поиск по getActivity/getService/getBroadcast + ревью библиотек; статический анализ и CI‑шаблоны помогут предотвратить пропуски.
-
Что делать, если уведомления перестали запускать Activity?
- Убедитесь, что вы не используете trampoline (запуск Activity через короткий intermediate receiver/service). В Intent, который передаёте в PendingIntent, укажите явную Activity и правильные флаги, и соблюдайте требования FLAG_IMMUTABLE.
Короткий план на неделю: обновить target/compile → исправить сборку (exported, PendingIntent) → обновить SDK依赖 → ручное тестирование на Android 12 (permissions, BLE, notifications, foreground‑work) → выпуск. Если нужно, подготовлю diff и набор adb/espresso тестов под ваш стек.