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 в спеціальному реєстрі та відновлює доступ при наступному запуску додатка. Щоб перевірити, чи є у додатка постійний доступ до 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_STORAGE принципово іншим підходом до безпеки. Замість запиту доступу до всього сховища одним запитом 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також