Робота з файловою системою — основа будь-якого мобільного додатка. Кожна платформа пропонує свою модель доступу: Sandbox на iOS ізолює додатки в окремих контейнерах, а Scoped Storage на Android обмежує прямий доступ до спільного сховища. За даними Google Developer Documentation (2026), впровадження Scoped Storage з Android 10 потребувало повного перегляду архітектури зберігання даних. У цьому посібнику розглянемо FileManager, MediaStore API, Storage Access Framework та DocumentProvider для обох платформ.
Головне
Файлова система в мобільних додатках — це набір API, правил безпеки та обмежень, що визначають зберігання та доступ до даних на пристроях iOS та Android. На відміну від десктопних ОС, мобільні платформи ізолюють кожен додаток, щоб захистити дані користувача від несанкціонованого читання іншими програмами.
iOS використовує модель Sandbox, де кожен додаток існує у власному контейнері з жорстко обмеженими правами. Android до версії 10 надавав повний доступ до зовнішнього сховища, але з впровадженням Scoped Storage підхід став ближчим до iOS. Ключова відмінність — iOS повністю ізолює файлову систему, а Android пропонує кілька рівнів доступу: приватний каталог, загальнодоступний MediaStore та тимчасовий доступ через SAF.
Мобільні додатки використовують три типи сховищ даних. Приватне сховище — каталог, доступний лише додатку, для внутрішніх файлів та кешу. Спільне сховище — медіафайли через MediaStore (Android) або Files App (iOS). Хмарне сховище — iCloud Drive та Google Drive для синхронізації між пристроями. Кожен тип має свої обмеження за розміром, часом життя файлів та умовами доступу.
| Тип сховища | iOS | Android |
|---|---|---|
| Приватне | Documents, Library, Caches | getFilesDir(), getCacheDir() |
| Спільні медіа | PHPhotoLibrary через пікер | MediaStore API (ContentResolver) |
| Спільні документи | Files App через UIDocumentPicker | Storage Access Framework (SAF) |
| Хмарне | iCloud Drive (UIDocument) | Google Drive API |
| Кеш | Каталог Caches, очищається системою | getCacheDir(), getExternalCacheDir() |
Sandbox — архітектура безпеки iOS, що ізолює кожен додаток. Додаток може читати та писати лише всередині своєї пісочниці. Для доступу до контактів, фотографій чи файлів інших додатків необхідно використовувати системні пікери: UIImagePickerController або UIDocumentPickerViewController. Доступ до Files App налаштовується через прапорець UIFileSharingEnabled у Info.plist. Файлова система в мобільній розробці на iOS вимагає розуміння структури каталогів та правильного вибору місця для кожного типу даних.
Пісочниця iOS складається з кількох стандартних каталогів. Documents — для файлів користувача, включено до iCloud Backup. Caches — для тимчасових даних, які система може видалити при нестачі місця на пристрої. Temporary — для файлів поточної сесії, очищається при перезапуску. Application Support — для внутрішніх даних додатка, прихованих від користувача. Вибір неправильного каталогу призводить до проблем: збереження кешу в Documents надмірно витрачає місце в iCloud та порушує рекомендації Apple щодо роботи з файловою системою.
import Foundation
let fileManager = FileManager.default
guard let documentsURL = fileManager.urls(
for: .documentDirectory,
in: .userDomainMask
).first else { return }
let fileURL = documentsURL.appendingPathComponent("notes.txt")
let text = "Содержимое файла"
// Атомарний запис з шифруванням
try text.write(
to: fileURL,
atomically: true,
encoding: .utf8
)
Клас FileManager надає повний набір методів для керування файлами на iOS. FileManager.default — thread-safe синглтон, придатний для більшості операцій. Методи fileExists(atPath:), createDirectory(at:withIntermediateDirectories:attributes:), copyItem(at:to:) та removeItem(at:) покривають базові сценарії. Операції з файлами розміром понад 1 МБ рекомендується виконувати у фоновому потоці через DispatchQueue.global(). Для потокового читання великих обсягів використовуйте FileHandle замість завантаження всього файлу в пам'ять.
func readDocumentsFile(named fileName: String) -> String? {
guard let docsURL = FileManager.default.urls(
for: .documentDirectory,
in: .userDomainMask
).first else { return nil }
let fileURL = docsURL.appendingPathComponent(fileName)
return try? String(contentsOf: fileURL)
}
З виходом Android 10 Google ввів Scoped Storage — модель обмеженого доступу до файлової системи. Додаток може вільно читати та писати лише у свої приватні каталоги. Для доступу до медіафайлів (фото, відео, аудіо) використовується MediaStore API через ContentResolver. Для довільних документів — Storage Access Framework через Intent ACTION_OPEN_DOCUMENT. На Android 11+ прямий доступ до кореня зовнішнього сховища повністю заборонений, і всі розробники зобов'язані використовувати нові API.
MediaStore — системний ContentProvider для доступу до медіафайлів на пристрої. Через ContentResolver додаток запитує Uri файлів замість прямих шляхів. MediaStore.Files — для всіх типів файлів, Images — для зображень, Video — для відео, Audio — для аудіозаписів. Запис у спільні каталоги здійснюється через insert() із зазначенням DISPLAY_NAME, MIME_TYPE та RELATIVE_PATH. Після вставки додаток отримує Uri, через який виконується запис байтів. MIME-типи відіграють ключову роль — невірний тип призведе до помилки при відкритті файлу.
val contentValues = ContentValues().apply {
put(MediaStore.MediaColumns.DISPLAY_NAME, "report.pdf")
put(MediaStore.MediaColumns.MIME_TYPE, "application/pdf")
put(MediaStore.MediaColumns.RELATIVE_PATH, "Documents/Reports")
}
val uri = contentResolver.insert(
MediaStore.Files.getContentUri("external"),
contentValues
)
uri?.let {
contentResolver.openOutputStream(it)?.use { stream ->
stream.write(pdfBytes)
}
}
SAF надає єдиний інтерфейс для вибору та створення файлів без runtime-дозволів. Intent ACTION_OPEN_DOCUMENT відкриває системний файловий менеджер Android. Після вибору додаток отримує content:// Uri з тимчасовим доступом через FLAG_GRANT_READ_URI_PERMISSION. ACTION_CREATE_DOCUMENT дозволяє зберігати файли в будь-яке місце зовнішнього сховища за вибором користувача. SAF працює на Android 5+ та дає доступ до файлів із хмарних провайдерів, підключених через DocumentsProvider.
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
addCategory(Intent.CATEGORY_OPENABLE)
type = "*/*"
putExtra(Intent.EXTRA_MIME_TYPES, arrayOf(
"application/pdf",
"text/plain"
))
}
startActivityForResult(intent, REQUEST_CODE)
Обидві платформи надають вбудовані механізми для вибору файлів користувачем. Документи в мобільних додатках передаються через системні пікери, які надають тимчасовий доступ до файлу без постійних дозволів. На iOS це UIDocumentPickerViewController, на Android — ACTION_OPEN_DOCUMENT. Документи в мобільних додатках можна вибирати як із локального сховища, так і з хмарних сервісів. Користувач явно вказує файл, додаток отримує Uri або URL з обмеженим терміном дії.
UIDocumentPickerViewController відкриває Files App та дозволяє вибрати один або кілька документів. Режими: import (копіювання в пісочницю) та open (доступ за security-scoped URL). Для фільтрації файлів передається масив типів UTType — наприклад, .pdf та .plainText. Після отримання URL додаток повинен викликати startAccessingSecurityScopedResource() до читання та stopAccessingSecurityScopedResource() після завершення. Невиклик stopAccessing призводить до витоку системних ресурсів. Документи в мобільних додатках на iOS вимагають обов'язкового звільнення тимчасових дозволів після завершення роботи з файлом.
let picker = UIDocumentPickerViewController(
forOpeningContentTypes: [.pdf, .plainText]
)
picker.allowsMultipleSelection = true
picker.delegate = self
present(picker, animated: true)
// У делегаті звільняємо доступ
func documentPicker(
_ controller: UIDocumentPickerViewController,
didPickDocumentsAt urls: [URL]
) {
guard let url = urls.first else { return }
url.startAccessingSecurityScopedResource()
defer { url.stopAccessingSecurityScopedResource() }
}
FileProvider — підклас ContentProvider для безпечної передачі файлів між додатками. Він генерує тимчасові content:// Uri на основі файлів із вказаних XML-каталогів. Інші додатки отримують доступ через Intent із FLAG_GRANT_READ_URI_PERMISSION. DocumentProvider, на відміну від FileProvider, публікує файли в SAF та дозволяє іншим додаткам переглядати вміст вашого додатка як частину файлової системи. Для реалізації DocumentsProvider потрібно перевизначити queryRoots(), queryChildDocuments() та openDocument(), потім зареєструвати в AndroidManifest.xml
Хмарна синхронізація дає користувачеві доступ до документів на всіх пристроях. Файлова система в мобільних додатках доповнюється хмарним шаром: UIDocument на iOS автоматично відстежує зміни та синхронізує їх через iCloud. На Android аналогічна функціональність будується через Google Drive API або DocumentsProvider із хмарними коренями. Розуміння файлової системи в мобільній розробці критичне для побудови надійної синхронізації між пристроями.
UIDocument — абстрактний клас для роботи з документами iCloud. Він автоматично зберігає зміни, читає дані та повідомляє делегата про оновлення. При конфлікті запису NSFileVersion надає список доступних версій — розробник може вибрати останню або показати користувачеві варіанти вирішення конфлікту. Налаштування Ubiquity Container у Capabilities проєкту обов'язкове для роботи з iCloud Drive. NSFileCoordinator та NSFilePresenter запобігають гонкам даних при одночасному доступі з кількох потоків або пристроїв.
iOS автоматично включає Documents Directory у iCloud Backup. На Android працює Auto Backup for Apps — система зберігає дані з getFilesDir(), SharedPreferences та SQLite-баз у Google Drive. Кеш та зовнішні файли в бекап не включаються. Обидві платформи дозволяють налаштовувати винятки: на iOS через NSURLIsExcludedFromBackupKey, на Android через XML-конфігурацію правил бекапу. Шифрування файлів з персональними даними обов'язкове — на iOS використовуйте NSDataWritingFileProtectionComplete, на Android — EncryptedFile з бібліотеки security-crypto.
| Параметр | iOS | Android |
|---|---|---|
| Бекап за замовчуванням | Documents та Library | getFilesDir(), SharedPreferences, БД |
| Виняток файлів | isExcludedFromBackupKey | XML правила бекапу (fullBackupContent) |
| Шифрування | NSDataWritingFileProtectionComplete | EncryptedFile (security-crypto) |
| Хмарна синхронізація | UIDocument + iCloud | Google Drive API + SAF |
| Auto Restore | iCloud Restore після встановлення | Auto Backup при повторному встановленні |
Поширені запитання
Sandbox — ізольоване середовище кожного додатка на iOS. Додаток не має доступу до файлів інших додатків без використання системних пікерів, таких як UIDocumentPickerViewController.
Scoped Storage — модель обмеженого доступу до файлової системи на Android 10+. Додаток безпосередньо читає лише свої файли, для медіа використовує MediaStore API, для документів — Storage Access Framework.
Використовуйте UIDocumentPickerViewController — системний пікер для вибору документів із Files App або iCloud Drive. Після вибору отримаєте security-scoped URL з тимчасовим доступом.
Для медіафайлів використовуйте MediaStore API через ContentResolver із зазначенням MIME-типу. Для довільних документів — Storage Access Framework з Intent ACTION_OPEN_DOCUMENT.
FileProvider — підклас ContentProvider для безпечної передачі файлів між додатками через тимчасові content:// Uri з прапорцем FLAG_GRANT_READ_URI_PERMISSION.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.