삽입된 사진 선택 도구: 앱에서 비공개로 사진과 동영상을 요청하는 더 원활한 방법
Android 사진 선택 도구를 사용하는 새로운 방법을 통해 앱의 사용자 환경을 개선할 준비를 하세요. 새로운 삽입된 사진 선택 도구를 사용하면 사용자가 앱 인터페이스 내에서 바로 원활하고 개인 정보 보호에 중점을 둔 방식으로 사진과 동영상을 선택할 수 있습니다. 이제 앱에서 클라우드 콘텐츠 액세스를 비롯해 사진 선택 도구에서 제공하는 모든 이점을 앱 환경에 직접 통합하여 누릴 수 있습니다.
왜 삽입해야 하나요?
많은 앱에서 사용자가 사진이나 동영상을 선택할 때 고도로 통합되고 원활한 환경을 제공하기를 원한다는 것을 잘 알고 있습니다. 내장된 사진 선택 도구는 사용자가 앱을 종료하지 않고도 최근 사진에 빠르게 액세스할 수 있도록 설계되었습니다. 또한 즐겨찾기, 앨범, 검색 기능을 비롯해 선호하는 클라우드 미디어 제공업체 (예: Google 포토)에서 전체 라이브러리를 탐색할 수 있습니다. 따라서 사용자는 앱 간에 전환하거나 원하는 사진이 로컬에 저장되어 있는지 클라우드에 저장되어 있는지 걱정할 필요가 없습니다.
원활한 통합, 강화된 개인 정보 보호
내장된 사진 선택 도구를 사용하면 사용자가 실제로 항목을 선택할 때까지 앱이 사용자의 사진이나 동영상에 액세스할 필요가 없습니다. 즉, 사용자에게 더 나은 개인 정보 보호와 간소화된 환경을 제공할 수 있습니다. 또한 내장된 사진 선택 도구는 사용자에게 전체 클라우드 기반 미디어 라이브러리에 대한 액세스 권한을 제공하는 반면 표준 사진 권한은 로컬 파일로만 제한됩니다.
Google 메시지의 삽입된 사진 선택 도구
Google 메시지는 삽입된 사진 선택 도구의 기능을 보여줍니다. 통합된 방식은 다음과 같습니다.
- 직관적인 배치: 사진 선택 도구가 카메라 버튼 바로 아래에 있어 사용자가 새 사진을 촬영할지 기존 사진을 선택할지 명확하게 선택할 수 있습니다.
- 동적 미리보기: 사용자가 사진을 탭하면 즉시 큰 미리보기가 표시되어 선택한 항목을 쉽게 확인할 수 있습니다. 사진을 선택 해제하면 미리보기가 사라져 깔끔한 환경을 유지할 수 있습니다.
- 더 많은 콘텐츠를 보려면 펼치기: 초기 보기가 단순화되어 최근 사진에 쉽게 액세스할 수 있습니다. 하지만 사용자는 사진 선택 도구를 쉽게 확장하여 Google 포토의 클라우드 콘텐츠를 비롯한 라이브러리의 모든 사진과 동영상을 탐색하고 선택할 수 있습니다.
- 사용자 선택 존중: 삽입된 사진 선택 도구는 사용자가 선택한 특정 사진 또는 동영상에만 액세스 권한을 부여하므로 사진 및 동영상 권한 요청을 완전히 중지할 수 있습니다. 이렇게 하면 사용자가 사진 및 동영상에 대한 제한된 액세스 권한만 부여하는 상황을 메시지에서 처리하지 않아도 됩니다.
구현
사진 선택 도구 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는 광고 배너를 계획하는 것처럼 사진 선택기의 표시 영역을 별도의 전용 요소로 고려해야 합니다.
의견이나 제안사항이 있으면 문제 추적기에 티켓을 제출하세요.
계속 읽기
-
제품 소식
개인 정보 보호와 사용자 관리 기능은 Android 환경의 핵심으로 유지됩니다. 사진 선택 도구가 미디어 공유를 안전하고 쉽게 구현할 수 있도록 지원한 것처럼 이제 연락처 선택에도 동일한 수준의 개인 정보 보호, 단순성, 뛰어난 사용자 환경을 제공합니다.
Roxanna Aliabadi Walker • 읽는 데 4분 소요
-
제품 소식
이제 Android 스튜디오 Panda 4가 안정화되어 프로덕션에서 사용할 수 있습니다. 이번 출시에는 계획 모드, 다음 수정사항 예측 등이 도입되어 고품질 Android 앱을 그 어느 때보다 쉽게 빌드할 수 있습니다.
Matt Dyor • 읽는 데 5분 소요
-
제품 소식
앱에 혁신적인 AI 기능을 구현하려는 Android 개발자라면 최근에 출시된 강력한 새 업데이트를 확인해 보세요.
Thomas Ezan • 3분 읽기
소식 받아 보기
Android 개발 관련 최신 정보를 이메일로 받아 보세요.