Новости о продуктах

Не только отдельные функции: гарантированная работа комбинаций функций в CameraX 1.5

Время на чтение: 6 минут
Посмотреть профиль Тахсина Масрура
Tahsin Masrur Разработчик программного обеспечения

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

Но разработчики знают, что на самом деле все сложнее. Как гарантировать, что определенное устройство поддерживает заданную комбинацию? До сих пор включение нескольких функций часто было азартной игрой. Вы можете проверить поддержку отдельных функций, но их сочетание может привести к неопределенному поведению или, что ещё хуже, к сбою сеанса камеры. Из-за этого разработчики вынуждены действовать осторожно, и пользователи мощных устройств не могут получить максимум от игры.

Например, очень немногие устройства премиум-класса поддерживают HDR и видео с частотой 60 кадров в секунду одновременно. Поэтому в большинстве приложений не включают обе функции одновременно, чтобы не ухудшать работу на большинстве телефонов.

Чтобы решить эту проблему, мы представляем Feature Group в CameraX – новый API, который позволяет избежать догадок. Теперь вы можете узнать, поддерживается ли определенная комбинация функций, до настройки камеры или просто указать приоритеты в CameraX, чтобы включить наиболее подходящую комбинацию.

Для тех, кто только начинает работать с CameraX

Прежде чем перейти к новому Feature Group API, давайте вспомним, что такое CameraX. Это библиотека поддержки Jetpack, которая упрощает разработку приложений для камеры. Он предоставляет согласованный и простой в использовании API, который работает на большинстве устройств Android и обратно совместим с Android 6.0 (API уровня 23). Если вы не знакомы с CameraX, рекомендуем изучить официальную документацию и выполнить практическую работу.

Что можно создать с помощью Feature Group API

Вам больше не нужно гадать, какие функции будут работать вместе. Вы можете уверенно предлагать пользователям лучшие возможности камеры, например одновременную съемку в HDR и с частотой 60 кадров/с на поддерживаемом оборудовании (например, Pixel 10 Pro), и при этом избегать ошибок на устройствах, которые не поддерживают такую комбинацию.

unnamed.png
Pixel 10 Pro с включенными HDR и 60 FPS
unnamed (1).png
На старых устройствах, которые не поддерживают одновременное использование HDR и 60 кадров/с, будет включен только HDR.

С помощью Feature Group API вы можете:

  • Создавайте более умные и динамичные интерфейсы. Включайте или отключайте настройки в интерфейсе в зависимости от поддержки оборудования в реальном времени. Например, если пользователь включает HDR, вы можете сразу же сделать недоступным вариант "60 кадров/с", если устройство не поддерживает такую комбинацию. 
hdr.gif
  • Режим высокого качества.  Настройте камеру, выбрав нужные функции из списка. CameraX автоматически находит и включает оптимальную комбинацию для любого устройства, обеспечивая отличный результат без сложной логики, зависящей от устройства.
  • Предотвращение сбоев сеансов камеры. Проверяя поддержку заранее, вы предотвращаете попытки камеры настроить неподдерживаемую комбинацию, устраняя распространенный источник сбоев и обеспечивая удобство работы пользователей.

Принцип работы: основные компоненты

Новый API основан на ключевых дополнениях к SessionConfig и CameraInfo.

  1. GroupableFeature. API предлагает набор предопределенных группируемых функций, таких как HDR_HLG10, FPS_60, PREVIEW_STABILIZATION и IMAGE_ULTRA_HDR. Из-за вычислительных ограничений только определенный набор функций может быть сгруппирован с высокой степенью надежности, которую обеспечивает этот API. Мы активно работаем над расширением этого списка и добавим поддержку дополнительных функций в будущих выпусках.
  2. Новые параметры SessionConfig. Этот класс, используемый для запуска сеанса камеры, теперь принимает два новых параметра:
    • requiredFeatureGroup. Используйте это значение для функций, которые должны поддерживаться, чтобы конфигурация была успешной. Это идеальный вариант для функций, которые пользователь включает явным образом, например HDR. Чтобы обеспечить детерминированность и согласованность, вызов bindToLifecycle вызовет исключение IllegalArgumentException, если запрошенная комбинация не поддерживается, а не просто проигнорирует запрос на добавление функции. Чтобы заранее узнать результат, используйте API CameraInfo#isFeatureGroupSupported (подробности ниже).
    • preferredFeatureGroup – используйте для желательных, но необязательных функций, например для режима высокого качества по умолчанию. Вы предоставляете список нужных вам функций, упорядоченных по приоритету, и CameraX автоматически включает комбинацию с наивысшим приоритетом, которую поддерживает устройство.
  3. CameraInfo#isFeatureGroupSupported() – основной метод запроса, который позволяет проверить, поддерживается ли группа функций. Он подходит для того, чтобы показывать пользователям в интерфейсе приложения только поддерживаемые функции. Вы передаете ему SessionConfig, и он возвращает логическое значение, указывающее, поддерживается ли комбинация. Если вы хотите связать SessionConfig с обязательными функциями, сначала используйте этот API, чтобы убедиться, что он поддерживается. 

Реализация на практике

Давайте посмотрим, как использовать эти компоненты, чтобы улучшить работу камеры.

Сценарий 1. Режим высокого качества Best Effort

Если вы хотите включить по умолчанию лучшие функции, укажите их в списке приоритетов для preferredFeatureGroup. В этом примере мы указываем CameraX, что приоритет должен быть у HDR, затем у 60 кадров/с и, наконец, у стабилизации предварительного просмотра. CameraX проверяет все возможные комбинации и выбирает лучшую из поддерживаемых устройством.

Например, если устройство может обрабатывать HDR и 60 кадров в секунду вместе, но не со стабилизацией предварительного просмотра, CameraX включит первые два и отбросит третий. Это позволяет обеспечить наилучшее взаимодействие с пользователем без написания сложных проверок для конкретных устройств.

cameraProvider.bindToLifecycle(

    lifecycleOwner,

    cameraSelector,

    SessionConfig(

        useCases = listOf(preview, videoCapture),

        // The order of features in this list determines their priority. 

        // CameraX will enable the best-supported combination based on these

        // priorities: HDR_HLG10 > FPS_60 > Preview Stabilization.  

        preferredFeatureGroup =

           listOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION),

    ).apply {

        // (Optional) Get a callback with the enabled features

        // to update your UI. 

        setFeatureSelectionListener { selectedFeatures ->

            updateUiIndicators(selectedFeatures)

        }

    }

)

Для этого фрагмента кода CameraX попытается включить комбинации функций в следующем порядке приоритета, выбрав первую, которую устройство полностью поддерживает:

  1. HDR + 60 кадров/с + стабилизация предпросмотра
  2. HDR + 60 кадров/с
  3. HDR + стабилизация предпросмотра
  4. HDR
  5. 60 кадр/с и стабилизация при предпросмотре
  6. 60 кадров/с
  7. Стабилизация при предпросмотре
  8. Ни одна из перечисленных выше функций

Сценарий 2. Создание реактивного пользовательского интерфейса

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

/**

 * Returns a list of features that are NOT supported in combination

 * with the currently selected features.

 */

fun getUnsupportedFeatures(

    currentFeatures: Set<GroupableFeature>

): Set<GroupableFeature> {

    val unsupportedFeatures = mutableSetOf<GroupableFeature>()

    val appFeatureOptions = setOf(HDR_HLG10, FPS_60, PREVIEW_STABILIZATION)


    // Iterate over every available feature option in your app. 

    appFeatureOptions.forEach { featureOption ->

        // Skip features the user has already selected. 

        if (currentFeatures.contains(featureOption)) return@forEach


        // Check if adding this new feature is supported. 

        val isSupported = cameraInfo.isFeatureGroupSupported(

            SessionConfig(

                useCases = useCases,

                // Check the new feature on top of existing ones.

                requiredFeatureGroup = currentFeatures + featureOption

            )

        )


        if (!isSupported) {

            unsupportedFeatures.add(featureOption)

        }

    }


    return unsupportedFeatures

}

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

// Invoked when user turns some feature on/off.

fun onFeatureChange(currentFeatures: Set<GroupableFeature>) {

    // Identify features that are unsupported with the current selection.

    val unsupportedFeatures = getUnsupportedFeatures(currentFeatures)



    // Update app UI so that users can't enable them.

    updateDisabledFeatures(unsupportedFeatures)



    // Since the UI now only allows selecting supported feature combinations, 

    // `currentFeatures` is always valid. This allows setting

    // `requiredFeatureGroup` directly, without needing to re-check for

    // support or set a feature selection listener.  

    cameraProvider.bindToLifecycle(

        lifecycleOwner,

        cameraSelector,

        SessionConfig(

            useCases = listOf(preview, videoCapture),

            requiredFeatureGroup = currentFeatures,

        )

    )

}

Чтобы посмотреть, как эти концепции работают в приложении, изучите наше внутреннее тестовое приложение. В нем полностью реализованы оба сценария, описанные выше.

Обратите внимание, что это тестовое приложение, а не официально поддерживаемый пример. Хотя это отличный справочник по Feature Group API, он не был доработан для использования в рабочей среде.

Начните уже сегодня

Feature Group API устраняет неоднозначность при работе с расширенными возможностями камеры. Благодаря детерминированному способу запроса поддержки функций вы можете создавать более мощные и надежные приложения для камеры.

API доступен в экспериментальном режиме в CameraX 1.5 и должен стать полностью стабильным в выпуске 1.6, с дополнительной поддержкой и улучшениями.

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

Продолжить чтение