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 явно рекомендують такий підхід у документації для розробників.
Якщо програмі дійсно потрібен повний доступ до галереї, покажіть попередній екран з поясненням. Розкажіть, навіщо потрібні всі фотографії, а не лише одна. Наприклад, програма для резервного копіювання повинна пояснити, що вона скануватиме всі медіафайли для створення копії. Pre-permission screen особливо важливий для iOS через механізм Limited Access.
Якщо програма лише зберігає фото, але не читає їх (наприклад, фоторедактор, який зберігає результат), запитуйте лише дозвіл на запис у галерею. На Android це WRITE_EXTERNAL_STORAGE (для Android 12 та нижче) або MediaStore API без дозволів (для Android 10+). На iOS використовуйте NSPhotoLibraryAddUsageDescription без NSPhotoLibraryUsageDescription.
Часті запитання
Починаючи з Android 10 (API 29), збереження фото через MediaStore не потребує дозволу WRITE_EXTERNAL_STORAGE. Система надає доступ до загального сховища для запису без явного permission. Для читання чужих файлів, як і раніше, потрібен відповідний дозвіл.
READ_EXTERNAL_STORAGE — старий дозвіл для читання всіх файлів із загального сховища (до Android 12). READ_MEDIA_IMAGES — новий гранулярний дозвіл для читання лише зображень (Android 13+). Користувач може надати доступ лише до фото, відмовивши в доступі до відео та аудіо.
Статус .limited означає, що користувач вибрав кілька фото для доступу. Програма може відобразити системний діалог розширення через PHPhotoLibrary.shared().presentLimitedLibraryPicker. Рекомендується показувати цей діалог лише за явним запитом користувача, наприклад, при натисканні кнопки «Додати ще фото».
Так, за наявності Photo Library Permission програма може читати EXIF-дані, включаючи геотеги, дату зйомки та модель камери. На iOS для доступу до геотегів може знадобитися додатковий Location Permission, оскільки 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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також