Какие разрешения нужны для доступа к файлам и как их запросить

Короткий ответ: для Android < 11 (API < 30) нужны READ/WRITE_EXTERNAL_STORAGE; для Android 10+ стоит использовать Scoped Storage — MediaStore и SAF; полный доступ (MANAGE_EXTERNAL_STORAGE) разрешают только для узких кейсов (файловые менеджеры) и требует обоснования в Play Console. Ниже — практические инструкции и готовые примеры.

Типы разрешений и когда они требуются

  • READ_EXTERNAL_STORAGE / WRITE_EXTERNAL_STORAGE — классические разрешения для общих файлов на старых устройствах (maxSdkVersion 32). С Android 10 их использование ограничено.
  • Scoped Storage (Android 10+ / 11+) — система, где приложение получает доступ к своим папкам, медиатеке через MediaStore и отдельным выбранным файлам через SAF. Рекомендуется по умолчанию.
  • MANAGE_EXTERNAL_STORAGE — "полный доступ" (All files access). Только для приложений с реальной потребностью (файловые менеджеры, бэкап‑утилиты). Требует политики и проверки в маркетах.

Используйте Storage Access Framework (SAF) для работы с документами и произвольными файлами — пользователь сам выбирает файлы и нет необходимости в глобальных разрешениях.

Как добавить разрешения в AndroidManifest.xml

Добавьте классические разрешения ограничив maxSdkVersion:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
                 android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
                 android:maxSdkVersion="32"/>
<!-- Только для кейсов полного доступа -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

maxSdkVersion="32" гарантирует, что на новых API система будет использовать Scoped Storage.

Как корректно запрашивать разрешения в коде (Kotlin)

Используйте ActivityResult API:

private val requestPermissionLauncher =
    registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
        if (granted) loadFiles()
        else showRationaleDialog()
    }

private fun requestStoragePermission() {
    when {
        ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
            == PackageManager.PERMISSION_GRANTED -> loadFiles()
        shouldShowRequestPermissionRationale(Manifest.permission.READ_EXTERNAL_STORAGE) -> showRationaleDialog()
        else -> requestPermissionLauncher.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
    }
}

Обязательно показывайте объяснение (rationale) если shouldShowRequestPermissionRationale() == true — иначе пользователь может "запомнить" отказ.

Работа с файлами без глобальных разрешений

  • Media (фото/видео/аудио): используйте MediaStore для чтения/записи медиаконтента.
  • Документы/любые файлы: открывайте селектор через SAF:
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
    addCategory(Intent.CATEGORY_OPENABLE)
    type = "*/*"
}
startActivityForResult(intent, REQUEST_CODE_OPEN)
  • Для файлов, принадлежащих приложению, используйте getExternalFilesDir() — разрешения не нужны.

MANAGE_EXTERNAL_STORAGE строго контролируется. Без ясного обоснования запрос будет отклонён в магазине приложений.

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

  • Запрос разрешения при старте приложения вместо Just‑In‑Time — снижает конверсию.
  • Игнорирование shouldShowRequestPermissionRationale() — пользователь не поймёт, зачем нужен доступ.
  • Тестирование только на одном API: проверяйте поведение на Android 9, 10, 11+.
  • Просить MANAGE_EXTERNAL_STORAGE без необходимости — риск блокировки при модерации.

FAQ

  • Нужен ли WRITE_EXTERNAL_STORAGE на Android 11+?
    Нет, для медиаконтента используйте MediaStore; для документов — SAF. WRITE_EXTERNAL_STORAGE устарел для большинства задач.

  • Когда стоит запрашивать MANAGE_EXTERNAL_STORAGE?
    Только если приложение реально требует полного доступа (файловый менеджер). Готовьте детальное обоснование для магазина и логику минимизации доступа.

  • Как дать пользователю выбор файлов без разрешений?
    Через SAF (ACTION_OPEN_DOCUMENT / ACTION_CREATE_DOCUMENT). Это лучший подход для работы с отдельными файлами.

  • Нужно ли хранить URI после выбора файла через SAF?
    Да — сохраните persistable URI permission через ContentResolver.takePersistableUriPermission(), если планируете доступ позже.

Соблюдая эти практики, ваше приложение корректно будет работать на разных версиях Android, минимизируя риски отказа в публикации и повышая доверие пользователей.�