Photo Library Permission is a permission required by an app to access photos and videos stored on the user's device. It is needed for selecting images from the gallery, saving media files, and managing photo albums. According to Apple Developer Documentation, 2024, starting with iOS 14, apps must request access to a limited library rather than all photos at once.
Key Takeaways
Photo Library Permission is a system permission that regulates an app's access to media files stored on the device. It covers both reading (viewing and selecting photos and videos) and writing (saving new files to the gallery). Mobile platforms consider the media library as sensitive data because photos may contain personal and private information.
On Android 13 (API 33), Google split the single READ_EXTERNAL_STORAGE permission into three separate ones: READ_MEDIA_IMAGES for photos, READ_MEDIA_VIDEO for videos, and READ_MEDIA_AUDIO for audio. This allows users to grant access only to a specific type of media file. On iOS, starting with iOS 14, PhotoKit enables users to select specific photos for access rather than opening the entire library.
According to Counterpoint Research (2024), more than 70% of mobile apps in the categories of social networks, communication, and photo editors request Photo Library Permission. At the same time, 32% of users deny gallery access if they do not understand why the app needs their photos. Apple and Google recommend using the system PhotoPicker for selecting individual files without requesting full access.
Gallery access on Android has changed significantly with the release of Android 13. Instead of a single READ_EXTERNAL_STORAGE permission, granular permissions for each media type have been introduced, giving users more control.
Starting with Android 13, READ_MEDIA_IMAGES is used for photo access, READ_MEDIA_VIDEO for video access. The READ_EXTERNAL_STORAGE permission no longer provides access to media files — it is retained only for reading non-media files from shared storage. The manifest declaration looks like this:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
For backward compatibility with Android 12 and below, you also need to declare READ_EXTERNAL_STORAGE. However, Android 13 automatically ignores this permission when the new granular ones are present. Use the android:maxSdkVersion="32" attribute in the manifest for the old permission to hide it on newer versions. This prevents redundant requests on devices running Android 13+.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
Runtime request for Photo Library Permission on Android is performed via the Activity Result API. Example for requesting image access:
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)
}
}
Gallery access on iOS is managed through the PhotoKit framework and the NSPhotoLibraryUsageDescription and NSPhotoLibraryAddUsageDescription keys in Info.plist. Starting with iOS 14, users can grant access only to selected photos (Limited Photo Library).
Reading photos from the library requires NSPhotoLibraryUsageDescription, while writing (saving photos) requires NSPhotoLibraryAddUsageDescription. If the app only saves media but does not read it, the second key is sufficient.
<key>NSPhotoLibraryUsageDescription</key>
<string>The app needs access to photos to select a profile picture and publish snapshots.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>The app needs access to save processed photos to your gallery.</string>
Photo access request on iOS is performed via PHPhotoLibrary.requestAuthorization. Starting with iOS 14, the .limited status indicates that the user has granted access to a limited set of photos.
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)
// Handling request results
}
The .limited status on iOS 14+ means the user has granted access only to a few selected photos. The app can request extended access through a system dialog by calling PHPhotoLibrary.shared().presentLimitedLibraryPicker. It is recommended to show this dialog only when the user explicitly requests a feature that requires additional photos.
PhotoPicker is a system component for selecting media files that does not require permission to access the entire library. Starting with Android 13 and iOS 14, Google and Apple recommend using PhotoPicker instead of requesting Photo Library Permission if the app only needs to select one or several photos.
On Android 13+, the built-in PhotoPicker (ActivityResultContracts.PickVisualMedia) allows users to select a photo or video without granting access to the entire gallery. The app receives only the URI of the selected files. PhotoPicker works without declaring any permissions in the manifest.
private val pickMedia =
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
if (uri != null) {
// URI of the selected file, without access to the entire library
showImage(uri)
}
}
fun selectPhoto() {
pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
On iOS 14+, PHPickerViewController was introduced — a system picker that also does not require access to the entire library. PHPicker runs in a separate process and has no access to the app's library. This is the preferred way to select photos for most scenarios.
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 is not suitable if the app needs access to the entire library for bulk operations: backup, cloud synchronization, gallery app, file manager. In these cases, you need to request Photo Library Permission and handle the limited access case (Limited). For iOS, you must include handling for the .limited status and offer users the option to extend access.
Best practices for working with Photo Library Permission help reduce the number of denials and comply with platform privacy requirements.
For selecting one or multiple photos, use the system PhotoPicker or PHPicker. These components do not require permissions and provide the best user experience. Request full gallery access only if the app's functionality requires access to the entire media library. Google and Apple explicitly recommend this approach in their developer documentation.
If the app truly needs full gallery access, show a preliminary screen with an explanation. Explain why all photos are needed rather than just one. For example, a backup app should explain that it will scan all media files to create a copy. The pre-permission screen is especially important for iOS due to the Limited Access mechanism.
If the app only saves photos but does not read them (e.g., a photo editor that saves the result), request only write permission to the gallery. On Android, this is WRITE_EXTERNAL_STORAGE (for Android 12 and below) or the MediaStore API without permissions (for Android 10+). On iOS, use NSPhotoLibraryAddUsageDescription without NSPhotoLibraryUsageDescription.
Frequently Asked Questions
Starting with Android 10 (API 29), saving photos via MediaStore does not require WRITE_EXTERNAL_STORAGE permission. The system provides access to shared storage for writing without an explicit permission. Reading other users' files still requires the appropriate permission.
READ_EXTERNAL_STORAGE is the old permission for reading all files from shared storage (up to Android 12). READ_MEDIA_IMAGES is a new granular permission for reading only images (Android 13+). Users can grant access only to photos while denying access to videos and audio.
The .limited status means the user selected a few photos for access. The app can display a system extension dialog via PHPhotoLibrary.shared().presentLimitedLibraryPicker. It is recommended to show this dialog only upon explicit user request, for example, when the user taps an “Add More Photos” button.
Yes, with Photo Library Permission, the app can read EXIF data, including geotags, capture date, and camera model. On iOS, accessing geotags may require additional Location Permission since Apple considers GPS coordinates as confidential data.
Use the system picker: PHPicker with filter = .videos on iOS, PickVisualMedia with VideoOnly on Android. On Android, you can also use Intent(Intent.ACTION_PICK) with MediaStore.Video.Media.EXTERNAL_CONTENT_URI to select a video from the gallery, but this requires READ_EXTERNAL_STORAGE permission on versions below Android 13.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also