埋め込み写真選択ツール: アプリ内で写真や動画を非公開でリクエストする、よりシームレスな方法
Android 写真選択ツールの新しい使用方法で、アプリのユーザー エクスペリエンスを向上させる準備をしましょう。新しい埋め込み写真選択ツールを使用すると、アプリのインターフェース内で写真や動画をシームレスかつプライバシーを重視して選択できます。アプリは、クラウド コンテンツへのアクセスなど、写真選択ツールで利用できるすべてのメリットをアプリのエクスペリエンスに直接統合できます。
埋め込みのメリット
多くのアプリが、写真や動画を選択する際に、高度に統合されたシームレスなエクスペリエンスをユーザーに提供したいと考えていることを Google は理解しています。埋め込み写真選択ツールは、まさにそれを実現するために設計されており、ユーザーはアプリを離れることなく最近の写真にすばやくアクセスできます。また、お気に入りの写真、アルバム、検索機能など、好みのクラウド メディア プロバイダ(Google フォトなど)のライブラリ全体を探索することもできます。これにより、ユーザーはアプリを切り替える必要がなくなり、目的の写真がローカルに保存されているかクラウドに保存されているかを気にする必要もなくなります。
シームレスな統合、プライバシーの強化
埋め込み写真選択ツールを使用すると、ユーザーが実際に何かを選択するまで、アプリはユーザーの写真や動画にアクセスする必要がありません。これにより、ユーザーのプライバシーが強化され、エクスペリエンスが合理化されます。さらに、埋め込み写真選択ツールでは、ユーザーはクラウドベースのメディア ライブラリ全体にアクセスできますが、標準の写真権限はローカル ファイルのみに制限されます。
Google メッセージの埋め込み写真選択ツール
Google メッセージは、埋め込み写真選択ツールの機能を活用しています。統合方法は次のとおりです。
- 直感的な配置: 写真選択ツールはカメラボタンのすぐ下に配置されているため、ユーザーは新しい写真を撮影するか、既存の写真を選択するかを明確に選択できます。
- 動的なプレビュー: ユーザーが写真をタップするとすぐに大きなプレビューが表示されるため、選択内容を簡単に確認できます。写真の選択を解除するとプレビューが消え、すっきりとしたエクスペリエンスが維持されます。
- 展開してコンテンツを増やす: 最初のビューは簡略化され、最近の写真に簡単にアクセスできます。ただし、ユーザーは写真選択ツールを簡単に展開して、Google フォトのクラウド コンテンツなど、ライブラリ内のすべての写真や動画を閲覧して選択できます。
- ユーザーの選択を尊重: 埋め込み写真選択ツールは、ユーザーが選択した特定の写真や動画にのみアクセス権を付与します。つまり、写真と動画の権限のリクエストを完全に停止できます。これにより、ユーザーが写真や動画へのアクセスを制限した場合に、メッセージで対応する必要がなくなります。
実装
埋め込み写真選択ツールの統合は、Photo Picker Jetpack ライブラリを使用すると簡単に行えます。
Jetpack Compose
まず、Jetpack Photo Picker ライブラリを依存関係として含めます。
implementation("androidx.photopicker:photopicker-compose:1.0.0-alpha01")
EmbeddedPhotoPicker コンポーズ可能な関数は、Compose 画面内に埋め込み写真選択ツールの UI を直接含めるメカニズムを提供します。このコンポーザブルは、埋め込み写真選択ツールの UI をホストする SurfaceView を作成します。EmbeddedPhotoPicker サービスへの接続を管理し、ユーザー操作を処理し、選択したメディア URI を呼び出し元のアプリケーションに伝えます。
@Composable fun EmbeddedPhotoPickerDemo() { // We keep track of the list of selected attachments var attachments by remember { mutableStateOf(emptyList<Uri>()) } val coroutineScope = rememberCoroutineScope() // We hide the bottom sheet by default but we show it when the user clicks on the button val scaffoldState = rememberBottomSheetScaffoldState( bottomSheetState = rememberStandardBottomSheetState( initialValue = SheetValue.Hidden, skipHiddenState = false ) ) // Customize the embedded photo picker val photoPickerInfo = EmbeddedPhotoPickerFeatureInfo .Builder() // Set limit the selection to 5 items .setMaxSelectionLimit(5) // Order the items selection (each item will have an index visible in the photo picker) .setOrderedSelection(true) // Set the accent color (red in this case, otherwise it follows the device's accent color) .setAccentColor(0xFF0000) .build() // The embedded photo picker state will be stored in this variable val photoPickerState = rememberEmbeddedPhotoPickerState( onSelectionComplete = { coroutineScope.launch { // Hide the bottom sheet once the user has clicked on the done button inside the picker scaffoldState.bottomSheetState.hide() } }, onUriPermissionGranted = { // We update our list of attachments with the new Uris granted attachments += it }, onUriPermissionRevoked = { // We update our list of attachments with the Uris revoked attachments -= it } ) SideEffect { val isExpanded = scaffoldState.bottomSheetState.targetValue == SheetValue.Expanded // We show/hide the embedded photo picker to match the bottom sheet state photoPickerState.setCurrentExpanded(isExpanded) } BottomSheetScaffold( topBar = { TopAppBar(title = { Text("Embedded Photo Picker demo") }) }, scaffoldState = scaffoldState, sheetPeekHeight = if (scaffoldState.bottomSheetState.isVisible) 400.dp else 0.dp, sheetContent = { Column(Modifier.fillMaxWidth()) { // We render the embedded photo picker inside the bottom sheet EmbeddedPhotoPicker( state = photoPickerState, embeddedPhotoPickerFeatureInfo = photoPickerInfo ) } } ) { innerPadding -> Column(Modifier.padding(innerPadding).fillMaxSize().padding(horizontal = 16.dp)) { Button(onClick = { coroutineScope.launch { // We expand the bottom sheet, which will trigger the embedded picker to be shown scaffoldState.bottomSheetState.partialExpand() } }) { Text("Open photo picker") } LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 64.dp)) { // We render the image using the Coil library itemsIndexed(attachments) { index, uri -> AsyncImage( model = uri, contentDescription = "Image ${index + 1}", contentScale = ContentScale.Crop, modifier = Modifier.clickable { coroutineScope.launch { // When the user clicks on the media from the app's UI, we deselect it // from the embedded photo picker by calling the method deselectUri photoPickerState.deselectUri(uri) } } ) } } } } }
視聴回数
まず、Jetpack Photo Picker ライブラリを依存関係として含めます。
implementation("androidx.photopicker:photopicker:1.0.0-alpha01")
埋め込み写真選択ツールを追加するには、レイアウト ファイルにエントリを追加する必要があります。
<view class="androidx.photopicker.EmbeddedPhotoPickerView"
android:id="@+id/photopicker"
android:layout_width="match_parent"
android:layout_height="match_parent" />アクティビティまたはフラグメントで初期化します。
// We keep track of the list of selected attachments private val _attachments = MutableStateFlow(emptyList<Uri>()) val attachments = _attachments.asStateFlow() private lateinit var picker: EmbeddedPhotoPickerView private var openSession: EmbeddedPhotoPickerSession? = null val pickerListener = object EmbeddedPhotoPickerStateChangeListener { override fun onSessionOpened (newSession: EmbeddedPhotoPickerSession) { openSession = newSession } override fun onSessionError (throwable: Throwable) {} override fun onUriPermissionGranted(uris: List<Uri>) { _attachments += uris } override fun onUriPermissionRevoked (uris: List<Uri>) { _attachments -= uris } override fun onSelectionComplete() { // Hide the embedded photo picker as the user is done with the photo/video selection } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main_view) // // Add the embedded photo picker to a bottom sheet to allow the dragging to display the full photo library // picker = findViewById(R.id.photopicker) picker.addEmbeddedPhotoPickerStateChangeListener(pickerListener) picker.setEmbeddedPhotoPickerFeatureInfo( // Set a custom accent color EmbeddedPhotoPickerFeatureInfo.Builder().setAccentColor(0xFF0000).build() ) }
EmbeddedPhotoPickerSession のさまざまなメソッドを呼び出して、埋め込み選択ツールを操作できます。
// Notify the embedded picker of a configuration change openSession.notifyConfigurationChanged(newConfig) // Update the embedded picker to expand following a user interaction openSession.notifyPhotoPickerExpanded(/* expanded: */ true) // Resize the embedded picker openSession.notifyResized(/* width: */ 512, /* height: */ 256) // Show/hide the embedded picker (after a form has been submitted) openSession.notifyVisibilityChanged(/* visible: */ false) // Remove unselected media from the embedded picker after they have been // unselected from the host app's UI openSession.requestRevokeUriPermission(removedUris)
埋め込み写真選択ツールのエクスペリエンスは、SDK 拡張機能 15 以降を搭載した Android 14(API レベル 34)以降を実行しているユーザーが利用できます。詳しくは、写真選択ツールを利用できるデバイスをご覧ください。
ユーザーのプライバシーとセキュリティを強化するため、システムは描画やオーバーレイを防ぐ方法で埋め込み写真選択ツールを表示します。この意図的な設計上の選択により、UX では、広告バナーを計画する場合と同様に、写真選択ツールの表示領域を個別の専用要素として考慮する必要があります。
フィードバックやご提案がありましたら、Issue Trackerにチケットを送信してください。
続きを読む
-
プロダクト ニュース
プライバシーとユーザーによる管理は、Android エクスペリエンスの中核をなすものです。写真選択ツールでメディアの共有が安全かつ簡単に実装できるようになったのと同様に、連絡先の選択にも同じレベルのプライバシー、シンプルさ、優れたユーザー エクスペリエンスがもたらされます。
Roxanna Aliabadi Walker • 4 分で読了
-
プロダクト ニュース
デベロッパーの AI ワークフローとニーズはそれぞれ異なるため、AI が開発にどのように役立つかを選択できることが重要です。1 月に、ローカルまたはリモートの任意の AI モデルを選択して Android Studio の AI 機能に活用できる機能が導入されました。
Matthew Warner • 2 分で読了
-
プロダクト ニュース
Android Studio Panda 3 が安定版となり、本番環境で使用できる準備が整いました。このリリースでは、AI を活用したワークフローの制御とカスタマイズがさらに強化され、高品質の Android アプリをこれまで以上に簡単に構築できるようになります。
Matt Dyor • 3 分で読了
メールを受け取る
Android 開発に関する最新の分析情報を毎週メールでお届けします。