Selector de fotos incorporado: Una forma más fluida de solicitar fotos y videos de forma privada en tu app
Prepárate para mejorar la experiencia del usuario de tu app con una nueva y emocionante forma de usar el selector de fotos de Android. El nuevo selector de fotos incorporado ofrece una forma fluida y centrada en la privacidad para que los usuarios seleccionen fotos y videos, directamente desde la interfaz de tu app. Ahora, tu app puede obtener todos los mismos beneficios disponibles con el selector de fotos, incluido el acceso al contenido en la nube, integrado directamente en la experiencia de tu app.
¿Por qué incorporado?
Entendemos que muchas apps quieren brindar una experiencia altamente integrada y fluida para los usuarios cuando seleccionan fotos o videos. El selector de fotos incorporado está diseñado para hacer exactamente eso, ya que permite que los usuarios accedan rápidamente a sus fotos recientes sin salir de tu app. También pueden explorar su biblioteca completa en su proveedor de contenido multimedia en la nube preferido (p.ej., Google Fotos), incluidos los favoritos, los álbumes y la función de búsqueda. Esto elimina la necesidad de que los usuarios cambien de app o se preocupen por si la foto que quieren está almacenada de forma local o en la nube.
Integración perfecta y privacidad mejorada
Con el selector de fotos incorporado, tu app no necesita acceder a las fotos ni a los videos del usuario hasta que este seleccione algo. Esto significa mayor privacidad para tus usuarios y una experiencia más optimizada. Además, el selector de fotos incorporado les brinda a los usuarios acceso a toda su biblioteca de contenido multimedia basada en la nube, mientras que el permiso de fotos estándar se restringe solo a los archivos locales.
El selector de fotos integrado en Mensajes de Google
Mensajes de Google muestra el poder del selector de fotos incorporado. A continuación, se indica cómo lo integraron:
- Ubicación intuitiva: El selector de fotos se encuentra justo debajo del botón de la cámara, lo que les brinda a los usuarios una opción clara entre capturar una foto nueva o seleccionar una existente.
- Vista previa dinámica: Inmediatamente después de que un usuario presiona una foto, ve una vista previa grande, lo que facilita la confirmación de su selección. Si anulan la selección de la foto, la vista previa desaparece, lo que mantiene la experiencia limpia y ordenada.
- Expande para ver más contenido: La vista inicial se simplificó y ofrece acceso fácil a las fotos recientes. Sin embargo, los usuarios pueden expandir fácilmente el selector de fotos para explorar y elegir entre todas las fotos y los videos de su biblioteca, incluido el contenido en la nube de Google Fotos.
- Respetar las elecciones de los usuarios: El selector de fotos incorporado solo otorga acceso a las fotos o los videos específicos que selecciona el usuario, lo que significa que puede dejar de solicitar los permisos de fotos y videos por completo. Esto también evita que Mensajes tenga que controlar situaciones en las que los usuarios solo otorgan acceso limitado a fotos y videos.
Implementación
La integración del selector de fotos incorporado es fácil con la biblioteca de Jetpack del selector de fotos.
Jetpack Compose
Primero, incluye la biblioteca del selector de fotos de Jetpack como una dependencia.
implementation("androidx.photopicker:photopicker-compose:1.0.0-alpha01")
La función de componibilidad EmbeddedPhotoPicker proporciona un mecanismo para incluir la IU del selector de fotos incorporado directamente en tu pantalla de Compose. Este elemento de componibilidad crea un SurfaceView que aloja la IU del selector de fotos incorporado. Administra la conexión al servicio EmbeddedPhotoPicker, controla las interacciones del usuario y comunica los URIs de contenido multimedia seleccionados a la aplicación que realiza la llamada.
@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)
}
}
)
}
}
}
}
}Vistas
Primero, incluye la biblioteca del selector de fotos de Jetpack como una dependencia.
implementation("androidx.photopicker:photopicker:1.0.0-alpha01")
Para agregar el selector de fotos incorporado, debes agregar una entrada a tu archivo de diseño.
<view class="androidx.photopicker.EmbeddedPhotoPickerView"
android:id="@+id/photopicker"
android:layout_width="match_parent"
android:layout_height="match_parent" />Y, luego, inicialízalo en tu actividad o fragmento.
// 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()
)
}Puedes llamar a diferentes métodos de EmbeddedPhotoPickerSession para interactuar con el selector incorporado.
// 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)
Es importante tener en cuenta que la experiencia del selector de fotos incorporado está disponible para los usuarios que ejecutan Android 14 (nivel de API 34) o versiones posteriores con las extensiones del SDK 15 o versiones posteriores. Obtén más información sobre la disponibilidad del selector de fotos en dispositivos.
Para mejorar la privacidad y la seguridad del usuario, el sistema renderiza el selector de fotos incorporado de una manera que evita cualquier dibujo o superposición. Esta elección de diseño intencional significa que tu UX debe considerar el área de visualización del selector de fotos como un elemento distinto y exclusivo, de la misma manera que planificarías un banner publicitario.
Si tienes comentarios o sugerencias, envía tickets a nuestro seguimiento de errores.
-
Novedades de productosLas apps que se orienten a la próxima versión de Android ya no podrán escribir directamente en los contactos con el permiso WRITE_CONTACTS.
Roxanna Aliabadi Walker • Lectura de 6 min -
Novedades de productosLa privacidad y el control del usuario siguen siendo el núcleo de la experiencia de Android. Así como el selector de fotos hizo que el uso compartido de contenido multimedia fuera seguro y fácil de implementar, ahora llevamos ese mismo nivel de privacidad, simplicidad y excelente experiencia del usuario a la selección de contactos.
Roxanna Aliabadi Walker • Lectura de 4 min -
Novedades de productosA medida que se acelera el desarrollo basado en agentes, la ingeniería de Android alcanza una nueva y emocionante frontera: pasar de la finalización de código asistida a agentes que ejecutan tareas de extremo a extremo bajo tu dirección. Tienes total libertad y flexibilidad para elegir los modelos y agentes que usas.
Jason Buchel • Lectura de 3 min
Recibe la información más reciente sobre el desarrollo de Android en tu bandeja de entrada todas las semanas.