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 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также