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

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

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

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

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

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

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

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

Если окно выбора фотографий недоступно на устройстве, библиотека автоматически вызывает действие intent 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) до 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():

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

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

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

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

Как работает перекодирование в инструменте выбора фотографий

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

Приложение предоставляет инструменту выбора фотографий свои возможности обработки медиаконтента. Для этого при запуске инструмента выбора фотографий с помощью библиотеки 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-видео

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