Работа с файловой системой — основа любого мобильного приложения. Каждая платформа предлагает свою модель доступа: 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 Directory, очищается системой | 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-конфигурацию backup rules. Шифрование файлов с персональными данными обязательно — на iOS используйте NSDataWritingFileProtectionComplete, на Android — EncryptedFile из библиотеки security-crypto.
| Параметр | iOS | Android |
|---|---|---|
| Бэкап по умолчанию | Documents и Library | getFilesDir(), SharedPreferences, БД |
| Исключение файлов | isExcludedFromBackupKey | XML backup rules (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 года. Мы проконсультируем вас и предложим наилучшее решение.