حافظه داخلی برنامه فضایی اختصاصی در دستگاه است که فقط از طریق ذخیرهسازی ایزوله در دسترس برنامه خاصی قرار میگیرد. به گفته Android Developers، 2026، هر برنامه یک دایرکتوری sandbox مخصوص به خود دریافت میکند که سایر برنامهها به آن دسترسی مستقیم ندارند. چنین رویکردی از دادهها در برابر خواندن غیرمجاز محافظت میکند و عملکرد پایدار را در محیط چندوظیفهای دستگاههای موبایل تضمین مینماید.
نکات اصلی
Context.getFilesDir()، getCacheDir() و getDataDir() را برای دسترسی به حافظه داخلی فراهم میکندNSDocumentDirectory و NSCachesDirectory در کانتینر Sandbox برنامه استفاده میکندحافظه داخلی برنامه یک دایرکتوری ایزوله است که سیستم عامل هنگام نصب به هر برنامه اختصاص میدهد. سایر برنامهها و کاربر از طریق مدیران فایل استاندارد به این دایرکتوری دسترسی ندارند. سیستم تضمین میکند که دادههای داخل این دایرکتوری هنگام حذف برنامه به طور کامل پاک میشوند. این رویکرد اساس مدل امنیتی سیستمهای عامل موبایل را تشکیل میدهد و از نشت اطلاعات محرمانه بین برنامهها جلوگیری میکند.
برخلاف حافظه خارجی (کارت SD)، حافظه داخلی همیشه در دسترس است و نیازی به بررسی وجود حامل ندارد. سرعت خواندن و نوشتن در حافظه NAND فلش دستگاههای مدرن به 800 تا 900 مگابایت بر ثانیه برای خواندن ترتیبی و 200 تا 300 مگابایت بر ثانیه برای نوشتن ترتیبی میرسد که با SATA SSD قابل مقایسه است. اندازه فضای اختصاص یافته به حجم کلی دستگاه و سیاست تولیدکننده بستگی دارد: در دستگاههای با 64 گیگابایت حافظه فلش، برنامه از 16 تا 64 مگابایت فضای اولیه با امکان افزایش در صورت نیاز دریافت میکند.
معماری ذخیرهسازی داخلی در Android و iOS متفاوت است. در Android هر برنامه یک دایرکتوری /data/data/<package_name>/ دریافت میکند که سیستم زیرشاخههای files/، cache/ و databases/ را در داخل آن ایجاد میکند. در iOS برنامه در یک کانتینر Sandbox با دایرکتوریهای Documents/، Library/ و tmp/ کار میکند که هر کدام کاربرد و سیاست پشتیبانگیری خاص خود را دارند.
توسعهدهندگان به چندین روش برای ذخیره دادهها در حافظه داخلی برنامه دسترسی دارند. هر روش وظیفه خاص خود را حل میکند و برای نوع خاصی از دادهها مناسب است. انتخاب روش صحیح به طور مستقیم بر عملکرد برنامه، راحتی توسعه و امنیت دادههای کاربر تأثیر میگذارد.
پایینترین سطح روش — نوشتن مستقیم فایلها در دایرکتوری files. برنامه میتواند هر فایل و دایرکتوری را در داخل sandbox خود ایجاد کند. این روش برای ذخیره فایلهای رسانهای، اسناد کاربر و هر داده باینری که نیاز به سازماندهی ساختاریافته ندارد مناسب است. در Android دسترسی به دایرکتوری از طریق فراخوانی Context.getFilesDir() انجام میشود که مسیر مطلق دایرکتوری فایلهای برنامه را برمیگرداند. در iOS عملکرد مشابه توسط NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) انجام میشود.
برای ذخیره جفتهای کلید-مقدار، Android SharedPreferences و DataStore مدرنتر مبتنی بر کوروتینهای Kotlin و پروتکل protobuf را ارائه میدهد. SharedPreferences دادهها را در فایل XML در داخل دایرکتوری /data/data/<package>/shared_prefs/ ذخیره میکند. با وجود سادگی استفاده، SharedPreferences معایبی دارد: نوشتن همزمان ممکن است باعث تأخیر در رشته UI شود و عدم امنیت نوع خطر خطاها را افزایش میدهد. DataStore این مشکلات را با ارائه API ناهمزمان مبتنی بر Flow و پشتیبانی کامل از انواع از طریق طرحهای protobuf حل میکند.
برای دادههای ساختاریافته با روابط رابطهای انتخاب بهینه SQLite یا پوشش Room است. پایگاه داده در یک فایل واحد در داخل دایرکتوری databases/ ذخیره میشود و از نحو کامل SQL پشتیبانی میکند. Room یک کتابخانه رسمی Jetpack است که API امن از نظر نوع، مهاجرت خودکار طرح و پشتیبانی از کوروتینها را فراهم میکند. اندازه پایگاه داده میتواند بدون افت عملکرد قابل توجه با نمایهسازی صحیح به چندین گیگابایت برسد. SQLite در دستگاههای موبایل تا 50,000 عملیات نوشتن در ثانیه بر روی پردازندههای پرچمدار مدرن پردازش میکند.
برای ذخیره دادههای محرمانه مانند توکنهای احراز هویت و کلیدهای رمزنگاری، Android EncryptedSharedPreferences را ارائه میدهد. این پوشش بر روی SharedPreferences استاندارد به طور خودکار کلیدها و مقادیر را با استفاده از AES256-GCM-None رمزنگاری میکند. رمزنگاری در سطح فایل قبل از نوشتن روی دیسک انجام میشود، بنابراین حتی با دسترسی فیزیکی به دستگاه، مهاجم نمیتواند محتوا را بخواند. EncryptedSharedPreferences بخشی از کتابخانه AndroidX Security است که همچنین EncryptedFile را برای رمزنگاری فایلهای کامل شامل میشود.
Android SDK مجموعهای از متدها را برای کار با حافظه داخلی از طریق کلاس Context فراهم میکند. هر متد مسیر یک دایرکتوری سیستمی خاص را در داخل sandbox برنامه برمیگرداند. بیایید عملیات پایه نوشتن و خواندن فایلها را با مثال Kotlin بررسی کنیم.
متد اصلی برای دریافت مسیر دایرکتوری فایل داخلی — context.filesDir. این متد یک شیء File را برمیگرداند که به دایرکتوری /data/data/<package>/files/ اشاره میکند. در اولین فراخوانی، سیستم تمام دایرکتوریهای والد لازم را به طور خودکار ایجاد میکند. اندازه فایلها در حافظه داخلی به طور صریح محدود نشده است، اما حجم کل دادهها نباید از فضای موجود پارتیشن /data تجاوز کند که معمولاً 60 تا 80 درصد از حجم کل حافظه فلش دستگاه را تشکیل میدهد.
val context = getApplicationContext()
val file = File(context.filesDir, "notes.txt")
file.writeText("محتوی یادداشت")
val content = file.readText()
println("خوانده شده: $content")
متدهای writeText و readText توابع extension کتابخانه استاندارد Kotlin هستند. آنها به طور خودکار باز و بسته شدن جریانها را مدیریت میکنند که از نشت حافظه جلوگیری میکند. برای کار با دادههای باینری از writeBytes و readBytes استفاده کنید که به رمزگذاری نیاز ندارند و با آرایههای ByteArray کار میکنند. هنگام کار با فایلهای بزرگ توصیه میشود از جریانهای بافر شده استفاده کنید: BufferedReader و BufferedWriter برای متن، BufferedInputStream و BufferedOutputStream برای دادههای باینری.
برای سازماندهی فایلها به صورت سلسلهمراتبی زیرشاخههایی ایجاد کنید در داخل filesDir. این کار به ساختاربندی دادهها بر اساس نوع کمک میکند: تصاویر، اسناد، فایلهای صادراتی. متد mkdirs() تمام دایرکتوریهای موجود در مسیر را از جمله زیرشاخهها ایجاد میکند. مطمئن شوید که عملیات ایجاد با موفقیت انجام شده است — متد فقط در صورت ایجاد دایرکتوریهای جدید true برمیگرداند. خطای ایجاد اغلب به دلیل کمبود فضای پارتیشن /data یا اتمام ایندودهای سیستم فایل رخ میدهد.
val imagesDir = File(context.filesDir, "images")
if (imagesDir.mkdirs()) {
println("دایرکتوری ایجاد شد")
}
val imageFile = File(imagesDir, "photo.jpg")
imageFile.writeBytes(byteArray)
برای بررسی فضای موجود قبل از نوشتن فایلهای بزرگ از File.getFreeSpace() یا File.getUsableSpace() استفاده کنید. متد دوم تعداد بایتهای قابل دسترس برای برنامه فعلی را با در نظر گرفتن سهمیههای امنیتی برمیگرداند — در زمینه دستگاههای چندکاربره دقیقتر است. اگر فضای موجود از اندازه مورد انتظار فایل کمتر است، پیامی به کاربر نشان داده و پیشنهاد آزادسازی فضا در تنظیمات دستگاه را بدهید.
در iOS هر برنامه در یک کانتینر Sandbox ایزوله کار میکند. سیستم API برای خروج از محدوده آن بدون entitlements خاص ارائه نمیدهد. ابزار اصلی برای کار با سیستم فایل کلاس FileManager از فریمورک Foundation است. کانتینر Sandbox شامل چندین دایرکتوری استاندارد است که هر کدام سیاست پشتیبانگیری خاص خود را دارند.
دایرکتوری Documents برای دادههای کاربر در نظر گرفته شده است که باید بین راهاندازیهای برنامه حفظ شده و از پشتیبان بازیابی شوند. iOS به طور خودکار این دایرکتوری را در پشتیبانگیری iCloud و iTunes قرار میدهد. متد urls(for:in:) آرایهای از آدرسهای URL دایرکتوری درخواست شده را برمیگرداند — اولین عنصر آرایه اصلی است.
let fm = FileManager.default
let docs = fm.urls(
for: .documentDirectory,
in: .userDomainMask
).first!
let fileURL = docs.appendingPathComponent("data.plist")
try data.write(to: fileURL)
FileManager از مجموعه کاملی از عملیات فایل پشتیبانی میکند: ایجاد، کپی، جابجایی، حذف و تغییر نام فایلها. هر عملیات ممکن است خطا ایجاد کند، بنابراین همه فراخوانیها باید در ساختار do-catch قرار گیرند. به حذف فایلها توجه ویژه داشته باشید — عملیات غیرقابل برگشت است و بازیابی دادهها پس از removeItem(at:) بدون پشتیبان قبلی غیرممکن است.
همه دادههای کانتینر Sandbox نباید وارد پشتیبان iCloud شوند. برای مثال، کش تصاویر بارگیری شده یا فایلهای موقت پردازش نیازی به بازیابی ندارند — آنها در استفاده بعدی دوباره ایجاد میشوند. برای حذف یک دایرکتوری یا فایل از پشتیبانگیری، ویژگی isExcludedFromBackup را روی true تنظیم کنید. Apple توصیه میکند همیشه دادههایی که میتوان از راه دور بازیابی کرد را از پشتیبان حذف کنید تا حجم ذخیرهسازی iCloud به حداقل برسد و زمان بازیابی کاهش یابد.
var cacheURL = fm.urls(
for: .cachesDirectory,
in: .userDomainMask
).first!
cacheURL.hasExcludedFromBackupKey = true
var values = URLResourceValues()
values.isExcludedFromBackup = true
try cacheURL.setResourceValues(values)
هر نوع ذخیرهسازی در دستگاه موبایل کاربرد و قوانین استفاده خاص خود را دارد. درک این تفاوتها به توسعهدهنده کمک میکند مکان مناسب را برای هر نوع داده انتخاب کند. در زیر مقایسه سه نوع اصلی ذخیرهسازی در دسترس برنامه آورده شده است.
| ویژگی | Internal Storage | Cache Directory | External Storage |
|---|---|---|---|
| قابلیت مشاهده برای سایر برنامهها | مخفی | مخفی | قابل دسترس |
| حذف هنگام حذف برنامه | کامل | کامل | بستگی به مکان دارد |
| پشتیبانگیری | در Android — خیر، در iOS — بله (Documents) | خیر | فقط با همگامسازی |
| دسترسی بدون حامل | همیشه | همیشه | نیاز به کارت SD دارد |
| ریسک از دست دادن داده | حداقل | بالا | متوسط |
| اندازه توصیه شده فایلها | تا 100 مگابایت | تا 50 مگابایت | هر اندازه |
حافظه داخلی برای ذخیره تنظیمات برنامه، فایلهای پایگاه داده و اسناد کاربر که نباید در دسترس سایر برنامهها باشد بهینه است. دایرکتوری کش برای فایلهای موقتی که میتوان در استفاده بعدی دوباره ایجاد کرد در نظر گرفته شده است: تصاویر بارگیری شده، پاسخهای API، دادههای میانی پردازش. حافظه خارجی برای فایلهای رسانهای بزرگ (عکس، ویدیو، موسیقی) و دادههایی که کاربر میخواهد با سایر برنامهها از طریق اشتراک عمومی به اشتراک بگذارد مناسب است.
انتخاب نوع ذخیرهسازی همچنین بر رتبه برنامه در Google Play و App Store تأثیر میگذارد. برنامههایی که حجم زیادی از دادهها را در حافظه داخلی بدون پاکسازی ذخیره میکنند نظرات منفی دریافت میکنند: کاربران از کمبود فضا شکایت دارند. طبق تحقیق App Annie، 62٪ از کاربران برنامه را حذف میکنند اگر بیش از 500 مگابایت از حافظه داخلی دستگاه را بدون گزینه پاکسازی اشغال کند.
مدیریت صحیح حافظه داخلی برنامه باعث افزایش عملکرد، امنیت و تجربه کاربری میشود. توصیههای زیر بر اساس مستندات رسمی Android و iOS و همچنین تجربه عملی توسعه برنامهها با میلیونها نصب است.
توجه ویژه باید به تست موارد مرزی شود. رفتار برنامه را هنگام پر شدن حافظه داخلی، قطع ناگهانی نوشتن (سقوط برنامه، تماس) و بازیابی از پشتیبان iOS بررسی کنید. در هر یک از این سناریوها دادهها باید سازگار بمانند یا به آخرین حالت پایدار بازیابی شوند. از فایلهای تراکنشی استفاده کنید: دادهها را در یک فایل موقت بنویسید و سپس به طور اتمی آن را به فایل هدف تغییر نام دهید. این کار از خواندن دادههای خراب در صورت خرابی نوشتن جلوگیری میکند.
کنترل کاربر را فراموش نکنید. در تنظیمات برنامه گزینه پاکسازی دادههای موقت و نمایش حجم اشغال شده حافظه داخلی را ارائه دهید. طبق Google Play Console، برنامههایی با چنین قابلیتی 18٪ نظرات مثبت بیشتری در دسته «عملکرد» دریافت میکنند.
سوالات متداول
تمام دادههای حافظه داخلی برنامه به طور کامل حذف میشوند. سیستم عامل عدم وجود فایلهای باقیمانده از جمله پایگاههای داده، تنظیمات و فایلهای موقت را تضمین میکند. دادههای موجود در حافظه خارجی ممکن است حفظ شوند.
بدون دسترسی root به دستگاه، سایر برنامهها نمیتوانند فایلهای Internal Storage برنامه دیگر را بخوانند. در Android برای این کار به امتیازات ابرکاربر نیاز است و در iOS ایزولهسازی در سطح هسته از طریق Sandbox تضمین میشود.
محدودیت صریحی وجود ندارد، اما حجم کل به فضای خالی پارتیشن /data محدود است. توصیه میشود از 100 مگابایت برای هر برنامه تجاوز نکنید — حجمهای بزرگتر بهتر است در حافظه خارجی یا ابر قرار گیرند.
filesDir برای دادههای دائمی برنامه در نظر گرفته شده است و بدون نیاز توسط سیستم حذف نمیشود. cacheDir برای فایلهای موقتی است که سیستم میتواند در صورت کمبود حافظه حذف کند. سیستم ماندگاری cacheDir را تضمین نمیکند.
کپی مستقیم از Internal Storage به کارت SD توسط سیاست امنیتی ممنوع است. از MediaStore API در Android 10+ یا SAF (Storage Access Framework) برای ایجاد کپی از دادهها در دسترسی عمومی با رضایت کاربر استفاده کنید.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید