Storage Access Framework — это фреймворк Android для безопасного доступа к файлам и документам через системный диалог выбора. Вместо запроса широких разрешений на чтение хранилища приложение получает URI-ссылку на файл, выбранный пользователем. По данным Android Developers (2026), SAF поддерживает локальное хранилище, облачные сервисы Google Drive и Dropbox через DocumentProvider. Фреймворк внедрён в Android 4.4 и стал стандартом работы с документами начиная с Android 10.
Главное
Storage Access Framework — это часть Android SDK, которая предоставляет единый интерфейс для выбора и создания документов через системный диалог. SAF абстрагирует физическое расположение файлов: приложение не знает, откуда читается файл — с локального диска, Google Drive или Dropbox.
Архитектура SAF включает три компонента: клиентское приложение, которое инициирует запрос, системный пикер — стандартный диалог выбора файла, и DocumentProvider — контент-провайдер, реализующий доступ к файлам конкретного хранилища. Пользователь видит единый интерфейс независимо от источника данных.
SAF доступен начиная с Android 4.4 (API 19). Изначально фреймворк поддерживал только документы, но в Android 5.0 добавили поддержку директорий через ACTION_OPEN_DOCUMENT_TREE. С Android 10 SAF стал рекомендованным способом доступа к любому файлу за пределами app-specific storage.
SAF запускает системный диалог выбора файла через Intent с действием ACTION_OPEN_DOCUMENT. Пользователь видит список доступных источников: внутренняя память, Google Drive, Dropbox и другие зарегистрированные провайдеры. После выбора файла система возвращает content URI с временными правами доступа.
Content URI имеет формат content://com.android.externalstorage.documents/document/primary/Download/file.pdf. В отличие от file:// URI, content URI не раскрывает реальный путь к файлу и работает через DocumentProvider. Приложение читает файл через ContentResolver.openInputStream по полученному URI.
Системный пикер автоматически поддерживает поиск, сортировку и фильтрацию файлов по MIME-типам. Разработчик указывает нужные типы через Intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("application/pdf", "image/*")), и пикер показывает только релевантные файлы.
По умолчанию URI действителен до перезапуска приложения или перезагрузки устройства. Для долгосрочного доступа приложение запрашивает takePersistableUriPermission — это разрешает читать файл при последующих запусках без повторного выбора через диалог.
SAF предоставляет три основных действия для работы с файлами: открытие, создание и выбор дерева папок. ACTION_OPEN_DOCUMENT открывает системный пикер для выбора существующего файла. ACTION_CREATE_DOCUMENT создаёт новый файл — пользователь вводит имя в диалоге, а приложение получает URI для записи.
ACTION_OPEN_DOCUMENT_TREE позволяет выбрать целую директорию и получить доступ ко всем файлам в ней. Это используется в файловых менеджерах, приложениях для резервного копирования и синхронизации. Приложение получает URI директории и может рекурсивно перечислять содержимое через DocumentFile.
| Действие | Назначение | Флаг |
|---|---|---|
| ACTION_OPEN_DOCUMENT | Выбор существующего файла | READ_FLAG |
| ACTION_CREATE_DOCUMENT | Создание нового файла | WRITE_FLAG |
| ACTION_OPEN_DOCUMENT_TREE | Выбор директории | READ + WRITE |
Для каждого действия указываются MIME-типы через EXTRA_MIME_TYPES. Можно указать несколько типов: "application/pdf", "image/*", "text/plain". Если типы не указаны, пикер показывает все файлы.
Persistent URI permissions — механизм SAF, позволяющий сохранять доступ к файлу после завершения текущей сессии. Без этого флага URI действителен только до перезапуска приложения. Приложение запрашивает флаг FLAG_GRANT_PERSISTABLE_URI_PERMISSION вместе с READ и WRITE флагами.
Для сохранения прав используется метод ContentResolver.takePersistableUriPermission. Система сохраняет URI в специальном реестре и восстанавливает доступ при следующем запуске приложения. Чтобы проверить, есть ли у приложения persistent доступ к URI, используется ContentResolver.persistedUriPermissions.
Пользователь может отозвать сохранённые разрешения через Настройки → Приложения → Разрешения. Приложение должно обрабатывать сценарий, когда доступ к файлу неожиданно пропал. Рекомендуется проверять доступ через ContentResolver.openInputStream перед началом работы и корректно обрабатывать SecurityException.
SAF запускается через стандартный Intent. Код минимален: создать Intent с ACTION_OPEN_DOCUMENT, указать MIME-типы и запустить через ActivityResultContracts.StartActivityForResult. После выбора файла callback получает URI в data.data, который затем используется для чтения.
val pickFile = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result ->
result.data?.data?.let { uri ->
val inputStream = contentResolver?.openInputStream(uri)
// read from inputStream
}
}
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
setType("application/pdf")
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
pickFile.launch(intent)
Для записи нового файла используйте ACTION_CREATE_DOCUMENT. Intent принимает MIME-тип и имя файла через EXTRA_TITLE. После выбора папки и подтверждения пользователь возвращает URI, в который приложение записывает данные через ContentResolver.openOutputStream. Система автоматически создаёт файл в выбранном расположении.
SAF отличается от традиционного READ_EXTERNAL_STORACE принципиально другим подходом к безопасности. Вместо запроса доступа ко всему хранилищу при запросе "одним махом" SAF запрашивает доступ только к конкретному файлу. Это минимизирует поверхность атаки и повышает доверие пользователя.
READ_EXTERNAL_STORAGE даёт доступ ко всем файлам на устройстве, включая фотографии и документы других приложений. На Android 10+ этот подход ограничен. SAF, напротив, предоставляет доступ только к выбранному пользователем файлу и требует явного подтверждения на каждый файл. Для пакетной работы с медиа используйте MediaStore, для единичных документов — SAF.
Основной недостаток SAF — необходимость выбора каждого файла отдельно. Для массовых операций (резервное копирование, синхронизация папки) используется ACTION_OPEN_DOCUMENT_TREE, который даёт доступ ко всем файлам в выбранной директории. Решение зависит от сценария: SAF оптимален для пользовательского выбора, MediaStore — для программного доступа к медиа.
Часто задаваемые вопросы
Storage Access Framework — это фреймворк Android для безопасного доступа к файлам через системный диалог выбора. Приложение получает content URI на выбранный файл без запроса широких разрешений на чтение хранилища.
Создайте Intent с ACTION_OPEN_DOCUMENT, укажите MIME-тип через setType и запустите через ActivityResultContracts. В callback получите URI из data.data и читайте через ContentResolver.openInputStream.
Persistent URI permissions — это механизм сохранения доступа к URI после перезапуска приложения. Запрашивается через флаг FLAG_GRANT_PERSISTABLE_URI_PERMISSION и метод takePersistableUriPermission.
SAF поддерживает любые MIME-типы: application/pdf, image/*, text/plain, application/zip и другие. Типы указываются через Intent.putExtra с EXTRA_MIME_TYPES массивом.
SAF предназначен для выбора единичных файлов пользователем через системный диалог. MediaStore даёт программный доступ ко всем медиафайлам устройства через медиа-базу без участия пользователя.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также