Bộ nhớ trong của ứng dụng là không gian dành riêng trên thiết bị chỉ có thể truy cập được bởi một ứng dụng cụ thể thông qua bộ nhớ cách ly. Theo Android Developers, 2026, mỗi ứng dụng nhận được thư mục sandbox riêng mà các ứng dụng khác không thể truy cập trực tiếp. Cách tiếp cận này bảo vệ dữ liệu khỏi đọc trái phép và đảm bảo hoạt động ổn định trong môi trường đa nhiệm của thiết bị di động.
Những điểm chính
Context.getFilesDir(), getCacheDir() và getDataDir() để truy cập bộ nhớ trongNSDocumentDirectory và NSCachesDirectory trong vùng chứa Sandbox của ứng dụngBộ nhớ trong của ứng dụng là một thư mục cách ly mà hệ điều hành cấp cho mỗi ứng dụng trong quá trình cài đặt. Các ứng dụng khác và người dùng không thể truy cập thư mục này thông qua trình quản lý tệp tiêu chuẩn. Hệ thống đảm bảo rằng tất cả dữ liệu trong thư mục này sẽ bị xóa hoàn toàn khi gỡ cài đặt ứng dụng. Cách tiếp cận này tạo nên nền tảng của mô hình bảo mật hệ điều hành di động, ngăn chặn rò rỉ thông tin bảo mật giữa các chương trình.
Không giống như bộ nhớ ngoài (thẻ SD), bộ nhớ trong luôn khả dụng và không cần kiểm tra sự hiện diện của phương tiện. Tốc độ đọc và ghi trên bộ nhớ flash NAND của các thiết bị hiện đại đạt 800–900 MB/s đọc tuần tự và 200–300 MB/s ghi tuần tự, tương đương với SSD SATA. Kích thước vùng được cấp phát phụ thuộc vào tổng dung lượng thiết bị và chính sách nhà sản xuất: trên thiết bị có 64 GB bộ nhớ flash, ứng dụng nhận được 16 đến 64 MB không gian ban đầu với khả năng mở rộng khi cần.
Kiến trúc bộ nhớ trong khác nhau giữa Android và iOS. Trên Android, mỗi ứng dụng nhận được thư mục /data/data/<package_name>/, bên trong hệ thống tạo các thư mục con files/, cache/ và databases/. Trên iOS, ứng dụng hoạt động trong vùng chứa Sandbox với các thư mục Documents/, Library/ và tmp/, mỗi thư mục có mục đích và chính sách sao lưu riêng.
Các nhà phát triển có quyền truy cập vào một số phương pháp để lưu dữ liệu trong bộ nhớ trong của ứng dụng. Mỗi phương pháp giải quyết một tác vụ cụ thể và phù hợp với một loại dữ liệu nhất định. Chọn đúng phương pháp ảnh hưởng trực tiếp đến hiệu suất ứng dụng, sự thuận tiện trong phát triển và bảo mật dữ liệu người dùng.
Phương pháp cấp thấp nhất là ghi tệp trực tiếp vào thư mục tệp. Ứng dụng có thể tạo bất kỳ tệp và thư mục nào trong sandbox của mình. Phương pháp này phù hợp để lưu trữ tệp phương tiện, tài liệu người dùng và bất kỳ dữ liệu nhị phân nào không yêu cầu tổ chức có cấu trúc. Trên Android, quyền truy cập thư mục được thực hiện qua lệnh gọi Context.getFilesDir(), trả về đường dẫn tuyệt đối đến thư mục tệp của ứng dụng. Trên iOS, hàm NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) phục vụ mục đích tương tự.
Để lưu trữ cặp khóa-giá trị, Android cung cấp SharedPreferences và DataStore hiện đại hơn dựa trên coroutine Kotlin và giao thức protobuf. SharedPreferences lưu trữ dữ liệu trong tệp XML bên trong thư mục /data/data/<package>/shared_prefs/. Mặc dù dễ sử dụng, SharedPreferences có nhược điểm: ghi đồng bộ có thể gây chậm trễ trên luồng UI, và thiếu an toàn kiểu làm tăng nguy cơ lỗi. DataStore giải quyết những vấn đề này bằng cách cung cấp API không đồng bộ dựa trên Flow và hỗ trợ kiểu đầy đủ thông qua lược đồ protobuf.
Đối với dữ liệu có cấu trúc với mối quan hệ, SQLite hoặc wrapper Room là lựa chọn tối ưu. Cơ sở dữ liệu được lưu trữ trong một tệp duy nhất bên trong thư mục databases/ và hỗ trợ cú pháp SQL đầy đủ. Room là thư viện Jetpack chính thức cung cấp API an toàn kiểu, di chuyển lược đồ tự động và hỗ trợ coroutine. Kích thước cơ sở dữ liệu có thể đạt đến vài gigabyte mà không giảm hiệu suất đáng kể nếu được đánh chỉ mục đúng cách. SQLite trên thiết bị di động xử lý tới 50.000 thao tác ghi mỗi giây trên bộ xử lý flagship hiện đại.
Để lưu trữ dữ liệu bảo mật như mã thông báo xác thực và khóa mã hóa, Android cung cấp EncryptedSharedPreferences. Lớp bao bọc này trên SharedPreferences tiêu chuẩn tự động mã hóa khóa và giá trị bằng AES256-GCM-None. Việc mã hóa được thực hiện ở cấp tệp trước khi ghi vào đĩa, vì vậy ngay cả khi có quyền truy cập vật lý vào thiết bị, kẻ tấn công cũng không thể đọc nội dung. EncryptedSharedPreferences là một phần của thư viện AndroidX Security, cũng bao gồm EncryptedFile để mã hóa toàn bộ tệp.
Android SDK cung cấp một bộ phương pháp để làm việc với bộ nhớ trong thông qua lớp Context. Mỗi phương pháp trả về đường dẫn đến một thư mục hệ thống cụ thể trong sandbox của ứng dụng. Hãy xem xét các thao tác ghi và đọc tệp cơ bản sử dụng Kotlin làm ví dụ.
Phương pháp chính để lấy đường dẫn đến thư mục tệp nội bộ là context.filesDir. Nó trả về một đối tượng File trỏ đến thư mục /data/data/<package>/files/. Khi truy cập lần đầu, hệ thống tự động tạo tất cả các thư mục cha cần thiết. Kích thước tệp trong bộ nhớ trong không bị giới hạn rõ ràng, nhưng tổng khối lượng dữ liệu không được vượt quá không gian khả dụng trên phân vùng /data, thường chiếm 60–80% tổng dung lượng bộ nhớ flash.
val context = getApplicationContext()
val file = File(context.filesDir, "notes.txt")
file.writeText("Nội dung ghi chú")
val content = file.readText()
println("Đã đọc: $content")
Các phương pháp writeText và readText là các hàm mở rộng của thư viện chuẩn Kotlin. Chúng tự động quản lý việc mở và đóng luồng, ngăn ngừa rò rỉ bộ nhớ. Đối với dữ liệu nhị phân, hãy sử dụng writeBytes và readBytes, không yêu cầu mã hóa và làm việc với mảng ByteArray. Khi làm việc với tệp lớn, nên sử dụng luồng có bộ đệm: BufferedReader và BufferedWriter cho văn bản, BufferedInputStream và BufferedOutputStream cho dữ liệu nhị phân.
Để tổ chức tệp theo phân cấp, hãy tạo thư mục con bên trong filesDir. Điều này giúp cấu trúc dữ liệu theo loại: hình ảnh, tài liệu, tệp xuất. Phương pháp mkdirs() tạo tất cả các thư mục còn thiếu trong đường dẫn, bao gồm cả thư mục lồng nhau. Đảm bảo thao tác tạo thành công — phương pháp chỉ trả về true khi tạo thư mục mới. Lỗi tạo thường liên quan đến không gian không đủ trên phân vùng /data hoặc cạn kiệt inode của hệ thống tệp.
val imagesDir = File(context.filesDir, "images")
if (imagesDir.mkdirs()) {
println("Thư mục đã được tạo")
}
val imageFile = File(imagesDir, "photo.jpg")
imageFile.writeBytes(byteArray)
Để kiểm tra không gian khả dụng trước khi ghi tệp lớn, hãy sử dụng File.getFreeSpace() hoặc File.getUsableSpace(). Phương pháp thứ hai trả về số byte khả dụng cho ứng dụng hiện tại có tính đến hạn ngạch bảo mật — chính xác hơn trong ngữ cảnh thiết bị nhiều người dùng. Nếu không gian khả dụng nhỏ hơn kích thước tệp dự kiến, hãy hiển thị thông báo cho người dùng và đề xuất giải phóng không gian trong cài đặt thiết bị.
Trên iOS, mỗi ứng dụng hoạt động trong một vùng chứa Sandbox cách ly. Hệ thống không cung cấp API để vượt ra ngoài ranh giới của nó mà không có entitlements đặc biệt. Công cụ chính để làm việc với hệ thống tệp là lớp FileManager từ framework Foundation. Vùng chứa Sandbox bao gồm một số thư mục tiêu chuẩn, mỗi thư mục có chính sách sao lưu riêng.
Thư mục Documents dành cho dữ liệu người dùng cần được giữ lại giữa các lần khởi chạy ứng dụng và khôi phục từ bản sao lưu. iOS tự động bao gồm thư mục này trong bản sao lưu iCloud và iTunes. Phương pháp urls(for:in:) trả về một mảng URL của thư mục được yêu cầu — phần tử đầu tiên của mảng là chính.
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 hỗ trợ đầy đủ các thao tác tệp: tạo, sao chép, di chuyển, xóa và đổi tên tệp. Mỗi thao tác có thể ném lỗi, vì vậy tất cả các lệnh gọi phải được bọc trong cấu trúc do-catch. Đặc biệt chú ý đến việc xóa tệp — thao tác này không thể đảo ngược và khôi phục dữ liệu sau removeItem(at:) là không thể nếu không có bản sao lưu trước.
Không phải tất cả dữ liệu trong vùng chứa Sandbox đều nên được đưa vào bản sao lưu iCloud. Ví dụ, hình ảnh đã tải xuống trong bộ nhớ đệm hoặc tệp xử lý tạm thời không cần khôi phục — chúng sẽ được tạo lại khi sử dụng tiếp theo. Để loại trừ thư mục hoặc tệp khỏi sao lưu, đặt thuộc tính isExcludedFromBackup thành true. Apple khuyến nghị luôn loại trừ khỏi sao lưu những dữ liệu có thể khôi phục từ xa, để giảm thiểu việc sử dụng bộ nhớ iCloud và giảm thời gian khôi phục.
var cacheURL = fm.urls(
for: .cachesDirectory,
in: .userDomainMask
).first!
cacheURL.hasExcludedFromBackupKey = true
var values = URLResourceValues()
values.isExcludedFromBackup = true
try cacheURL.setResourceValues(values)
Mỗi loại bộ nhớ trên thiết bị di động có mục đích và quy tắc sử dụng riêng. Hiểu những khác biệt này giúp nhà phát triển chọn đúng vị trí cho mỗi loại dữ liệu. Dưới đây là so sánh ba loại bộ nhớ chính có sẵn cho ứng dụng.
| Đặc điểm | Internal Storage | Thư mục bộ nhớ đệm | External Storage |
|---|---|---|---|
| Hiển thị với ứng dụng khác | Ẩn | Ẩn | Có thể truy cập |
| Xóa khi gỡ ứng dụng | Hoàn toàn | Hoàn toàn | Phụ thuộc vị trí |
| Sao lưu | Android — không, iOS — có (Documents) | Không | Chỉ khi đồng bộ |
| Khả dụng không cần phương tiện | Luôn luôn | Luôn luôn | Yêu cầu thẻ SD |
| Rủi ro mất dữ liệu | Tối thiểu | Cao | Trung bình |
| Kích thước tệp khuyến nghị | Đến 100 MB | Đến 50 MB | Bất kỳ |
Bộ nhớ trong phù hợp tối ưu để lưu trữ cấu hình ứng dụng, tệp cơ sở dữ liệu và tài liệu người dùng không nên được truy cập bởi các chương trình khác. Thư mục bộ nhớ đệm dành cho các tệp tạm thời có thể được tạo lại khi sử dụng tiếp theo: hình ảnh đã tải xuống, phản hồi API, dữ liệu xử lý trung gian. Bộ nhớ ngoài phù hợp nhất cho các tệp phương tiện lớn (ảnh, video, nhạc) và dữ liệu mà người dùng muốn chia sẻ với các ứng dụng khác thông qua quyền truy cập chung.
Việc chọn loại bộ nhớ cũng ảnh hưởng đến xếp hạng ứng dụng trên Google Play và App Store. Các ứng dụng lưu trữ lượng lớn dữ liệu trong bộ nhớ trong mà không dọn dẹp sẽ nhận được đánh giá tiêu cực: người dùng phàn nàn về thiếu không gian. Theo nghiên cứu của App Annie, 62% người dùng xóa ứng dụng nếu nó chiếm hơn 500 MB bộ nhớ trong của thiết bị mà không có tùy chọn dọn dẹp.
Quản lý đúng cách bộ nhớ trong của ứng dụng cải thiện hiệu suất, bảo mật và trải nghiệm người dùng. Các khuyến nghị sau đây dựa trên tài liệu chính thức của Android và iOS, cũng như kinh nghiệm thực tế phát triển ứng dụng với hàng triệu lượt cài đặt.
Cần đặc biệt chú ý đến kiểm thử trường hợp biên. Kiểm tra hành vi ứng dụng khi bộ nhớ trong đầy, khi thao tác ghi bị gián đoạn bất ngờ (ứng dụng sập, cuộc gọi đến) và khi khôi phục từ bản sao lưu iOS. Trong mỗi kịch bản này, dữ liệu phải duy trì tính nhất quán hoặc được khôi phục về trạng thái ổn định cuối cùng. Sử dụng tệp giao dịch: ghi dữ liệu vào tệp tạm thời, sau đó đổi tên nguyên tử thành tệp đích. Điều này ngăn đọc dữ liệu hỏng khi ghi thất bại.
Đừng quên kiểm soát người dùng. Cung cấp trong cài đặt ứng dụng tùy chọn để xóa dữ liệu tạm thời và hiển thị dung lượng bộ nhớ trong đã sử dụng. Theo Google Play Console, các ứng dụng có tính năng này nhận được nhiều hơn 18% đánh giá tích cực trong danh mục “Hiệu suất”.
Các câu hỏi thường gặp
Tất cả dữ liệu từ bộ nhớ trong của ứng dụng bị xóa hoàn toàn. Hệ điều hành đảm bảo không có tệp còn sót lại, bao gồm cơ sở dữ liệu, cài đặt và tệp tạm thời. Dữ liệu trên bộ nhớ ngoài có thể vẫn còn.
Nếu không có quyền truy cập root vào thiết bị, các ứng dụng khác không thể đọc tệp từ Internal Storage của ứng dụng khác. Trên Android, điều này yêu cầu đặc quyền siêu người dùng, trong khi trên iOS, sự cách ly được thực thi ở cấp nhân thông qua Sandbox.
Không có giới hạn rõ ràng, nhưng tổng khối lượng bị giới hạn bởi không gian khả dụng trên phân vùng /data. Khuyến nghị không vượt quá 100 MB cho mỗi ứng dụng — khối lượng lớn hơn nên được đặt trên bộ nhớ ngoài hoặc đám mây.
filesDir dành cho dữ liệu ứng dụng vĩnh viễn và hệ thống không xóa trừ khi cần thiết. cacheDir dành cho tệp tạm thời mà hệ thống có thể xóa khi thiếu bộ nhớ. Hệ thống không đảm bảo tính bền vững của cacheDir.
Sao chép trực tiếp từ Internal Storage sang thẻ SD bị cấm bởi chính sách bảo mật. Sử dụng MediaStore API trên Android 10+ hoặc SAF (Storage Access Framework) để tạo bản sao dữ liệu trong bộ nhớ dùng chung với sự đồng ý của người dùng.
Tổng kết
Chúng tôi sẽ phát triển ứng dụng di động chìa khóa trao tay
IT Sectr tạo các ứng dụng iOS và Android cho các công ty khởi nghiệp và doanh nghiệp từ năm 2017. Chúng tôi sẽ tư vấn và đề xuất giải pháp tốt nhất cho bạn.
Đọc thêm