
El selector de fotos ofrece una interfaz de navegación que le presenta al usuario su biblioteca multimedia, ordenada por fecha (de lo más reciente a lo más antiguo). Como se muestra en el codelab de prácticas recomendadas sobre privacidad, el selector de fotos proporciona una forma integrada y segura para que los usuarios otorguen a tu app acceso solo a las imágenes y los videos seleccionados, en lugar de brindar acceso a su biblioteca multimedia completa.
Los usuarios que tengan proveedores de contenido multimedia en la nube aptos en sus dispositivos también pueden seleccionar fotos y videos almacenados de forma remota. Obtén más información sobre los proveedores de contenido multimedia en la nube.
La herramienta se actualizará automáticamente y ofrecerá una funcionalidad expandida a los usuarios de la app con el paso del tiempo, sin necesidad de realizar cambios en el código.
Cómo usar los contratos de actividad de Jetpack
Para simplificar la integración del selector de fotos, incluye la versión 1.7.0 o posterior de la biblioteca androidx.activity
.
Usa los siguientes contratos de resultados de actividad para iniciar el selector de fotos:
PickVisualMedia
(para seleccionar una sola imagen o video)PickMultipleVisualMedia
(para seleccionar varias imágenes o videos)
Si el selector de fotos no está disponible en un dispositivo, la biblioteca invoca automáticamente la acción de intent ACTION_OPEN_DOCUMENT
en su lugar. Este intent es compatible con dispositivos que ejecutan Android 4.4 (nivel de API 19) o versiones posteriores. Puedes verificar si el selector de fotos está disponible en un dispositivo determinado llamando a isPhotoPickerAvailable()
.
Cómo seleccionar un solo elemento multimedia
Para seleccionar un solo elemento multimedia, usa el contrato de resultados de la actividad PickVisualMedia
, como se muestra en el siguiente fragmento de código:
Objetos View
// Registers a photo picker activity launcher in single-select mode. val pickMedia = registerForActivityResult(PickVisualMedia()) { uri -> // Callback is invoked after the user selects a media item or closes the // photo picker. if (uri != null) { Log.d("PhotoPicker", "Selected URI: $uri") } else { Log.d("PhotoPicker", "No media selected") } } // Include only one of the following calls to launch(), depending on the types // of media that you want to let the user choose from. // Launch the photo picker and let the user choose images and videos. pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo)) // Launch the photo picker and let the user choose only images. pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly)) // Launch the photo picker and let the user choose only videos. pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly)) // Launch the photo picker and let the user choose only images/videos of a // specific MIME type, such as GIFs. val mimeType = "image/gif" pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType(mimeType)))
Vistas
// Registers a photo picker activity launcher in single-select mode. ActivityResultLauncher<PickVisualMediaRequest> pickMedia = registerForActivityResult(new PickVisualMedia(), uri -> { // Callback is invoked after the user selects a media item or closes the // photo picker. if (uri != null) { Log.d("PhotoPicker", "Selected URI: " + uri); } else { Log.d("PhotoPicker", "No media selected"); } }); // Include only one of the following calls to launch(), depending on the types // of media that you want to let the user choose from. // Launch the photo picker and let the user choose images and videos. pickMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE) .build()); // Launch the photo picker and let the user choose only images. pickMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.ImageOnly.INSTANCE) .build()); // Launch the photo picker and let the user choose only videos. pickMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.VideoOnly.INSTANCE) .build()); // Launch the photo picker and let the user choose only images/videos of a // specific MIME type, such as GIFs. String mimeType = "image/gif"; pickMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(new PickVisualMedia.SingleMimeType(mimeType)) .build());
Compose
// Registers a photo picker activity launcher in single-select mode. val pickMedia = rememberLauncherForActivityResult(PickVisualMedia()) { uri -> // Callback is invoked after the user selects a media item or closes the // photo picker. if (uri != null) { Log.d("PhotoPicker", "Selected URI: $uri") } else { Log.d("PhotoPicker", "No media selected") } } // Include only one of the following calls to launch(), depending on the types // of media that you want to let the user choose from. // Launch the photo picker and let the user choose images and videos. pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo)) // Launch the photo picker and let the user choose only images. pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly)) // Launch the photo picker and let the user choose only videos. pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly)) // Launch the photo picker and let the user choose only images/videos of a // specific MIME type, such as GIFs. val mimeType = "image/gif" pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType(mimeType)))
Cómo seleccionar varios elementos multimedia
Para elegir varios elementos multimedia, configura una cantidad máxima de archivos multimedia seleccionables, como se muestra en el siguiente fragmento de código.
Objetos View
// Registers a photo picker activity launcher in multi-select mode. // In this example, the app lets the user select up to 5 media files. val pickMultipleMedia = registerForActivityResult(PickMultipleVisualMedia(5)) { uris -> // Callback is invoked after the user selects media items or closes the // photo picker. if (uris.isNotEmpty()) { Log.d("PhotoPicker", "Number of items selected: ${uris.size}") } else { Log.d("PhotoPicker", "No media selected") } } // For this example, launch the photo picker and let the user choose images // and videos. If you want the user to select a specific type of media file, // use the overloaded versions of launch(), as shown in the section about how // to select a single media item. pickMultipleMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))
Vistas
// Registers a photo picker activity launcher in multi-select mode. // In this example, the app lets the user select up to 5 media files. ActivityResultLauncher<PickVisualMediaRequest> pickMultipleMedia = registerForActivityResult(new PickMultipleVisualMedia(5), uris -> { // Callback is invoked after the user selects media items or closes the // photo picker. if (!uris.isEmpty()) { Log.d("PhotoPicker", "Number of items selected: " + uris.size()); } else { Log.d("PhotoPicker", "No media selected"); } }); // For this example, launch the photo picker and let the user choose images // and videos. If you want the user to select a specific type of media file, // use the overloaded versions of launch(), as shown in the section about how // to select a single media item. pickMultipleMedia.launch(new PickVisualMediaRequest.Builder() .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE) .build());
Compose
// Registers a photo picker activity launcher in multi-select mode. // In this example, the app lets the user select up to 5 media files. val pickMultipleMedia = rememberLauncherForActivityResult(PickMultipleVisualMedia(5)) { uris -> // Callback is invoked after the user selects media items or closes the // photo picker. if (uris.isNotEmpty()) { Log.d("PhotoPicker", "Number of items selected: ${uris.size}") } else { Log.d("PhotoPicker", "No media selected") } } // For this example, launch the photo picker and let the user choose images // and videos. If you want the user to select a specific type of media file, // use the overloaded versions of launch(), as shown in the section about how // to select a single media item. pickMultipleMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))
La plataforma limita la cantidad máxima de archivos que puedes pedirle al usuario que seleccione en el selector de fotos. Para acceder a este límite, llama a getPickImagesMaxLimit()
.
En dispositivos que no admiten el selector de fotos, se ignora este límite.
Disponibilidad de dispositivos
El selector de fotos está disponible en dispositivos que cumplen con los siguientes criterios:
- Ejecuta Android 11 (nivel de API 30) o una versión posterior.
- Recibe cambios en los componentes modulares del sistema con las actualizaciones del sistema de Google.
Los dispositivos más antiguos con Android 4.4 (nivel de API 19) a Android 10 (nivel de API 29) inclusive, así como los dispositivos Android Go con Android 11 o 12 compatibles con los Servicios de Google Play, pueden instalar una versión con portabilidad a versiones anteriores del selector de fotos. Para habilitar la instalación automática del módulo del selector de fotos con portabilidad a versiones anteriores a través de los Servicios de Google Play, agrega la siguiente entrada a la etiqueta <application>
en el archivo de manifiesto de tu app:
<!-- Trigger Google Play services to install the backported photo picker module. -->
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
android:enabled="false"
android:exported="false"
tools:ignore="MissingClass">
<intent-filter>
<action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
</intent-filter>
<meta-data android:name="photopicker_activity:0:required" android:value="" />
</service>
Cómo conservar el acceso a los archivos multimedia
De forma predeterminada, el sistema le otorga a tu app acceso a los archivos multimedia hasta que se reinicie el dispositivo o hasta que se detenga la app. Si tu app realiza trabajos de larga duración (por ejemplo, subir un archivo grande en segundo plano), es posible que necesites que este acceso se conserve durante un período más extenso. Para ello, llama al método takePersistableUriPermission()
:
Kotlin
val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION context.contentResolver.takePersistableUriPermission(uri, flag)
Java
int flag = Intent.FLAG_GRANT_READ_URI_PERMISSION; context.contentResolver.takePersistableUriPermission(uri, flag);
Controla el video HDR con transcodificación
Android 13 (nivel de API 33) introdujo la capacidad de capturar videos de alto rango dinámico (HDR). Si bien el HDR ofrece una experiencia visual más rica, es posible que algunas apps más antiguas no estén preparadas para manejar estos formatos más nuevos, lo que genera problemas como una reproducción de colores poco naturales (como rostros con tinte verde). Para abordar esta brecha de compatibilidad, el selector de fotos ofrece una función de transcodificación que puede convertir automáticamente los videos HDR al formato rango dinámico estándar (SDR) antes de proporcionarlos a la app solicitante.
El objetivo principal de la transcodificación del selector de fotos es garantizar una experiencia de contenido multimedia coherente y visualmente precisa en una amplia variedad de aplicaciones, incluso aquellas que aún no admiten HDR de forma explícita. Cuando se transcodifica un video HDR a SDR, el selector de fotos tiene como objetivo mejorar la compatibilidad de la app y brindar una experiencia del usuario fluida.
Cómo funciona la transcodificación del selector de fotos
La transcodificación HDR del selector de fotos no está habilitada de forma predeterminada. Para habilitar esta función, tu app debe declarar de forma explícita sus capacidades de manejo de formatos multimedia cuando inicia el selector de fotos.
Tu app proporciona sus capacidades de procesamiento de contenido multimedia al selector de fotos. Esto se hace cuando se inicia el selector de fotos con la biblioteca de actividades de AndroidX. Para ello, se agrega mediaCapabilities
a PickVisualMediaRequest.Builder
. Se agregó una nueva API, setMediaCapabilitiesForTranscoding(capabilities: MediaCapabilities?)
, a PickVisualMediaRequest.Builder
para facilitar esto.
Puedes controlar el comportamiento de transcodificación HDR con la clase MediaCapabilities
.
Proporciona un objeto MediaCapabilities
que especifique exactamente qué tipos de HDR admite tu app (p.ej., TYPE_HLG10
, TYPE_HDR10
, TYPE_HDR10_PLUS
,
TYPE_DOLBY_VISION
).
Para inhabilitar la transcodificación por completo, pasa null
para MediaCapabilities
. Cualquier tipo de HDR que no aparezca de forma explícita en las capacidades proporcionadas se considerará no compatible. Esta API es compatible con Android 13 (nivel de API 33) y versiones posteriores, y está anototada con @RequiresApi(Build.VERSION_CODES.TIRAMISU)
.
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts.PickVisualMedia
import androidx.annotation.RequiresApi
import android.os.Build
import android.util.Log
import android.provider.MediaStore
// Registers a photo picker activity launcher.
val pickMedia = registerForActivityResult(PickVisualMedia()) { uri ->
// Callback invoked after media selected or picker activity closed.
if (uri != null) {
Log.d("photo picker", "Selected URI: $uri")
} else {
Log.d("photo picker", "No media selected")
}
}
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
fun launchPhotoPickerWithTranscodingSupport() {
val mediaCapabilities = MediaCapabilities.Builder()
.addSupportedHdrType(MediaCapabilities.HdrType.TYPE_HLG10)
.build()
// Launch the photo picker and let the user choose only videos with
// transcoding enabled.
pickMedia.launch(PickVisualMediaRequest.Builder()
.setMediaType(PickVisualMedia.VideoOnly)
.setMediaCapabilitiesForTranscoding(mediaCapabilities)
.build())
}
La transcodificación del selector de fotos se basa en las capacidades multimedia de la app y en el video elegido. Si se realiza la transcodificación, se muestra un URI al video transcodificado.
Consideraciones importantes para la transcodificación HDR
- Rendimiento y almacenamiento: La transcodificación requiere tiempo de procesamiento y crea un archivo nuevo, que consume espacio de almacenamiento.
- Límite de duración del video: Para equilibrar la experiencia del usuario y las restricciones de almacenamiento, hay un límite de 1 minuto para la duración de los videos.
- Administración de archivos almacenados en caché: Los archivos transcodificados almacenados en caché se borran periódicamente durante el mantenimiento inactivo para evitar el uso excesivo de almacenamiento.
- Disponibilidad de dispositivos: La transcodificación del selector de fotos es compatible con Android 13 (nivel de API 33) y versiones posteriores.
- Integración de actividades de AndroidX: Asegúrate de usar la versión 1.11.0-alpha01 o una versión alfa, beta, RC o estable posterior de la biblioteca de actividades de AndroidX, ya que incluye la API de
setMediaCapabilitiesForTranscoding
necesaria.