ذخیرهسازی خارجی در دستگاههای موبایل یک رسانه داده قابل جابجایی است که هر برنامهای با مجوزهای مناسب میتواند به آن دسترسی پیدا کند. بر اساس Android Open Source Project, 2026, از Android 10 به بعد Google Scoped Storage را معرفی کرد — مدلی که دسترسی مستقیم به سیستم فایل را محدود میکند و نیاز به استفاده از MediaStore API برای کار با فایلهای رسانهای مشترک دارد. این رویکرد امنیت دادههای کاربر را افزایش میدهد و از نشت اطلاعات بین برنامهها جلوگیری میکند.
نکات اصلی
READ_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE برای Android 9 و پایینتر الزامی هستندذخیرهسازی خارجی — ناحیهای از حافظه است که در Sandbox محافظت شده برنامه قرار ندارد و برای سایر برنامهها قابل دسترسی است. در Android این اصطلاح معمولاً به SD-card اشاره دارد، اما ذخیرهسازی خارجی همچنین شامل USB-driveهای متصل از طریق OTG-adapter و دیسکهای ابری یکپارچه شده در سطح سیستم فایل میشود.
در Android ذخیرهسازی خارجی با دو حالت اصلی: قابل حمل (portable) و داخلی (adoptable). هنگام فرمتبندی SD-card به عنوان ذخیرهسازی قابل حمل، قابل جابجایی باقی میماند و با FAT32 یا exFAT فرمت میشود. در حالت adoptable storage کارت با ext4 فرمت شده و با AES-128 رمزگذاری میشود، پس از آن سیستم آن را به عنوان گسترش حافظه داخلی میبیند. حالت adoptable از Android 6.0 Marshmallow در دسترس است، اما تولیدکنندگان دستگاهها اغلب این امکان را در سیستمعامل خود غیرفعال میکنند. طبق آمار Google Play Console، تنها حدود 12% از دستگاههای Android از adoptable storage پشتیبانی میکنند، بنابراین توصیه نمیشود برای گسترش حافظه داخلی از طریق SD-card به عنوان تنها گزینه تکیه کنید.
در iOS SD-card سنتی وجود ندارد. Apple از معماری بسته استفاده میکند که در آن تمام ذخیرهسازی بر روی حافظه فلش داخلی و iCloud ساخته شده است. درایوهای خارجی از طریق پورت Lightning یا USB-C پشتیبانی میشوند، اما دسترسی به آنها به مدیر فایل سیستمی Files و برنامههایی که با Document Picker یکپارچه شدهاند محدود است. کاربر خود تصمیم میگیرد کدام فایلها را از منبع خارجی باز کند — برنامه نمیتواند درایو متصل را بدون رضایت صریح اسکن کند.
انتخاب رسانه خارجی به الزامات سرعت، ظرفیت و قابلیت حمل بستگی دارد. انواع مختلف رسانه ویژگیهای سرعتی، سیستمهای فایل و سناریوهای استفاده متفاوتی در برنامههای موبایل دارند.
| نوع رسانه | حداکثر ظرفیت | سرعت خواندن | سیستم فایل |
|---|---|---|---|
| SD UHS-I | ۲ ترابایت | تا ۱۰۴ مگابایت/ثانیه | exFAT / FAT32 |
| SD UHS-II | ۲ ترابایت | تا ۳۱۲ مگابایت/ثانیه | exFAT / FAT32 |
| USB 3.0 OTG | ۲ ترابایت | تا ۴۰۰ مگابایت/ثانیه | exFAT / NTFS / FAT32 |
| USB-C SSD | ۴ ترابایت | تا ۱۰۰۰ مگابایت/ثانیه | exFAT / APFS / NTFS |
SD-cardها بر اساس سرعت نوشتن طبقهبندی میشوند: Class 10 (۱۰ مگابایت/ثانیه)، U1 (۱۰ مگابایت/ثانیه)، U3 (۳۰ مگابایت/ثانیه)، V30 (۳۰ مگابایت/ثانیه) و V90 (۹۰ مگابایت/ثانیه). برای ضبط ویدئوی 4K به کارتی حداقل U3 یا V30 نیاز است. برای برنامههای موبایل که با فایلهای رسانهای بزرگ کار میکنند (پردازش عکس، ویرایش ویدئو)، توصیه میشود از کارتهای کلاس U3 و بالاتر استفاده کنید. سرعت کارت به طور مستقیم بر عملکرد برنامه تأثیر میگذارد: ضبط ویدئوی 4K روی کارت Class 10 ممکن است به دلیل پهنای باند ناکافی باعث افت فریم شود. هنگام انتخاب SD-card برای برنامه، نه تنها به کلاس سرعت، بلکه به رتبه Application Performance Class نیز توجه کنید: A1 و A2 حداقل عملکرد خواندن و نوشتن تصادفی را نشان میدهند که برای کار پایگاههای داده و حافظه نهان برنامهها حیاتی است.
USB-OTG (On-The-Go) امکان اتصال USB-driveهای خارجی به دستگاه موبایل از طریق آداپتور را فراهم میکند. Android از OTG از نسخه 3.1 پشتیبانی میکند، اما برای mount کردن درایو به هستهای با پشتیبانی از سیستم فایل نیاز است. FAT32 و exFAT به صورت پیشفرض پشتیبانی میشوند، NTFS — فقط در دستگاههای دارای هسته سفارشی یا از طریق کتابخانه Paragon. در iOS پشتیبانی از USB-driveها از iOS 13 به همراه برنامه Files اضافه شد. برای کار با درایو، برنامه باید از UIDocumentPickerViewController استفاده کند که دسترسی فقط به فایلهای انتخاب شده توسط کاربر را باز میکند — iOS دسترسی کامل به سیستم فایل درایو را فراهم نمیکند.
سرویسهای ابری — iCloud, Google Drive، Dropbox — میتوانند از طریق ارائهدهندگان سیستمی در سیستم فایل دستگاه یکپارچه شوند. در iOS iCloud Drive بخشی از Sandbox-container برنامه است و فایلها به طور خودکار بین دستگاههای کاربر همگامسازی میشوند. در Android Google Drive API برای خواندن و نوشتن فایلها ارائه میدهد، اما mount مستقیم در سیستم فایل انجام نمیشود. برای برنامههای موبایل که با حجم زیادی از داده کار میکنند، ذخیرهسازی ابری میتواند جایگزینی برای SD-card باشد، به ویژه در دستگاههای بدون اسلات توسعه.
کار با ذخیرهسازی خارجی در Android به نسخه سیستم عامل و مدل Scoped Storage بستگی دارد. فرآیند دسترسی به فایلها برای Android 9 و پایینتر، Android 10–12 و Android 13+ متفاوت است.
از Android 10, روش اصلی دسترسی به فایلهای رسانهای مشترک MediaStore API است. این API یک رابط یکپارچه برای خواندن و نوشتن تصاویر، ویدئوها و فایلهای صوتی در حافظه مشترک فراهم میکند. برنامه برای دسترسی به فایلهای خود به مجوز READ_EXTERNAL_STORAGE برای دسترسی به فایلهای خود نیاز ندارد، اما برای خواندن فایلهای سایر برنامهها همچنان به مجوز صریح کاربر نیاز است. MediaStore به طور خودکار فایلهای رسانهای را ایندکس میکند و ContentResolver برای جستجوی آنها ارائه میدهد.
val collection = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
} else {
MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
val projection = arrayOf(
MediaStore.Images.Media._ID,
MediaStore.Images.Media.DISPLAY_NAME
)
val cursor = contentResolver.query(collection, projection, null, null, null)
پس از اجرای درخواست، یک Cursor حاوی URI فایلها دریافت میکنید. برای خواندن فایل InputStream را از طریق contentResolver.openInputStream(uri). نوشتن به طور مشابه از طریق contentResolver.openOutputStream(uri). MediaStore به طور خودکار تضاد نامها را مدیریت میکند و امکان درج فایلهای جدید را از طریق contentResolver.insert(uri, values), که URI فایل ایجاد شده را برمیگرداند.
Storage Access Framework (SAF) — روش توصیه شده برای دسترسی به فایلهای دلخواه در Android 10+ است. SAF یک دیالوگ سیستمی انتخاب فایل ارائه میدهد که از طریق آن کاربر به برنامه دسترسی به یک فایل یا پوشه خاص میدهد. برنامه یک URI دسترسی دریافت میکند که تا راهاندازی مجدد دستگاه یا لغو صریح مجوز از طریق تنظیمات معتبر است. SAF به مجوزهای READ_EXTERNAL_STORAGE یا WRITE_EXTERNAL_STORAGE, که انتشار در Google Play را سادهتر کرده و تعداد درخواستهای مجوز را کاهش میدهد.
val requestCode = 42
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
intent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
)
startActivityForResult(intent, requestCode)
در iOS کار با فایلهای خارجی از طریق UIDocumentPickerViewController انجام میشود که کاربر برای انتخاب فایلها یا پوشههای خاص باز میکند. برنامه دسترسی مستقیم به سیستم فایل درایو خارجی ندارد — فقط به فایلهایی که کاربر صریحاً انتخاب کرده است. پس از انتخاب فایل، برنامه یک URL موقت در Sandbox-container دریافت میکند و میتواند از طریق FileManager با فایل کار کند.
UIDocumentPickerViewController به کاربر امکان انتخاب یک یا چند فایل از هر منبع در دسترس را میدهد: iCloud Drive، USB-drive متصل، سرویس ابری شخص ثالث. پس از انتخاب، کنترلکننده آرایهای از URLها را برمیگرداند که برنامه میتواند در طول جلسه آنها را بخواند. برای حفظ دسترسی پس از بستن برنامه، باید startAccessingSecurityScopedResource() فراخوانی شود و bookmark امن در UserDefaults ذخیره شود.
let picker = UIDocumentPickerViewController(
forOpeningContentTypes: [.data, .image],
asCopy: true
)
picker.delegate = self
func documentPicker(
controller: UIDocumentPickerViewController,
didPickDocumentsAt urls: [URL]
) {
guard let url = urls.first else { return }
let data = try Data(contentsOf: url)
}
پارامتر asCopy: true به این معنی است که iOS فایل را در Sandbox-container برنامه کپی میکند و برنامه یک کپی مستقل از فایل اصلی دریافت میکند. اگر asCopy: false مشخص شود، برنامه یک مرجع به فایل اصلی دریافت میکند، اما برای دسترسی به آن باید url.startAccessingSecurityScopedResource(). بدون این فراخوانی، خواندن فایل باعث ایجاد استثنا میشود. پس از اتمام کار با فایل، حتماً url.stopAccessingSecurityScopedResource(), تا منبع بسته شده و از نشت توصیفگرها جلوگیری شود.
امنیت ذخیرهسازی خارجی کمتر از Internal Storage است زیرا فایلها برای سایر برنامهها قابل دسترسی هستند. هر برنامهای با مجوز READ_EXTERNAL_STORAGE میتواند تمام فایلهای SD-card را بخواند، از جمله فایلهایی که برنامه شما برای ذخیره موقت دادههای محرمانه ایجاد کرده است. یک برنامه مخرب میتواند SD-card را اسکن کرده و دادههای کاربر را استخراج کند، اگر رمزگذاری نشده باشند. بنابراین به شدت توصیه نمیشود توکنهای احراز هویت، رمزهای عبور یا دادههای شخصی کاربر را در ذخیرهسازی خارجی به صورت آشکار ذخیره کنید.
در Android 10+ Scoped Storage دسترسی برنامهها به سیستم فایل مشترک را به میزان قابل توجهی محدود میکند. برنامه بدون مجوز میتواند فقط فایلهایی را که خود ایجاد کرده است بخواند و برای دسترسی به فایلهای سایر برنامهها به رضایت صریح کاربر از طریق دیالوگ SAF نیاز است. با این حال، این محدودیت برای برنامههایی با target SDK version زیر 29 اعمال نمیشود — آنها به کار با مدل قدیمی ادامه میدهند که خطری برای کاربرانی که برنامههای خود را بهروز نکردهاند ایجاد میکند. Google Play از سال 2021 برای همه برنامههای جدید و بهروز شده targetSdkVersion 29+ را الزامی کرده است.
فرمتبندی و رمزگذاری — جنبه مهم دیگر امنیت است. SD-card فرمت شده به عنوان ذخیرهسازی قابل حمل به طور پیشفرض توسط سیستم رمزگذاری نمیشود. حتی هنگام استفاده از adoptable storage، رمزگذاری فقط در صورتی فعال میشود که تولیدکننده دستگاه این امکان را در سیستمعامل فعال کرده باشد. برای محافظت از دادههای محرمانه ذخیره شده در ذخیرهسازی خارجی، از کتابخانه EncryptedFile از AndroidX Security استفاده کنید که هر فایل را جداگانه با AES256-GCM رمزگذاری میکند، صرف نظر از رمزگذاری سیستمی.
استفاده مؤثر از ذخیرهسازی خارجی نیاز به تعادل بین در دسترس بودن دادهها و امنیت دارد. برای اطمینان از ذخیرهسازی مطمئن فایلهای کاربر قوانین زیر را رعایت کنید.
Environment.getExternalStorageState() برای بررسی وضعیت SD-card استفاده کنید. کارت ممکن است خارج شده، آسیب دیده یا برای نوشتن در دسترس نباشدمهم است به خاطر داشته باشید که ذخیرهسازی خارجی حفظ دادهها را در هنگام خرابی تضمین نمیکند. SD-cardها منابع محدودی از چرخههای بازنویسی دارند، به ویژه مدلهای اقتصادی کلاس Class 4 و Class 6. در نوشتن فشرده (به عنوان مثال، logging یا ذخیرهسازی جریان داده)، کارت ممکن است ظرف چند ماه از کار بیفتد. برای چنین سناریوهایی از حافظه داخلی یا ذخیرهسازی ابری استفاده کنید و در ذخیرهسازی خارجی فقط فایلهایی را ذخیره کنید که کاربر از دست دادن آنها را قابل قبول بداند. StatFs و در مورد خطاهای بحرانی سیستم فایل به کاربر اطلاع دهید.
سؤالات متداول
در Android 13+ مجوز READ_EXTERNAL_STORAGE با مجوزهای دقیقتری جایگزین شده است: READ_MEDIA_IMAGES, READ_MEDIA_VIDEO و READ_MEDIA_AUDIO. برای دسترسی به انواع دیگر فایلها از SAF استفاده کنید.
بله، قابلیت adoptable storage در Android 6.0+ در دسترس است. کارت با ext4 فرمت شده و با AES-128 رمزگذاری میشود. با این حال، بسیاری از تولیدکنندگان این گزینه را غیرفعال میکنند و حدود 88% دستگاهها از adoptable storage پشتیبانی نمیکنند.
از روش Environment.getExternalStorageState(), استفاده کنید که یک رشته وضعیت برمیگرداند. مقدار MEDIA_MOUNTED به این معنی است که کارت برای خواندن و نوشتن در دسترس است. سایر مقادیر نشاندهنده خطا یا عدم وجود کارت هستند.
Scoped Storage برنامه را به ظرف مخصوص خود و MediaStore مشترک محدود میکند. دسترسی کامل خواندن هر فایلی را در دستگاه مجاز میکند. دادههای کاربر را افزایش میدهد و برای برنامههای جدید الزامی است.
یک Intent با action ACTION_OPEN_DOCUMENT_TREE راهاندازی کنید که یک دیالوگ سیستمی انتخاب پوشه را باز میکند. پس از انتخاب، یک URI-مجوز دریافت میکنید که تا راهاندازی مجدد معتبر است. این URI را در SharedPreferences برای استفاده بعدی ذخیره کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید