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

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

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

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

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

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

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

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

Если средство выбора фотографий недоступно на устройстве, библиотека вместо этого автоматически вызывает действие намерения 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 в средстве выбора фотографий не включено по умолчанию. Чтобы включить эту функцию, вашему приложению необходимо явно объявить свои возможности обработки медиаформатов при запуске средства выбора фотографий.

Ваше приложение предоставляет средства обработки мультимедиа средству выбора фотографий. Это делается при запуске средства выбора фотографий с использованием библиотеки действий AndroidX путем добавления 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 .