Selector de fotos

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.
Aparece el diálogo del selector de fotos con archivos multimedia en tu dispositivo. Selecciona una foto para compartirla con la app.
Figura 1. El selector de fotos ofrece una IU intuitiva para compartir fotos con la app.

El selector de fotos ofrece una interfaz de búsqueda explorable 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.

La herramienta se actualizará automáticamente y ofrecerá una funcionalidad expandida a los usuarios de la app con el tiempo, sin necesidad de realizar cambios en el código.

El selector de fotos está disponible en dispositivos que cumplan con los siguientes criterios:

Cómo usar los contratos de actividad de Jetpack

Para simplificar la integración del selector de fotos, incluye la versión 1.6.1 o posterior de la biblioteca androidx.activity.

Usa los siguientes contratos de resultados de actividad para iniciar el selector de fotos:

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:

Kotlin

// 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 allow the user to choose from.

// Launch the photo picker and allow the user to choose images and videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageAndVideo))

// Launch the photo picker and allow the user to choose only images.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.ImageOnly))

// Launch the photo picker and allow the user to choose only videos.
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.VideoOnly))

// Launch the photo picker and allow the user to choose only images/videos of a
// specific MIME type, such as GIFs.
val mimeType = "image/gif"
pickMedia.launch(PickVisualMediaRequest(PickVisualMedia.SingleMimeType(mimeType)))

Java

// 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 allow the user to choose from.

// Launch the photo picker and allow the user to choose images and videos.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.ImageAndVideo.INSTANCE)
        .build());

// Launch the photo picker and allow the user to choose only images.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.ImageOnly.INSTANCE)
        .build());

// Launch the photo picker and allow the user to choose only videos.
pickMedia.launch(new PickVisualMediaRequest.Builder()
        .setMediaType(PickVisualMedia.VideoOnly.INSTANCE)
        .build());

// Launch the photo picker and allow the user to 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());

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.

Kotlin

// Registers a photo picker activity launcher in multi-select mode.
// In this example, the app allows the user to 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 allow the user to 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))

Java

// Registering Photo Picker activity launcher with multiple selects (5 max in this example)
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 allow the user to 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());

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.

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 comprobar si el selector de fotos está disponible

En la siguiente sección, se describe cómo puedes usar una biblioteca de framework para verificar si el selector de fotos está disponible en un dispositivo determinado. Este flujo de trabajo te permite personalizar el comportamiento de inicio del selector de fotos y no depende de la biblioteca de compatibilidad.

Para usar la versión que proporciona el framework del selector de fotos, agrega la siguiente lógica a tu app:

Kotlin

import android.os.ext.SdkExtensions.getExtensionVersion

private fun isPhotoPickerAvailable(): Boolean {
    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        true
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        getExtensionVersion(Build.VERSION_CODES.R) >= 2
    } else {
        false
    }
}

fun handlePhotoPickerLaunch() {
    if (isPhotoPickerAvailable()) {
        // To launch the system photo picker, invoke an intent that includes the
        // ACTION_PICK_IMAGES action. Consider adding support for the
        // EXTRA_PICK_IMAGES_MAX intent extra.
    } else {
        // Consider implementing fallback functionality so that users can still
        // select images and videos.
    }
}

Java

import android.os.ext.SdkExtensions.getExtensionVersion;

private boolean isPhotoPickerAvailable() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
        return true;
    } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        return getExtensionVersion(Build.VERSION_CODES.R) >= 2;
    } else
        return false;
    }
}

public void launchPhotoPicker() {
    if (isPhotoPickerAvailable()) {
        // To launch the system photo picker, invoke an intent that includes the
        // ACTION_PICK_IMAGES action. Consider adding support for the
        // EXTRA_PICK_IMAGES_MAX intent extra.
    } else {
        // Consider implementing fallback functionality so that users can still
        // select images and videos.
    }
}