Photo Library Permission — to uprawnienie niezbędne aplikacji do dostępu do zdjęć i filmów przechowywanych na urządzeniu użytkownika. Jest wymagane do wyboru obrazów z galerii, zapisywania plików multimedialnych i zarządzania albumami zdjęciowymi. Według Apple Developer Documentation, 2024, od iOS 14 aplikacje muszą żądać dostępu do ograniczonej biblioteki, a nie do wszystkich zdjęć naraz.
Najważniejsze
Photo Library Permission — to systemowe uprawnienie regulujące dostęp aplikacji do plików multimedialnych przechowywanych na urządzeniu. Obejmuje zarówno odczyt (przeglądanie i wybór zdjęć i filmów), jak i zapis (zapisywanie nowych plików do galerii). Platformy mobilne traktują bibliotekę multimediów jako dane poufne, ponieważ zdjęcia mogą zawierać informacje osobiste i wrażliwe.
Na Android 13 (API 33) Google podzielił jedno uprawnienie READ_EXTERNAL_STORAGE na trzy osobne: READ_MEDIA_IMAGES dla zdjęć, READ_MEDIA_VIDEO dla filmów i READ_MEDIA_AUDIO dla audio. Pozwala to użytkownikowi przyznać dostęp tylko do określonego typu plików multimedialnych. Na iOS, od iOS 14, PhotoKit umożliwia użytkownikowi wybór konkretnych zdjęć do udostępnienia, zamiast otwierania całej biblioteki.
Według Counterpoint Research (2024), ponad 70% aplikacji mobilnych w kategoriach mediów społecznościowych, komunikacji i edytorów zdjęć żąda Photo Library Permission. Przy tym 32% użytkowników odmawia dostępu do galerii, jeśli nie rozumieją, po co aplikacji potrzebne są ich zdjęcia. Apple i Google zalecają korzystanie z systemowego PhotoPicker do wyboru pojedynczych plików bez żądania pełnego dostępu.
Dostęp do galerii na Android znacząco zmienił się wraz z wydaniem Android 13. Zamiast jednego uprawnienia READ_EXTERNAL_STORAGE pojawiły się szczegółowe uprawnienia dla każdego typu plików multimedialnych, co daje użytkownikowi większą kontrolę.
Od Android 13 do dostępu do zdjęć używa się READ_MEDIA_IMAGES, a do filmów — READ_MEDIA_VIDEO. Uprawnienie READ_EXTERNAL_STORAGE nie zapewnia już dostępu do plików multimedialnych — pozostało tylko do odczytu plików innych niż multimedia z pamięci współdzielonej. Deklaracja w manifeście wygląda następująco:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
Dla wstecznej zgodności z Android 12 i starszymi należy również zadeklarować READ_EXTERNAL_STORAGE. Jednak Android 13 automatycznie ignoruje to uprawnienie przy obecności nowych szczegółowych. Użyj w manifeście atrybutu android:maxSdkVersion="32" dla starego uprawnienia, aby ukryć je na nowych wersjach. Zapobiega to zbędnemu żądaniu na urządzeniach z Android 13+.
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
Żądanie w czasie wykonania dla Photo Library Permission na Android wykonuje się przez Activity Result API. Przykład żądania dostępu do obrazów:
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)
}
}
Dostęp do galerii na iOS jest zarządzany przez framework PhotoKit i klucze NSPhotoLibraryUsageDescription oraz NSPhotoLibraryAddUsageDescription w Info.plist. Od iOS 14 użytkownik może przyznać dostęp tylko do wybranych zdjęć (Limited Photo Library).
Do odczytu zdjęć z biblioteki wymagany jest NSPhotoLibraryUsageDescription, do zapisu (zapisywanie zdjęć) — NSPhotoLibraryAddUsageDescription. Jeśli aplikacja tylko zapisuje multimedia, ale ich nie odczytuje, wystarczy drugi klucz.
<key>NSPhotoLibraryUsageDescription</key>
<string>Aplikacja potrzebuje dostępu do zdjęć, aby wybrać zdjęcie profilowe i publikować zdjęcia.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>Aplikacja potrzebuje dostępu, aby zapisać przetworzone zdjęcia w Twojej galerii.</string>
Żądanie dostępu do zdjęć na iOS wykonuje się przez PHPhotoLibrary.requestAuthorization. Od iOS 14 status .limited oznacza, że użytkownik przyznał dostęp do ograniczonego zestawu zdjęć.
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)
// Praca z wynikami żądania
}
Status .limited na iOS 14+ oznacza, że użytkownik przyznał dostęp tylko do kilku wybranych zdjęć. Aplikacja może zażądać rozszerzenia dostępu przez systemowy dialog, wywołując PHPhotoLibrary.shared().presentLimitedLibraryPicker. Zaleca się pokazywanie tego dialogu tylko gdy użytkownik wyraźnie zażąda funkcji, do której potrzebne są dodatkowe zdjęcia.
PhotoPicker — to systemowy komponent wyboru plików multimedialnych, który nie wymaga uprawnienia do dostępu do całej biblioteki. Od Android 13 i iOS 14, Google i Apple zalecają korzystanie z PhotoPicker zamiast żądania Photo Library Permission, jeśli aplikacja potrzebuje tylko wybrać jedno lub kilka zdjęć.
Na Android 13+ wbudowany PhotoPicker (ActivityResultContracts.PickVisualMedia) pozwala użytkownikowi wybrać zdjęcie lub film bez przyznawania dostępu do całej galerii. Aplikacja otrzymuje tylko URI wybranych plików. PhotoPicker działa bez deklarowania jakichkolwiek uprawnień w manifeście.
private val pickMedia =
registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
if (uri != null) {
// URI wybranego pliku, bez dostępu do całej biblioteki
showImage(uri)
}
}
fun selectPhoto() {
pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
Na iOS 14+ pojawił się PHPickerViewController — systemowy picker, który również nie wymaga dostępu do całej biblioteki. PHPicker działa w osobnym procesie i nie ma dostępu do biblioteki aplikacji. Jest to preferowany sposób wyboru zdjęć w większości scenariuszy.
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 nie jest odpowiedni, jeśli aplikacja wymaga dostępu do całej biblioteki do operacji masowych: tworzenie kopii zapasowej, synchronizacja z chmurą, aplikacja-galeria, menedżer plików. W takich przypadkach należy żądać Photo Library Permission i obsługiwać przypadek ograniczonego dostępu (Limited). Dla iOS obowiązkowe jest dodanie obsługi statusu .limited i zaproponowanie użytkownikowi rozszerzenia dostępu.
Najlepsze praktyki pracy z Photo Library Permission pomagają zmniejszyć liczbę odmów i spełniać wymagania platform dotyczące ochrony prywatności.
Do wyboru jednego lub kilku zdjęć używaj systemowego PhotoPicker lub PHPicker. Te komponenty nie wymagają uprawnień i zapewniają najlepsze doświadczenie użytkownika. Pełne uprawnienie do dostępu do galerii żądaj tylko wtedy, gdy funkcjonalność aplikacji wymaga dostępu do całej biblioteki multimediów. Google i Apple wyraźnie zalecają takie podejście w dokumentacji dla programistów.
Jeśli aplikacja rzeczywiście potrzebuje pełnego dostępu do galerii, pokaż wstępny ekran z wyjaśnieniem. Wyjaśnij, po co potrzebne są wszystkie zdjęcia, a nie tylko jedno. Na przykład aplikacja do tworzenia kopii zapasowej powinna wyjaśnić, że będzie skanować wszystkie pliki multimedialne w celu utworzenia kopii. Pre-permission screen jest szczególnie ważny na iOS ze względu na mechanizm Limited Access.
Jeśli aplikacja tylko zapisuje zdjęcia, ale ich nie odczytuje (np. edytor zdjęć, który zapisuje wynik), żądaj tylko uprawnienia do zapisu w galerii. Na Android jest to WRITE_EXTERNAL_STORAGE (dla Android 12 i starszych) lub MediaStore API bez uprawnień (dla Android 10+). Na iOS używaj NSPhotoLibraryAddUsageDescription bez NSPhotoLibraryUsageDescription.
Często zadawane pytania
Od Android 10 (API 29) zapis zdjęć przez MediaStore nie wymaga uprawnienia WRITE_EXTERNAL_STORAGE. System zapewnia dostęp do pamięci współdzielonej do zapisu bez jawnego uprawnienia. Do odczytu cudzych plików nadal wymagane jest odpowiednie uprawnienie.
READ_EXTERNAL_STORAGE — stare uprawnienie do odczytu wszystkich plików z pamięci współdzielonej (do Android 12). READ_MEDIA_IMAGES — nowe szczegółowe uprawnienie do odczytu tylko obrazów (Android 13+). Użytkownik może przyznać dostęp tylko do zdjęć, odmawiając dostępu do filmów i audio.
Status .limited oznacza, że użytkownik wybrał kilka zdjęć do udostępnienia. Aplikacja może wyświetlić systemowy dialog rozszerzenia przez PHPhotoLibrary.shared().presentLimitedLibraryPicker. Zaleca się pokazywanie tego dialogu tylko na wyraźne żądanie użytkownika, na przykład po naciśnięciu przycisku „Dodaj więcej zdjęć”.
Tak, przy posiadaniu Photo Library Permission aplikacja może odczytywać dane EXIF, w tym geotagi, datę wykonania i model aparatu. Na iOS do dostępu do geotagów może być wymagane dodatkowe Location Permission, ponieważ Apple uważa współrzędne GPS za dane poufne.
Użyj systemowego pickera: PHPicker z filter = .videos na iOS, PickVisualMedia z VideoOnly na Android. Na Android do wyboru filmu z galerii można również użyć Intent(Intent.ACTION_PICK) z MediaStore.Video.Media.EXTERNAL_CONTENT_URI, ale wymaga to uprawnienia READ_EXTERNAL_STORAGE na wersjach poniżej Android 13.
Podsumowanie
Opracujemy aplikację mobilną pod klucz
IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.
Przeczytaj również