
El selector de fotos ofrece una interfaz de exploració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());
Redactar
// 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());
Redactar
// 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);
Cómo controlar videos HDR con transcodificación
Android 13 (API 33) introdujo la capacidad de capturar videos de alto rango dinámico (HDR). Si bien el HDR ofrece una experiencia visual más enriquecida, es posible que algunas apps más antiguas no estén equipadas para controlar estos formatos más nuevos, lo que genera problemas como una reproducción de colores poco natural (por ejemplo, rostros con un 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 de 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 multimedia coherente y visualmente precisa en una mayor variedad de aplicaciones, incluso en aquellas que aún no tienen compatibilidad explícita con HDR. Al transcodificar videos HDR a SDR, el selector de fotos busca mejorar la compatibilidad de las apps y brindar una experiencia del usuario optimizada.
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 procesamiento de formatos multimedia cuando inicie el selector de fotos.
Tu app proporciona sus capacidades de procesamiento de medios al selector de fotos. Esto se realiza cuando se inicia el selector de fotos con la biblioteca de actividades de AndroidX agregando mediaCapabilities
a PickVisualMediaRequest.Builder
. Se agregó una nueva API, setMediaCapabilitiesForTranscoding(capabilities: MediaCapabilities?)
, a PickVisualMediaRequest.Builder
para facilitar esta tarea.
Puedes controlar el comportamiento de la 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 se incluya de forma explícita en las capacidades proporcionadas se considerará no compatible. Esta API se admite en Android 13 (nivel de API 33) y versiones posteriores, y se anota 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 tanto en las capacidades multimedia de la app como en el video elegido. Si se realiza la transcodificación, se devuelve 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, lo que consume espacio de almacenamiento.
- Límite de duración del video: Para equilibrar la experiencia del usuario y las limitaciones de almacenamiento, la duración de los videos tiene un límite de 1 minuto.
- 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 en dispositivos: La transcodificación del selector de fotos es compatible con Android 13 (nivel de API 33) y versiones posteriores.
- Integración de AndroidX Activity: Asegúrate de usar la versión 1.11.0-alpha01 o una versión estable, RC, beta o alfa posterior de la biblioteca de AndroidX Activity, ya que incluye la API de
setMediaCapabilitiesForTranscoding
necesaria.