Краткое руководство по приложениям на Android 11: разрешения, уведомления и совместимость
Android 11 усилил приватность: появились одноразовые разрешения и auto‑revoke, стал обязательным scoped storage для targetSdk≥30, добавлены Conversation/Bubbles и ужесточены правила MANAGE_EXTERNAL_STORAGE — ключевые действия: мигрировать на MediaStore/SAF/app‑specific, проверить логику запросов разрешений и привести уведомления к MessagingStyle/Person.
Разрешения и поведение системы
Что важно учесть сразу и как это реализовать:
- Одноразовые разрешения: пользователь может дать доступ «только в этот раз». Проверяйте разрешение при каждом запуске критичной функциональности и готовьте понятный rationale.
- Auto‑revoke: система сбрасывает чувствительные runtime‑права у неиспользуемых приложений. При старте функционала проверяйте и заново запрашивайте права.
- Background‑location: запрашивайте сначала foreground‑location, затем — по необходимости — background; Google Play требует обоснования.
Практика
- Всегда проверяйте ContextCompat.checkSelfPermission перед доступом.
- При отказе показывайте объяснение и предлагаете deep link в системные настройки.
- Для критичных фич (резервное копирование, менеджеры файлов) заранее объясняйте пользователю, зачем нужен доступ.
Если функциональность зависит от прав постоянно, реализуйте экран с объяснением и кнопкой «Открыть настройки», чтобы избежать потерь пользователя после auto‑revoke.
Scoped Storage и доступ к файлам — куда мигрировать и когда нужен All files access
Основной принцип: ограничить произвольный доступ в shared storage. Варианты работы с файлами:
Сравнение способов доступа к файлам
| Способ | Что даёт | Когда использовать |
|---|---|---|
| App‑specific dirs (getExternalFilesDir) | Полный доступ в приватной папке приложения | Для файлов, которыми оперирует только приложение |
| MediaStore API | Запись/чтение медиаконтента через индексированную БД | Для фото, видео, аудио — рекомендовано |
| Storage Access Framework (SAF) | Доступ к выбранным пользователем папкам/файлам | Для документов и произвольных файлов, где нужен пользовательский выбор |
| MANAGE_EXTERNAL_STORAGE | Доступ ко всей общей файловой системе | Только для файловых менеджеров/backup — с декларацией в Play Console |
Практические шаги миграции
- Проведите аудит всех прямых обращений к Environment.getExternalStorageDirectory и Android/data; замените на app‑specific/MediaStore/SAF.
- Тестируйте массовые операции через batch‑методы MediaStore и выполняйте I/O вне UI‑потока.
- Если действительно нужен MANAGE_EXTERNAL_STORAGE, подготовьте декларацию для публикации и реализуйте понятный диалог включения разрешения. Для локальной отладки можно временно разрешить через adb: adb shell appops set <PACKAGE_NAME> MANAGE_EXTERNAL_STORAGE allow
Не добавляйте MANAGE_EXTERNAL_STORAGE «на всякий случай» — Google Play строго проверяет оправданность.
Уведомления: Conversations, Bubbles и поведение истории уведомлений
Что нужно поменять в реализации уведомлений:
- Для попадания в Conversation section используйте Notification.MessagingStyle, подключайте объекты Person и shortcutId.
- Чтобы поддержать Bubbles, формируйте Notification с корректным BubbleMetadata и не удаляйте уведомление сразу после создания пузыря (используйте флаги suppression по документации).
- Ожидайте, что пользователи могут восстанавливать недавно закрытые уведомления через системную историю уведомлений; тестируйте поведение с media controls и quick settings.
Практические советы
- Тестируйте уведомления на реальных устройствах с API 30+, проверяйте видимость в Conversation section и работу Bubbles.
- При отправке сообщений обновляйте существующий notificationId, используйте PendingIntent с FLAG_UPDATE_CURRENT.
Частые ошибки
- EACCES / Permission denied при File API: причина — scoped storage. Решение — мигрировать данные в app‑specific/MediaStore/SAF.
- Замедление при массовых операциях: решение — использовать batch‑операции MediaStore и выполнять I/O в background.
- Уведомления не становятся Conversation/Bubble: проверьте MessagingStyle, Person и shortcutId.
- Функции «сломались» после длительного простоя: проверьте auto‑revoke и добавьте проверку прав при старте.
- Отклонение в Play Console из‑за MANAGE_EXTERNAL_STORAGE: уберите его или подготовьте полноценную декларацию и описание кейсов.
FAQ
- Нужно ли менять targetSdk на 30 немедленно? Рекомендуется тестировать миграцию локально и планировать обновление targetSdk заранее — после повышения нужно соблюдать все ограничения API 30.
- Как проверить, сброшено ли разрешение пользователю? Всегда проверяйте checkSelfPermission перед операцией и показывайте rationale/направление в настройки при отказе.
- Можно ли временно обойти scoped storage для тестов? Для отладки используют adb‑команды или специальные флаги на эмуляторе, но в проде полагаться на это нельзя.
- Что эффективнее для медиаконтента — MediaStore или SAF? MediaStore — оптимальный выбор для фото/видео/аудио; SAF применим для документов и пользовательских папок.
Контрольный чеклист перед обновлением targetSdk до 30
- Аудит прямых обращений к общему хранилищу.
- Миграция данных в app‑specific или MediaStore.
- Обновление логики запросов разрешений (one‑time, rationale, auto‑revoke).
- Приведение уведомлений к MessagingStyle/Person/shortcutId.
- Подготовка декларации для MANAGE_EXTERNAL_STORAGE, если он необходим.
Если нужно, подготовлю конкретный план миграции манифеста и примеры кода для MediaStore/SAF под ваш проект или разберу ваш AndroidManifest.xml и список разрешений — укажите, что предпочитаете.