Photo Library Permission คือสิทธิ์ที่จำเป็นสำหรับแอปพลิเคชันในการเข้าถึงรูปภาพและวิดีโอที่จัดเก็บไว้บนอุปกรณ์ของผู้ใช้ จำเป็นสำหรับการเลือกรูปภาพจากแกลเลอรี บันทึกไฟล์มีเดีย และจัดการอัลบั้มรูปภาพ ตาม Apple Developer Documentation, 2024 ตั้งแต่ iOS 14 เป็นต้นไป แอปพลิเคชันต้องขอเข้าถึงคลังแบบจำกัด ไม่ใช่รูปภาพทั้งหมดพร้อมกัน
ประเด็นสำคัญ
Photo Library Permission คือสิทธิ์ของระบบที่ควบคุมการเข้าถึงไฟล์มีเดียที่จัดเก็บไว้บนอุปกรณ์ของแอปพลิเคชัน ครอบคลุมทั้งการอ่าน (การดูและเลือกรูปภาพและวิดีโอ) และการเขียน (การบันทึกไฟล์ใหม่ในแกลเลอรี) แพลตฟอร์มมือถือถือว่าคลังมีเดียเป็นข้อมูลที่ละเอียดอ่อนเนื่องจากรูปภาพอาจมีข้อมูลส่วนตัวและข้อมูลส่วนบุคคล
บน Android 13 (API 33) Google ได้แบ่งสิทธิ์ READ_EXTERNAL_STORAGE เดียวออกเป็นสามสิทธิ์แยกกัน: READ_MEDIA_IMAGES สำหรับรูปภาพ READ_MEDIA_VIDEO สำหรับวิดีโอ และ READ_MEDIA_AUDIO สำหรับเสียง ทำให้ผู้ใช้สามารถให้สิทธิ์เข้าถึงไฟล์มีเดียประเภทใดประเภทหนึ่งเท่านั้น บน iOS ตั้งแต่ iOS 14 เป็นต้นไป PhotoKit ให้ผู้ใช้สามารถเลือกรูปภาพเฉพาะเพื่อเข้าถึงแทนที่จะเปิดคลังทั้งหมด
ตาม Counterpoint Research (2024) แอปมือถือมากกว่า 70% ในหมวดหมู่โซเชียลเน็ตเวิร์ก การสื่อสาร และโปรแกรมแก้ไขรูปภาพขอ Photo Library Permission ในขณะเดียวกัน ผู้ใช้ 32% ปฏิเสธการเข้าถึงแกลเลอรีหากไม่เข้าใจว่าแอปต้องการรูปภาพของพวกเขาทำไม Apple และ Google แนะนำให้ใช้ PhotoPicker ของระบบเพื่อเลือกไฟล์แต่ละไฟล์โดยไม่ต้องขอสิทธิ์เข้าถึงเต็มรูปแบบ
การเข้าถึงแกลเลอรีบน Android เปลี่ยนแปลงอย่างมีนัยสำคัญเมื่อ Android 13 เปิดตัว แทนที่จะใช้สิทธิ์ READ_EXTERNAL_STORAGE เดียว ได้มีการแนะนำสิทธิ์แบบละเอียดสำหรับไฟล์มีเดียแต่ละประเภท ทำให้ผู้ใช้ควบคุมได้มากขึ้น
ตั้งแต่ Android 13 เป็นต้นไป ใช้ READ_MEDIA_IMAGES สำหรับการเข้าถึงรูปภาพ และ READ_MEDIA_VIDEO สำหรับการเข้าถึงวิดีโอ สิทธิ์ READ_EXTERNAL_STORAGE ไม่ได้ให้การเข้าถึงไฟล์มีเดียอีกต่อไป — ยังคงไว้สำหรับการอ่านไฟล์ที่ไม่ใช่มีเดียจากพื้นที่เก็บข้อมูลที่ใช้ร่วมกันเท่านั้น การประกาศในแมนิเฟสต์มีลักษณะดังนี้:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
สำหรับความเข้ากันได้ย้อนหลังกับ Android 12 และต่ำกว่า คุณต้องประกาศ READ_EXTERNAL_STORAGE ด้วย อย่างไรก็ตาม Android 13 จะไม่สนใจสิทธิ์นี้โดยอัตโนมัติเมื่อมีสิทธิ์แบบละเอียดใหม่ ใช้แอตทริบิวต์ android:maxSdkVersion="32" ในแมนิเฟสต์สำหรับสิทธิ์เก่าเพื่อซ่อนบนเวอร์ชันใหม่ ซึ่งป้องกันการขอสิทธิ์ซ้ำซ้อนบนอุปกรณ์ที่ใช้ Android 13+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
การขอสิทธิ์ขณะรันไทม์สำหรับ Photo Library Permission บน Android ดำเนินการผ่าน Activity Result API ตัวอย่างการขอสิทธิ์เข้าถึงรูปภาพ:
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)
}
}
การเข้าถึงแกลเลอรีบน iOS จัดการผ่านเฟรมเวิร์ก PhotoKit และคีย์ NSPhotoLibraryUsageDescription และ NSPhotoLibraryAddUsageDescription ใน Info.plist ตั้งแต่ iOS 14 เป็นต้นไป ผู้ใช้สามารถให้สิทธิ์เข้าถึงเฉพาะรูปภาพที่เลือก (Limited Photo Library)
การอ่านรูปภาพจากคลังต้องใช้ NSPhotoLibraryUsageDescription ในขณะที่การเขียน (บันทึกรูปภาพ) ต้องใช้ NSPhotoLibraryAddUsageDescription หากแอปบันทึกมีเดียเท่านั้นโดยไม่ได้อ่าน คีย์ที่สองก็เพียงพอ
<key>NSPhotoLibraryUsageDescription</key>
<string>แอปต้องเข้าถึงรูปภาพเพื่อเลือกรูปโปรไฟล์และเผยแพร่ภาพสแนปช็อต</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>แอปต้องเข้าถึงเพื่อบันทึกรูปภาพที่ประมวลผลแล้วในแกลเลอรีของคุณ</string>
การขอสิทธิ์เข้าถึงรูปภาพบน iOS ดำเนินการผ่าน PHPhotoLibrary.requestAuthorization ตั้งแต่ iOS 14 เป็นต้นไป สถานะ .limited บ่งชี้ว่าผู้ใช้ให้สิทธิ์เข้าถึงชุดรูปภาพแบบจำกัด
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)
// การจัดการผลลัพธ์การขอสิทธิ์
}
สถานะ .limited บน iOS 14+ หมายความว่าผู้ใช้ให้สิทธิ์เข้าถึงเฉพาะรูปภาพที่เลือกไว้ไม่กี่รูป แอปสามารถขอสิทธิ์เข้าถึงเพิ่มเติมผ่านไดอะล็อกของระบบโดยเรียก PHPhotoLibrary.shared().presentLimitedLibraryPicker แนะนำให้แสดงไดอะล็อกนี้เมื่อผู้ใช้ร้องขอฟีเจอร์ที่ต้องการรูปภาพเพิ่มเติมอย่างชัดเจนเท่านั้น
PhotoPicker คือส่วนประกอบของระบบสำหรับเลือกไฟล์มีเดียที่ไม่ต้องการสิทธิ์เข้าถึงคลังทั้งหมด ตั้งแต่ Android 13 และ iOS 14 เป็นต้นไป Google และ Apple แนะนำให้ใช้ PhotoPicker แทนการขอ Photo Library Permission หากแอปต้องการเลือกรูปภาพเพียงหนึ่งหรือไม่กี่รูป
บน Android 13+ PhotoPicker ในตัว (ActivityResultContracts.PickVisualMedia) ให้ผู้ใช้เลือกรูปภาพหรือวิดีโอโดยไม่ต้องให้สิทธิ์เข้าถึงแกลเลอรีทั้งหมด แอปได้รับเฉพาะ URI ของไฟล์ที่เลือก PhotoPicker ทำงานโดยไม่ต้องประกาศสิทธิ์ใดๆ ในแมนิเฟสต์
private val pickMedia =
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
if (uri != null) {
// URI ของไฟล์ที่เลือก โดยไม่ต้องเข้าถึงคลังทั้งหมด
showImage(uri)
}
}
fun selectPhoto() {
pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
บน iOS 14+ มีการแนะนำ PHPickerViewController — ตัวเลือกระบบที่ไม่ต้องการสิทธิ์เข้าถึงคลังทั้งหมดเช่นกัน PHPicker ทำงานในโพรเซสแยกต่างหากและไม่สามารถเข้าถึงคลังของแอปได้ นี่เป็นวิธีที่แนะนำในการเลือกรูปภาพสำหรับสถานการณ์ส่วนใหญ่
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 ไม่เหมาะสมหากแอปต้องการเข้าถึงคลังทั้งหมดสำหรับการดำเนินการจำนวนมาก: การสำรองข้อมูล การซิงค์คลาวด์ แอปแกลเลอรี ตัวจัดการไฟล์ ในกรณีเหล่านี้ คุณต้องขอ Photo Library Permission และจัดการกรณีการเข้าถึงแบบจำกัด (Limited) สำหรับ iOS จำเป็นต้องรวมการจัดการสถานะ .limited และเสนอตัวเลือกให้ผู้ใช้ขยายการเข้าถึง
แนวปฏิบัติที่ดีที่สุด สำหรับการทำงานกับ Photo Library Permission ช่วยลดจำนวนการปฏิเสธและปฏิบัติตามข้อกำหนดความเป็นส่วนตัวของแพลตฟอร์ม
สำหรับการเลือกรูปภาพหนึ่งหรือหลายรูป ให้ใช้ PhotoPicker หรือ PHPicker ของระบบ ส่วนประกอบเหล่านี้ไม่ต้องการสิทธิ์และให้ประสบการณ์ผู้ใช้ที่ดีที่สุด ขอสิทธิ์เข้าถึงแกลเลอรีเต็มรูปแบบเฉพาะเมื่อฟังก์ชันการทำงานของแอปต้องการเข้าถึงคลังมีเดียทั้งหมด Google และ Apple แนะนำแนวทางนี้อย่างชัดเจนในเอกสารสำหรับนักพัฒนา
หากแอปจำเป็นต้องเข้าถึงแกลเลอรีเต็มรูปแบบจริงๆ ให้แสดงหน้าจอเบื้องต้นพร้อมคำอธิบาย อธิบายว่าทำไมต้องใช้รูปภาพทั้งหมดไม่ใช่เพียงรูปเดียว ตัวอย่างเช่น แอปสำรองข้อมูลควรอธิบายว่าจะสแกนไฟล์มีเดียทั้งหมดเพื่อสร้างสำเนา หน้าจอก่อนขอสิทธิ์ มีความสำคัญเป็นพิเศษสำหรับ iOS เนื่องจากกลไกการเข้าถึงแบบจำกัด
หากแอปบันทึกรูปภาพเท่านั้นโดยไม่ได้อ่าน (เช่น โปรแกรมแก้ไขรูปภาพที่บันทึกผลลัพธ์) ให้ขอเฉพาะสิทธิ์เขียนในแกลเลอรี บน Android นี่คือ WRITE_EXTERNAL_STORAGE (สำหรับ Android 12 และต่ำกว่า) หรือ MediaStore API โดยไม่ต้องมีสิทธิ์ (สำหรับ Android 10+) บน iOS ให้ใช้ NSPhotoLibraryAddUsageDescription โดยไม่ต้องมี NSPhotoLibraryUsageDescription
คำถามที่พบบ่อย
ตั้งแต่ Android 10 (API 29) เป็นต้นไป การบันทึกรูปภาพผ่าน MediaStore ไม่ต้องการสิทธิ์ WRITE_EXTERNAL_STORAGE ระบบให้การเข้าถึงพื้นที่เก็บข้อมูลที่ใช้ร่วมกันสำหรับการเขียนโดยไม่ต้องมีสิทธิ์ชัดเจน การอ่านไฟล์ของผู้ใช้อื่นยังคงต้องมีสิทธิ์ที่เหมาะสม
READ_EXTERNAL_STORAGE คือสิทธิ์เก่าสำหรับอ่านไฟล์ทั้งหมดจากพื้นที่เก็บข้อมูลที่ใช้ร่วมกัน (จนถึง Android 12) READ_MEDIA_IMAGES คือสิทธิ์แบบละเอียดใหม่สำหรับอ่านเฉพาะรูปภาพ (Android 13+) ผู้ใช้สามารถให้สิทธิ์เข้าถึงเฉพาะรูปภาพ โดยปฏิเสธการเข้าถึงวิดีโอและเสียง
สถานะ .limited หมายความว่าผู้ใช้เลือกรูปภาพบางรูปเพื่อเข้าถึง แอปสามารถแสดงไดอะล็อกขยายการเข้าถึงของระบบผ่าน PHPhotoLibrary.shared().presentLimitedLibraryPicker แนะนำให้แสดงไดอะล็อกนี้เมื่อผู้ใช้ร้องขออย่างชัดเจนเท่านั้น เช่น เมื่อแตะปุ่ม “เพิ่มรูปภาพเพิ่มเติม”
ได้ ด้วย Photo Library Permission แอปสามารถอ่านข้อมูล EXID รวมถึงแท็กตำแหน่ง วันที่ถ่าย และรุ่นกล้อง บน iOS การเข้าถึงแท็กตำแหน่งอาจต้องมี สิทธิ์ตำแหน่งเพิ่มเติม เนื่องจาก Apple ถือว่าพิกัด GPS เป็นข้อมูลลับ
ใช้ตัวเลือกระบบ: PHPicker ด้วย filter = .videos บน iOS, PickVisualMedia ด้วย VideoOnly บน Android บน Android คุณยังสามารถใช้ Intent(Intent.ACTION_PICK) กับ MediaStore.Video.Media.EXTERNAL_CONTENT_URI เพื่อเลือกวิดีโอจากแกลเลอรี แต่ต้องใช้สิทธิ์ READ_EXTERNAL_STORAGE ในเวอร์ชันที่ต่ำกว่า Android 13
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม