Photo Library Permissionは、ユーザーのデバイスに保存されている写真や動画にアプリがアクセスするために必要な許可です。ギャラリーから画像を選択したり、メディアファイルを保存したり、フォトアルバムを管理するために必要です。Apple Developer Documentation, 2024によると、iOS 14以降、アプリはすべての写真に一度にアクセスするのではなく、制限されたライブラリへのアクセスをリクエストする必要があります。
重要なポイント
Photo Library Permissionは、デバイスに保存されているメディアファイルへのアプリのアクセスを制御するシステム許可です。読み取り(写真や動画の表示と選択)と書き込み(ギャラリーへの新しいファイルの保存)の両方をカバーします。モバイルプラットフォームは、写真に個人情報やプライベート情報が含まれる可能性があるため、メディアライブラリを機密データと見なします。
Android 13(API 33)では、Googleは単一のREAD_EXTERNAL_STORAGE許可を3つに分割しました: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" />
AndroidでのPhoto Library Permissionの実行時リクエストは、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フレームワークとInfo.plistのNSPhotoLibraryUsageDescriptionおよびNSPhotoLibraryAddUsageDescriptionキーを介して管理されます。iOS 14以降、ユーザーは選択した写真のみへのアクセスを許可できます(Limited Photo Library)。
ライブラリからの写真の読み取りにはNSPhotoLibraryUsageDescriptionが必要で、書き込み(写真の保存)にはNSPhotoLibraryAddUsageDescriptionが必要です。アプリがメディアを保存するだけで読み取らない場合、2番目のキーで十分です。
<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)
// リクエスト結果の処理
}
iOS 14+の.limitedステータスは、ユーザーが選択した数枚の写真にのみアクセスを許可したことを意味します。アプリはPHPhotoLibrary.shared().presentLimitedLibraryPickerを呼び出して、システムダイアログを通じて拡張アクセスをリクエストできます。このダイアログは、ユーザーが追加の写真を必要とする機能を明示的にリクエストした場合にのみ表示することをお勧めします。
PhotoPickerは、ライブラリ全体へのアクセス許可を必要としないメディアファイル選択のためのシステムコンポーネントです。Android 13とiOS 14以降、GoogleとAppleは、アプリが1枚または数枚の写真を選択するだけであれば、Photo Library Permissionをリクエストする代わりにPhotoPickerを使用することを推奨しています。
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を扱うことで、拒否の数を減らし、プラットフォームのプライバシー要件に準拠できます。
1枚または複数の写真を選択するには、システムのPhotoPickerまたはPHPickerを使用してください。これらのコンポーネントは許可を必要とせず、最良のユーザー体験を提供します。アプリの機能がメディアライブラリ全体へのアクセスを必要とする場合にのみ、完全なギャラリーアクセスをリクエストしてください。GoogleとAppleは、開発者向けドキュメントでこのアプローチを明示的に推奨しています。
アプリが本当に完全なギャラリーアクセスを必要とする場合は、説明を含む事前画面を表示してください。すべての写真が必要な理由を説明します。たとえば、バックアップアプリは、コピーを作成するためにすべてのメディアファイルをスキャンすることを説明する必要があります。事前許可画面は、制限付きアクセスメカニズムのため、iOSで特に重要です。
アプリが写真を保存するだけで読み取らない場合(たとえば、結果を保存する写真編集アプリ)、ギャラリーへの書き込み許可のみをリクエストしてください。Androidでは、これはWRITE_EXTERNAL_STORAGE(Android 12以下向け)または許可不要のMediaStore API(Android 10+向け)です。iOSでは、NSPhotoLibraryUsageDescriptionなしでNSPhotoLibraryAddUsageDescriptionを使用してください。
よくある質問
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があれば、アプリはジオタグ、撮影日、カメラモデルを含むEXIFデータを読み取れます。iOSでは、AppleがGPS座標を機密データと見なすため、ジオタグへのアクセスには追加の位置情報許可が必要になる場合があります。
システムピッカーを使用してください:iOSではfilter = .videosのPHPicker、AndroidではVideoOnlyのPickVisualMedia。Androidでは、MediaStore.Video.Media.EXTERNAL_CONTENT_URIを使用したIntent(Intent.ACTION_PICK)も使用できますが、Android 13未満のバージョンではREAD_EXTERNAL_STORAGE許可が必要です。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。