کار با سیستم فایل، پایه و اساس هر برنامه موبایل است. هر پلتفرم مدل دسترسی خود را ارائه میدهد: 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 استفاده میکند، که در آن هر برنامه در کانتینر خود با مجوزهای کاملاً محدود وجود دارد. قبل از نسخه 10، Android دسترسی کامل به فضای ذخیرهسازی خارجی فراهم میکرد، اما با معرفی 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 یک singleton ایمن برای نخ است که برای اکثر عملیات مناسب است. روشهایی مانند fileExists(atPath:)، createDirectory(at:withIntermediateDirectories:attributes:)، copyItem(at:to:) و removeItem(at:) سناریوهای اساسی را پوشش میدهند. عملیات فایل بزرگتر از 1 MB باید در یک نخ پسزمینه از طریق 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 یک رابط یکپارچه برای انتخاب و ایجاد فایلها بدون مجوزهای زمان اجرا فراهم میکند. Intent ACTION_OPEN_DOCUMENT مدیر فایل سیستمی را در Android باز میکند. پس از انتخاب، برنامه یک Uri از نوع content:// با دسترسی موقت از طریق 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 (کپی به جعبه شنی) و باز کردن (دسترسی از طریق 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 برای اشتراکگذاری امن فایلها بین برنامهها است. این Uriهای موقت content:// بر اساس فایلهای دایرکتوریهای 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 در قابلیتهای پروژه برای iCloud Drive الزامی است. NSFileCoordinator و NSFilePresenter از رقابت دادهها در هنگام دسترسی همزمان از چندین نخ یا دستگاه جلوگیری میکنند.
iOS به طور خودکار دایرکتوری Documents را در 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, DB |
| استثنای فایل | isExcludedFromBackupKey | قوانین XML پشتیبانگیری (fullBackupContent) |
| رمزگذاری | NSDataWritingFileProtectionComplete | EncryptedFile (security-crypto) |
| همگامسازی ابری | UIDocument + iCloud | Google Drive API + SAF |
| بازیابی خودکار | بازیابی iCloud پس از نصب | پشتیبانگیری خودکار در نصب مجدد |
سوالات متداول
Sandbox یک محیط ایزوله برای هر برنامه در iOS است. برنامه بدون استفاده از انتخابگرهای سیستمی مانند UIDocumentPickerViewController نمیتواند به فایلهای برنامههای دیگر دسترسی پیدا کند.
Scoped Storage یک مدل دسترسی محدود به سیستم فایل در Android 10+ است. برنامه فقط فایلهای خود را مستقیماً میخواند، برای رسانه از MediaStore API و برای اسناد از Storage Access Framework استفاده میکند.
از UIDocumentPickerViewController — انتخابگر سیستمی برای انتخاب اسناد از Files App یا iCloud Drive استفاده کنید. پس از انتخاب، یک URL با دامنه امنیتی و دسترسی موقت دریافت میکنید.
برای فایلهای رسانه، از MediaStore API از طریق ContentResolver با مشخص کردن نوع MIME استفاده کنید. برای اسناد دلخواه، از Storage Access Framework با Intent ACTION_OPEN_DOCUMENT استفاده کنید.
FileProvider زیرکلاسی از ContentProvider برای اشتراکگذاری امن فایلها بین برنامهها از طریق Uri موقت content:// با FLAG_GRANT_READ_URI_PERMISSION است.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.