Photo Library Permission là quyền cần thiết để ứng dụng truy cập vào ảnh và video được lưu trữ trên thiết bị của người dùng. Nó được yêu cầu để chọn ảnh từ thư viện, lưu tệp phương tiện và quản lý album ảnh. Theo Apple Developer Documentation, 2024, bắt đầu từ iOS 14, các ứng dụng phải yêu cầu quyền truy cập vào thư viện giới hạn, thay vì tất cả ảnh cùng một lúc.
Những Điểm Chính
Photo Library Permission là quyền hệ thống điều chỉnh quyền truy cập của ứng dụng vào các tệp phương tiện được lưu trữ trên thiết bị. Nó bao gồm cả đọc (xem và chọn ảnh và video) và ghi (lưu tệp mới vào thư viện). Các nền tảng di động coi thư viện phương tiện là dữ liệu nhạy cảm vì ảnh có thể chứa thông tin cá nhân và riêng tư.
Trên Android 13 (API 33), Google đã chia quyền READ_EXTERNAL_STORAGE duy nhất thành ba quyền riêng biệt: READ_MEDIA_IMAGES cho ảnh, READ_MEDIA_VIDEO cho video và READ_MEDIA_AUDIO cho âm thanh. Điều này cho phép người dùng chỉ cấp quyền truy cập vào một loại tệp phương tiện cụ thể. Trên iOS, bắt đầu từ iOS 14, PhotoKit cho phép người dùng chọn ảnh cụ thể để truy cập thay vì mở toàn bộ thư viện.
Theo Counterpoint Research (2024), hơn 70% ứng dụng di động trong các danh mục mạng xã hội, giao tiếp và trình chỉnh sửa ảnh yêu cầu Photo Library Permission. Đồng thời, 32% người dùng từ chối quyền truy cập thư viện nếu họ không hiểu tại sao ứng dụng cần ảnh của họ. Apple và Google khuyên bạn nên sử dụng PhotoPicker hệ thống để chọn tệp riêng lẻ mà không yêu cầu quyền truy cập đầy đủ.
Truy cập thư viện trên Android đã thay đổi đáng kể với việc phát hành Android 13. Thay vì một quyền READ_EXTERNAL_STORAGE duy nhất, các quyền chi tiết cho từng loại phương tiện đã được giới thiệu, mang lại cho người dùng nhiều quyền kiểm soát hơn.
Bắt đầu từ Android 13, READ_MEDIA_IMAGES được sử dụng để truy cập ảnh và READ_MEDIA_VIDEO để truy cập video. Quyền READ_EXTERNAL_STORAGE không còn cung cấp quyền truy cập vào tệp phương tiện — nó chỉ được giữ lại để đọc các tệp không phải phương tiện từ bộ nhớ dùng chung. Khai báo trong tệp kê khai như sau:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
Để tương thích ngược với Android 12 trở xuống, bạn cũng cần khai báo READ_EXTERNAL_STORAGE. Tuy nhiên, Android 13 tự động bỏ qua quyền này khi có các quyền chi tiết mới. Sử dụng thuộc tính android:maxSdkVersion="32" trong tệp kê khai cho quyền cũ để ẩn nó trên các phiên bản mới hơn. Điều này ngăn chặn các yêu cầu dư thừa trên thiết bị chạy Android 13+.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
Yêu cầu thời gian chạy cho Photo Library Permission trên Android được thực hiện thông qua Activity Result API. Ví dụ yêu cầu truy cập ảnh:
private val photoPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) {
loadGalleryImages()
} else {
showPermissionDenied()
}
}
fun pickPhoto() {
val permission = if (Build.version.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
Manifest.permission.READ_MEDIA_IMAGES
} else {
Manifest.permission.READ_EXTERNAL_STORAGE
}
if (ContextCompat.checkSelfPermission(this, permission)
== PackageManager.PERMISSION_GRANTED) {
loadGalleryImages()
} else {
photoPermissionLauncher.launch(permission)
}
}
Truy cập thư viện trên iOS được quản lý thông qua framework PhotoKit và các khóa NSPhotoLibraryUsageDescription và NSPhotoLibraryAddUsageDescription trong Info.plist. Bắt đầu từ iOS 14, người dùng có thể chỉ cấp quyền truy cập vào các ảnh đã chọn (Limited Photo Library).
Đọc ảnh từ thư viện yêu cầu NSPhotoLibraryUsageDescription, trong khi ghi (lưu ảnh) yêu cầu NSPhotoLibraryAddUsageDescription. Nếu ứng dụng chỉ lưu phương tiện mà không đọc chúng, khóa thứ hai là đủ.
<key>NSPhotoLibraryUsageDescription</key>
<string>Ứng dụng cần quyền truy cập vào ảnh để chọn ảnh hồ sơ và đăng ảnh chụp nhanh.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Ứng dụng cần quyền truy cập để lưu ảnh đã xử lý vào thư viện của bạn.</string>
Yêu cầu truy cập ảnh trên iOS được thực hiện qua PHPhotoLibrary.requestAuthorization. Bắt đầu từ iOS 14, trạng thái .limited cho biết người dùng đã cấp quyền truy cập vào một tập hợp ảnh giới hạn.
import PhotosUI
func requestPhotoLibraryAccess() {
PHPhotoLibrary.requestAuthorization { status in
DispatchQueue.main.async {
switch status {
case .authorized:
self.loadPhotoLibrary()
case .limited:
self.loadSelectedPhotos()
case .denied, .restricted:
self.showSettingsAlert()
case .notDetermined:
break
}
}
}
}
private func loadPhotoLibrary() {
let fetchOptions = PHFetchOptions()
fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]
let assets = PHAsset.fetchAssets(with: .image, options: fetchOptions)
// Xử lý kết quả yêu cầu
}
Trạng thái .limited trên iOS 14+ có nghĩa là người dùng chỉ cấp quyền truy cập vào một vài ảnh đã chọn. Ứng dụng có thể yêu cầu quyền truy cập mở rộng thông qua hộp thoại hệ thống bằng cách gọi PHPhotoLibrary.shared().presentLimitedLibraryPicker. Nên chỉ hiển thị hộp thoại này khi người dùng yêu cầu rõ ràng một tính năng cần thêm ảnh.
PhotoPicker là một thành phần hệ thống để chọn tệp phương tiện không yêu cầu quyền truy cập toàn bộ thư viện. Bắt đầu từ Android 13 và iOS 14, Google và Apple khuyên bạn nên sử dụng PhotoPicker thay vì yêu cầu Photo Library Permission nếu ứng dụng chỉ cần chọn một hoặc vài ảnh.
Trên Android 13+, PhotoPicker tích hợp (ActivityResultContracts.PickVisualMedia) cho phép người dùng chọn ảnh hoặc video mà không cấp quyền truy cập toàn bộ thư viện. Ứng dụng chỉ nhận được URI của các tệp đã chọn. PhotoPicker hoạt động mà không cần khai báo bất kỳ quyền nào trong tệp kê khai.
private val pickMedia =
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
if (uri != null) {
// URI của tệp đã chọn, không cần quyền truy cập toàn bộ thư viện
showImage(uri)
}
}
fun selectPhoto() {
pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
Trên iOS 14+, PHPickerViewController đã được giới thiệu — một bộ chọn hệ thống cũng không yêu cầu quyền truy cập toàn bộ thư viện. PHPicker chạy trong một tiến trình riêng biệt và không có quyền truy cập vào thư viện của ứng dụng. Đây là cách ưa thích để chọn ảnh cho hầu hết các tình huống.
import PhotosUI
func presentPhotoPicker() {
var config = PHPickerConfiguration()
config.selectionLimit = 1
config.filter = .images
let picker = PHPickerViewController(configuration: config)
picker.delegate = self
present(picker, animated: true)
}
PhotoPicker không phù hợp nếu ứng dụng cần quyền truy cập toàn bộ thư viện cho các thao tác hàng loạt: sao lưu, đồng bộ hóa đám mây, ứng dụng thư viện, trình quản lý tệp. Trong những trường hợp này, bạn cần yêu cầu Photo Library Permission và xử lý trường hợp quyền truy cập hạn chế (Limited). Đối với iOS, bắt buộc phải bao gồm xử lý trạng thái .limited và cung cấp cho người dùng tùy chọn mở rộng quyền truy cập.
Các thực hành tốt nhất khi làm việc với Photo Library Permission giúp giảm số lượng từ chối và tuân thủ các yêu cầu về quyền riêng tư của nền tảng.
Để chọn một hoặc nhiều ảnh, hãy sử dụng PhotoPicker hoặc PHPicker của hệ thống. Các thành phần này không yêu cầu quyền và mang lại trải nghiệm người dùng tốt nhất. Chỉ yêu cầu quyền truy cập đầy đủ vào thư viện nếu chức năng của ứng dụng yêu cầu quyền truy cập toàn bộ thư viện phương tiện. Google và Apple khuyến nghị rõ ràng cách tiếp cận này trong tài liệu dành cho nhà phát triển của họ.
Nếu ứng dụng thực sự cần quyền truy cập đầy đủ vào thư viện, hãy hiển thị màn hình sơ bộ kèm giải thích. Giải thích lý do tại sao cần tất cả ảnh chứ không chỉ một ảnh. Ví dụ, ứng dụng sao lưu nên giải thích rằng nó sẽ quét tất cả các tệp phương tiện để tạo bản sao. Màn hình tiền quyền đặc biệt quan trọng đối với iOS do cơ chế Truy cập Hạn chế.
Nếu ứng dụng chỉ lưu ảnh nhưng không đọc chúng (ví dụ: trình chỉnh sửa ảnh lưu kết quả), chỉ yêu cầu quyền ghi vào thư viện. Trên Android, đây là WRITE_EXTERNAL_STORAGE (cho Android 12 trở xuống) hoặc API MediaStore không cần quyền (cho Android 10+). Trên iOS, sử dụng NSPhotoLibraryAddUsageDescription mà không cần NSPhotoLibraryUsageDescription.
Câu Hỏi Thường Gặp
Bắt đầu từ Android 10 (API 29), lưu ảnh qua MediaStore không yêu cầu quyền WRITE_EXTERNAL_STORAGE. Hệ thống cung cấp quyền truy cập vào bộ nhớ dùng chung để ghi mà không cần quyền rõ ràng. Đọc tệp của người dùng khác vẫn yêu cầu quyền thích hợp.
READ_EXTERNAL_STORAGE là quyền cũ để đọc tất cả tệp từ bộ nhớ dùng chung (đến Android 12). READ_MEDIA_IMAGES là quyền chi tiết mới để chỉ đọc ảnh (Android 13+). Người dùng có thể chỉ cấp quyền truy cập vào ảnh, từ chối quyền truy cập vào video và âm thanh.
Trạng thái .limited có nghĩa là người dùng đã chọn một số ảnh để truy cập. Ứng dụng có thể hiển thị hộp thoại mở rộng hệ thống qua PHPhotoLibrary.shared().presentLimitedLibraryPicker. Nên chỉ hiển thị hộp thoại này khi người dùng yêu cầu rõ ràng, ví dụ: khi nhấn vào nút “Thêm ảnh khác”.
Có, với Photo Library Permission, ứng dụng có thể đọc dữ liệu EXIF, bao gồm thẻ địa lý, ngày chụp và kiểu máy ảnh. Trên iOS, việc truy cập thẻ địa lý có thể yêu cầu quyền vị trí bổ sung, vì Apple coi tọa độ GPS là dữ liệu bí mật.
Sử dụng bộ chọn hệ thống: PHPicker với filter = .videos trên iOS, PickVisualMedia với VideoOnly trên Android. Trên Android, bạn cũng có thể sử dụng Intent(Intent.ACTION_PICK) với MediaStore.Video.Media.EXTERNAL_CONTENT_URI để chọn video từ thư viện, nhưng điều này yêu cầu quyền READ_EXTERNAL_STORAGE trên các phiên bản dưới Android 13.
Tóm Tắ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