Storage Access Framework: khái niệm, cách hoạt động và truy cập tệp trong Android

Tác giả: IT Sectr Đã đăng: 2026-07-10 Thời gian đọc: 6 phút

Storage Access Framework là một framework Android để truy cập an toàn vào tệp và tài liệu thông qua hộp thoại chọn của hệ thống. Thay vì yêu cầu quyền đọc bộ nhớ rộng rãi, ứng dụng nhận được một liên kết URI đến tệp do người dùng chọn. Theo Android Developers (2026), SAF hỗ trợ bộ nhớ cục bộ, các dịch vụ đám mây Google Drive và Dropbox thông qua DocumentProvider. Framework được giới thiệu trong Android 4.4 và trở thành tiêu chuẩn làm việc với tài liệu từ Android 10.

Các điểm chính

  • SAF là một framework Android để chọn tệp thông qua hộp thoại hệ thống mà không cần quyền rộng rãi.
  • Liên kết URI thay thế đường dẫn tệp trực tiếp: ứng dụng làm việc với tệp thông qua content URI.
  • Persistent permissions cho phép duy trì quyền truy cập vào tệp sau khi khởi động lại ứng dụng.
  • DocumentProvider mở rộng SAF để truy cập vào bộ nhớ đám mây và tùy chỉnh.
  • Android 10 bắt buộc sử dụng SAF để truy cập tệp bên ngoài hộp cát của ứng dụng.

Storage Access Framework là gì?

Storage Access Framework là một phần của Android SDK cung cấp giao diện thống nhất để chọn và tạo tài liệu thông qua hộp thoại hệ thống. SAF trừu tượng hóa vị trí vật lý của tệp: ứng dụng không biết tệp được đọc từ đâu — đĩa cục bộ, Google Drive hay Dropbox.

Kiến trúc SAF bao gồm ba thành phần: ứng dụng khách khởi tạo yêu cầu, trình chọn hệ thống — hộp thoại chọn tệp tiêu chuẩn, và DocumentProvider — nhà cung cấp nội dung thực hiện quyền truy cập vào tệp của một bộ nhớ cụ thể. Người dùng thấy một giao diện thống nhất bất kể nguồn dữ liệu.

SAF có sẵn từ Android 4.4 (API 19). Ban đầu, framework chỉ hỗ trợ tài liệu, nhưng Android 5.0 đã thêm hỗ trợ thư mục thông qua ACTION_OPEN_DOCUMENT_TREE. Từ Android 10, SAF trở thành phương pháp được khuyến nghị để truy cập bất kỳ tệp nào bên ngoài bộ nhớ dành riêng cho ứng dụng.

Cách SAF hoạt động: trình chọn hệ thống và URI

SAF khởi chạy hộp thoại chọn tệp hệ thống thông qua Intent với hành động ACTION_OPEN_DOCUMENT. Người dùng thấy danh sách các nguồn khả dụng: bộ nhớ trong, Google Drive, Dropbox và các nhà cung cấp đã đăng ký khác. Sau khi chọn tệp, hệ thống trả về content URI với quyền truy cập tạm thời.

Content URI có định dạng content://com.android.externalstorage.documents/document/primary/Download/file.pdf. Không giống như URI file://, content URI không tiết lộ đường dẫn tệp thực tế và hoạt động thông qua DocumentProvider. Ứng dụng đọc tệp qua ContentResolver.openInputStream bằng URI nhận được.

Trình chọn hệ thống tự động hỗ trợ tìm kiếm, sắp xếp và lọc tệp theo loại MIME. Nhà phát triển chỉ định các loại cần thiết qua Intent.putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("application/pdf", "image/*")), và trình chọn chỉ hiển thị các tệp liên quan.

Vòng đời truy cập URI

Theo mặc định, URI có hiệu lực cho đến khi khởi động lại ứng dụng hoặc thiết bị. Để truy cập dài hạn, ứng dụng yêu cầu takePersistableUriPermission — điều này cho phép đọc tệp trong các lần khởi chạy sau mà không cần chọn lại qua hộp thoại.

ACTION_OPEN_DOCUMENT và ACTION_CREATE_DOCUMENT

SAF cung cấp ba hành động chính để làm việc với tệp: mở, tạo và chọn cây thư mục. ACTION_OPEN_DOCUMENT mở trình chọn hệ thống để chọn tệp hiện có. ACTION_CREATE_DOCUMENT tạo tệp mới — người dùng nhập tên trong hộp thoại và ứng dụng nhận URI để ghi.

ACTION_OPEN_DOCUMENT_TREE cho phép chọn toàn bộ thư mục và truy cập tất cả tệp bên trong nó. Điều này được sử dụng trong trình quản lý tệp, ứng dụng sao lưu và đồng bộ hóa. Ứng dụng nhận URI thư mục và có thể liệt kê đệ quy nội dung qua DocumentFile.

Hành độngMục đíchCờ
ACTION_OPEN_DOCUMENTChọn tệp hiện cóREAD_FLAG
ACTION_CREATE_DOCUMENTTạo tệp mớiWRITE_FLAG
ACTION_OPEN_DOCUMENT_TREEChọn thư mụcREAD + WRITE

Cho mỗi hành động, các loại MIME được chỉ định qua EXTRA_MIME_TYPES. Có thể chỉ định nhiều loại: "application/pdf", "image/*", "text/plain". Nếu không chỉ định loại nào, trình chọn hiển thị tất cả tệp.

Persistent URI permissions

Persistent URI permissions là một cơ chế SAF cho phép duy trì quyền truy cập vào tệp sau khi phiên hiện tại kết thúc. Không có cờ này, URI chỉ có hiệu lực cho đến khi khởi động lại ứng dụng. Ứng dụng yêu cầu cờ FLAG_GRANT_PERSISTABLE_URI_PERMISSION cùng với các cờ READ và WRITE.

Để lưu quyền, phương thức ContentResolver.takePersistableUriPermission được sử dụng. Hệ thống lưu URI vào một sổ đăng ký đặc biệt và khôi phục quyền truy cập ở lần khởi động ứng dụng tiếp theo. Để kiểm tra xem ứng dụng có quyền truy cập liên tục vào URI hay không, sử dụng ContentResolver.persistedUriPermissions.

Người dùng có thể thu hồi quyền đã lưu qua Cài đặt → Ứng dụng → Quyền. Ứng dụng nên xử lý tình huống mất quyền truy cập vào tệp bất ngờ. Khuyến nghị kiểm tra quyền truy cập qua ContentResolver.openInputStream trước khi bắt đầu làm việc và xử lý SecurityException đúng cách.

Ví dụ mã: chọn tệp qua SAF

SAF được khởi chạy qua Intent tiêu chuẩn. Mã rất đơn giản: tạo Intent với ACTION_OPEN_DOCUMENT, chỉ định loại MIME và khởi chạy qua ActivityResultContracts.StartActivityForResult. Sau khi chọn tệp, callback nhận URI trong data.data, sau đó được sử dụng để đọc.

kotlin
val pickFile = registerForActivityResult(
    ActivityResultContracts.StartActivityForResult()
) { result ->
    result.data?.data?.let { uri ->
        val inputStream = contentResolver?.openInputStream(uri)
        // read from inputStream
    }
}

val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
    addCategory(Intent.CATEGORY_OPENABLE)
    setType("application/pdf")
    putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
pickFile.launch(intent)

Tạo tệp qua ACTION_CREATE_DOCUMENT

Để ghi tệp mới, sử dụng ACTION_CREATE_DOCUMENT. Intent chấp nhận loại MIME và tên tệp qua EXTRA_TITLE. Sau khi chọn thư mục và xác nhận, người dùng trả về URI mà ứng dụng ghi dữ liệu qua ContentResolver.openOutputStream. Hệ thống tự động tạo tệp tại vị trí đã chọn.

SAF so với READ_EXTERNAL_STORAGE

SAF khác với READ_EXTERNAL_STORAGE truyền thống ở cách tiếp cận bảo mật hoàn toàn khác. Thay vì yêu cầu quyền truy cập toàn bộ bộ nhớ cùng một lúc, SAF chỉ yêu cầu quyền truy cập vào một tệp cụ thể. Điều này giảm thiểu bề mặt tấn công và tăng niềm tin của người dùng.

READ_EXTERNAL_STORAGE cấp quyền truy cập vào tất cả tệp trên thiết bị, bao gồm ảnh và tài liệu từ ứng dụng khác. Trên Android 10+, cách tiếp cận này bị hạn chế. Ngược lại, SAF chỉ cung cấp quyền truy cập vào tệp do người dùng chọn và yêu cầu xác nhận rõ ràng cho mỗi tệp. Đối với thao tác hàng loạt trên phương tiện, hãy sử dụng MediaStore; đối với tài liệu riêng lẻ, hãy sử dụng SAF.

Nhược điểm chính của SAF là cần chọn từng tệp riêng lẻ. Đối với thao tác hàng loạt (sao lưu, đồng bộ thư mục), sử dụng ACTION_OPEN_DOCUMENT_TREE, cấp quyền truy cập vào tất cả tệp trong thư mục đã chọn. Giải pháp phụ thuộc vào kịch bản: SAF tối ưu cho lựa chọn của người dùng, MediaStore cho truy cập phương tiện theo chương trình.

Câu hỏi thường gặp

Storage Access Framework trong Android là gì?

Storage Access Framework là một framework Android để truy cập tệp an toàn thông qua hộp thoại chọn của hệ thống. Ứng dụng nhận content URI cho tệp đã chọn mà không yêu cầu quyền đọc bộ nhớ rộng rãi.

Làm thế nào để mở tệp qua SAF?

Tạo Intent với ACTION_OPEN_DOCUMENT, chỉ định loại MIME qua setType và khởi chạy qua ActivityResultContracts. Trong callback, lấy URI từ data.data và đọc qua ContentResolver.openInputStream.

Persistent URI permissions là gì?

Persistent URI permissions là cơ chế duy trì quyền truy cập vào URI sau khi khởi động lại ứng dụng. Nó được yêu cầu qua cờ FLAG_GRANT_PERSISTABLE_URI_PERMISSION và phương thức takePersistableUriPermission.

SAF hỗ trợ những loại MIME nào?

SAF hỗ trợ mọi loại MIME: application/pdf, image/*, text/plain, application/zip và các loại khác. Các loại được chỉ định qua Intent.putExtra với mảng EXTRA_MIME_TYPES.

SAF khác MediaStore như thế nào?

SAF được thiết kế để người dùng chọn tệp riêng lẻ thông qua hộp thoại hệ thống. MediaStore cung cấp quyền truy cập theo chương trình vào tất cả tệp phương tiện trên thiết bị thông qua cơ sở dữ liệu phương tiện mà không cần người dùng tương tác.

Tóm tắt

  • Storage Access Framework là một framework Android để truy cập tệp an toàn qua trình chọn hệ thống mà không cần quyền rộng rãi.
  • Content URI thay thế đường dẫn tệp: ứng dụng làm việc với tệp qua DocumentProvider, không qua liên kết file:// trực tiếp.
  • ACTION_OPEN_DOCUMENT mở tệp hiện có, ACTION_CREATE_DOCUMENT tạo tệp mới, ACTION_OPEN_DOCUMENT_TREE chọn thư mục.
  • Persistent permissions duy trì quyền truy cập vào URI sau khi khởi động lại ứng dụng qua takePersistableUriPermission.
  • Android 10 bắt buộc SAF để truy cập tệp bên ngoài bộ nhớ dành riêng cho ứng dụng, hạn chế READ_EXTERNAL_STORAGE.
  • DocumentProvider mở rộng SAF để tích hợp với bộ nhớ đám mây và tùy chỉnh.
  • Sự lựa chọn giữa SAF và MediaStore phụ thuộc vào kịch bản: SAF cho lựa chọn của người dùng, MediaStore cho truy cập phương tiện theo chương trình.

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.

Thảo luận dự án

Đọc thêm