Выбор фотографий

Появится диалоговое окно выбора фотографий с медиафайлами на вашем устройстве. Выберите фотографию, чтобы поделиться ею с приложением.
Рисунок 1. Средство выбора фотографий обеспечивает интуитивно понятный пользовательский интерфейс для обмена фотографиями с вашим приложением.

Фотовыборщик предоставляет просматриваемый интерфейс, который представляет пользователю его медиатеку, отсортированную по дате от самых новых к самым старым. Как показано в codelab по лучшим практикам конфиденциальности , фотовыборщик предоставляет пользователям безопасный встроенный способ предоставить вашему приложению доступ только к выбранным изображениям и видео, а не ко всей медиатеке.

Пользователи, имеющие на своем устройстве соответствующих поставщиков облачных медиа, также могут выбирать из фотографий и видео, хранящихся удаленно. Узнайте больше о поставщиках облачных медиа .

Инструмент обновляется автоматически, со временем предлагая пользователям вашего приложения расширенные функциональные возможности без необходимости внесения каких-либо изменений в код.

Используйте контракты Jetpack Activity

Чтобы упростить интеграцию средства выбора фотографий, включите версию 1.7.0 или выше библиотеки androidx.activity .

Для запуска средства выбора фотографий используйте следующие контракты результатов активности:

Если фото-пикер недоступен на устройстве, библиотека автоматически вызывает вместо этого действие намерения ACTION_OPEN_DOCUMENT . Это намерение поддерживается на устройствах под управлением Android 4.4 (уровень API 19) или выше. Вы можете проверить, доступен ли фото-пикер на данном устройстве, вызвав isPhotoPickerAvailable() .

Выберите один элемент мультимедиа

Чтобы выбрать один элемент мультимедиа, используйте контракт результата действия PickVisualMedia , как показано в следующем фрагменте кода:

Просмотры

// 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)))

Просмотры

// 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());

Сочинять

// 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)))

Выберите несколько медиа-элементов

Чтобы выбрать несколько элементов мультимедиа, установите максимальное количество выбираемых файлов мультимедиа, как показано в следующем фрагменте кода.

Просмотры

// 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))

Просмотры

// 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());

Сочинять

// 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))

Платформа ограничивает максимальное количество файлов, которые вы можете попросить пользователя выбрать в фото-пикере. Чтобы получить доступ к этому ограничению, вызовите getPickImagesMaxLimit() . На устройствах, где фото-пикер не поддерживается, это ограничение игнорируется.

Доступность устройства

Средство выбора фотографий доступно на устройствах, соответствующих следующим критериям:

Старые устройства под управлением Android 4.4 (уровень API 19) по Android 10 (уровень API 29) и устройства Android Go под управлением Android 11 или 12, поддерживающие сервисы Google Play, могут установить бэкпортированную версию фото-пикера. Чтобы включить автоматическую установку бэкпортированного модуля фото-пикера через сервисы Google Play, добавьте следующую запись в тег <application> в файле манифеста вашего приложения:

<!-- 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>

Постоянный доступ к медиафайлам

По умолчанию система предоставляет вашему приложению доступ к медиафайлам до тех пор, пока устройство не будет перезапущено или пока ваше приложение не остановится. Если ваше приложение выполняет длительную работу, например, загружает большой файл в фоновом режиме, вам может потребоваться, чтобы этот доступ сохранялся в течение более длительного периода времени. Для этого вызовите метод takePersistableUriPermission() :

Котлин

val flag = Intent.FLAG_GRANT_READ_URI_PERMISSION
context.contentResolver.takePersistableUriPermission(uri, flag)

Ява

int flag = Intent.FLAG_GRANT_READ_URI_PERMISSION;
context.contentResolver.takePersistableUriPermission(uri, flag);

Обработка HDR-видео с помощью транскодирования

В Android 13 (API 33) появилась возможность снимать видео с высоким динамическим диапазоном (HDR) . Хотя HDR обеспечивает более богатый визуальный опыт, некоторые старые приложения могут не поддерживать эти новые форматы, что приводит к таким проблемам, как неестественная цветопередача во время воспроизведения (например, лица с зеленым оттенком). Чтобы устранить этот пробел в совместимости, средство выбора фотографий предлагает функцию перекодирования, которая может автоматически преобразовывать видео HDR в формат стандартного динамического диапазона (SDR) перед их предоставлением запрашивающему приложению.

Основная цель перекодирования фото-пикера — обеспечить единообразный и визуально точный медиа-опыт в более широком спектре приложений, даже тех, которые пока не имеют явной поддержки HDR. Перекодируя HDR-видео в SDR, фото-пикер стремится улучшить совместимость приложений и обеспечить бесперебойный пользовательский опыт.

Как работает перекодирование фото-пикера

Перекодирование HDR в Photo Picker по умолчанию не включено. Чтобы включить эту функцию, ваше приложение должно явно объявить о своих возможностях обработки форматов медиа при запуске photo Picker.

Ваше приложение предоставляет свои возможности обработки медиа для фото-пикера. Это делается при запуске фото-пикера с помощью библиотеки AndroidX Activity путем добавления mediaCapabilities в PickVisualMediaRequest.Builder . Для упрощения этого в PickVisualMediaRequest.Builder был добавлен новый API setMediaCapabilitiesForTranscoding(capabilities: MediaCapabilities?) .

Вы можете управлять поведением транскодирования HDR с помощью класса MediaCapabilities . Предоставьте объект MediaCapabilities , указав, какие именно типы HDR поддерживает ваше приложение (например, TYPE_HLG10 , TYPE_HDR10 , TYPE_HDR10_PLUS , TYPE_DOLBY_VISION ).

Чтобы полностью отключить транскодирование, передайте null для MediaCapabilities . Любой тип HDR, явно не указанный в предоставленных вами возможностях, будет считаться неподдерживаемым. Этот API поддерживается на Android 13 (уровень API 33) и выше и аннотируется @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())
}

Транскодирование с помощью фото-пикера основано как на возможностях медиа приложения, так и на выбранном видео. URI транскодированного видео возвращается, если выполняется транскодирование.

Важные соображения по перекодированию HDR

  • Производительность и хранилище: перекодирование занимает время и создает новый файл, который занимает место на диске.
  • Ограничение по продолжительности видео: для баланса между удобством использования и ограничениями по объему хранилища продолжительность видео ограничена 1 минутой.
  • Управление кэшированными файлами: кэшированные перекодированные файлы периодически очищаются во время простоя, чтобы предотвратить чрезмерное использование хранилища.
  • Доступность устройств: Транскодирование средства выбора фотографий поддерживается на Android 13 (уровень API 33) и более поздних версиях .
  • Интеграция активности AndroidX: убедитесь, что вы используете версию 1.11.0-alpha01 или более позднюю альфа/бета/RC/стабильную версию библиотеки активности AndroidX, так как она включает в себя необходимый API setMediaCapabilitiesForTranscoding .