Novidades do produto

Além de recursos únicos: como garantir combinações de recursos com o CameraX 1.5

Leitura de 6 minutos
Tahsin Masrur
Engenheiro de software

Os apps de câmera modernos são definidos por recursos poderosos e sobrepostos. Os usuários esperam gravar vídeos com HDR incrível, capturar movimentos fluidos a 60 QPS e obter imagens suaves com a estabilização de visualização, muitas vezes tudo ao mesmo tempo.

Como desenvolvedores, sabemos que a realidade é mais complicada. Como garantir que um dispositivo específico realmente ofereça suporte a uma determinada combinação? Até agora, ativar vários recursos era muitas vezes uma aposta. Você podia verificar o suporte a recursos individuais, mas a combinação deles poderia levar a um comportamento indefinido ou, pior, a uma sessão de câmera com falha. Essa incerteza força os desenvolvedores a serem conservadores, o que impede que os usuários em dispositivos capazes acessem a melhor experiência possível.

Por exemplo, poucos dispositivos premium oferecem suporte confiável a vídeos em HDR e 60 QPS simultaneamente. Consequentemente, a maioria dos apps evita ativar os dois ao mesmo tempo para evitar uma experiência ruim do usuário na maioria dos smartphones.

Para resolver isso, estamos apresentando o grupo de recursos no CameraX , uma nova API projetada para eliminar essa adivinhação. Agora você pode consultar se uma combinação específica de recursos é compatível antes de configurar a câmera ou simplesmente informar suas prioridades ao CameraX e permitir que ele ative a combinação com melhor suporte para você.

Para quem não conhece o CameraX

Antes de nos aprofundarmos na nova API de grupo de recursos, vamos recapitular rapidamente o que é o CameraX. O CameraX é uma biblioteca de suporte do Jetpack criada para facilitar o desenvolvimento de apps de câmera. Ele fornece uma superfície de API consistente e fácil de usar que funciona na maioria dos dispositivos Android e é compatível com versões anteriores ao Android 6.0 (nível 23 da API). Se você não conhece o CameraX, recomendamos consultar a documentação oficial e testar o codelab para começar.

O que você pode criar com a API de grupo de recursos

Você não precisa mais apostar em combinações de recursos e pode oferecer com confiança as melhores experiências de câmera possíveis, como vídeo HDR e 60 QPS simultâneos em hardware capaz (por exemplo, um Pixel 10 Pro), evitando erros em dispositivos que não oferecem suporte à combinação.

unnamed.png

Pixel 10 Pro ativando HDR e 60 QPS simultaneamente

unnamed (1).png

Em um dispositivo mais antigo em que HDR e 60 QPS não podem ser executados simultaneamente, apenas o HDR é ativado, enquanto a opção de 60 QPS é desativada.

Com a API de grupo de recursos, você pode:

  • Criar IUs dinâmicas e mais inteligentes:ative ou desative configurações de forma inteligente na sua IU com base no suporte de hardware em tempo real. Por exemplo, se um usuário ativar o HDR, você poderá desativar instantaneamente a opção de 60 QPS se a combinação não for compatível com esse dispositivo. 
unsupported-features-disabled.gif
  • Oferecer um modo "Alta qualidade" confiável : configure a câmera com uma lista priorizada de recursos desejados. O CameraX encontra e ativa automaticamente a combinação com melhor suporte para qualquer dispositivo, garantindo um ótimo resultado sem lógica complexa e específica do dispositivo.
  • Evitar falhas na sessão da câmera:ao verificar o suporte com antecedência, você impede que a câmera tente configurar uma combinação não compatível, eliminando uma fonte comum de falhas e oferecendo uma experiência do usuário tranquila.

Como funciona: os principais componentes

A nova API é centrada em adições importantes ao SessionConfig e ao CameraInfo.

  1. GroupableFeature: essa API apresenta um conjunto de recursos agrupáveis predefinidos, como HDR_HLG10, FPS_60, PREVIEW_STABILIZATION e IMAGE_ULTRA_HDR. Devido a limitações computacionais, apenas um conjunto específico de recursos pode ser agrupado com o alto grau de confiabilidade que essa API oferece. Estamos trabalhando ativamente para expandir essa lista e vamos introduzir suporte a mais recursos em versões futuras.
     
  2. Novos parâmetros SessionConfig: essa classe, usada para iniciar uma sessão de câmera, agora aceita dois novos parâmetros:
    • requiredFeatureGroup: use esse parâmetro para recursos que precisam ser compatíveis para que a configuração seja bem-sucedida. Ele é ideal para recursos que um usuário ativa explicitamente, como alternar uma chave "HDR". Para garantir uma experiência determinística e consistente, a chamada bindToLifecycle vai gerar uma IllegalArgumentException se a combinação solicitada for indisponível, em vez de ignorar silenciosamente uma solicitação de recurso. A API CameraInfo#isFeatureGroupSupported (detalhes abaixo) precisa ser usada para consultar esse resultado com antecedência.
    • preferredFeatureGroup: use esse parâmetro para recursos desejáveis, mas opcionais, por exemplo, quando você quiser implementar um modo "Alta qualidade" padrão. Você fornece uma lista dos recursos desejados ordenados de acordo com suas prioridades, e o CameraX ativa automaticamente a combinação de maior prioridade que o dispositivo oferece suporte.
  3. CameraInfo#isFeatureGroupSupported(): esse é o método de consulta principal para verificar explicitamente se um grupo de recursos é compatível. Ele é adequado para fornecer apenas opções de recursos compatíveis aos usuários na interface do app. Você transmite um SessionConfig, e ele retorna um booleano indicando se a combinação é compatível. Se você pretende vincular um SessionConfig com recursos obrigatórios, use essa API primeiro para garantir que ela seja compatível. 

Implementação na prática

Vamos conferir como usar esses componentes para criar uma experiência de câmera melhor.

Cenário 1: modo de alta qualidade "melhor esforço"

Se você quiser ativar os melhores recursos possíveis por padrão, forneça uma lista priorizada para preferredFeatureGroup. Neste exemplo, informamos ao CameraX para priorizar o HDR, depois 60 QPS e, por fim, a estabilização de visualização. O CameraX lida com a complexidade de verificar todas as combinações possíveis e escolher a melhor que o dispositivo oferece suporte.

Por exemplo, se um dispositivo puder processar HDR e 60 QPS juntos, mas não com a estabilização de visualização, o CameraX vai ativar os dois primeiros e descartar o terceiro. Dessa forma, você tem a melhor experiência possível sem escrever verificações complexas e específicas do dispositivo.

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)

        }

    }

)

Para esse snippet de código, o CameraX vai tentar ativar combinações de recursos na seguinte ordem de prioridade, selecionando a primeira que o dispositivo oferece suporte total:

  1. HDR + 60 QPS + estabilização de visualização
  2. HDR + 60 QPS
  3. HDR + estabilização de visualização
  4. HDR
  5. 60 QPS + estabilização de visualização
  6. 60 QPS
  7. Estabilização de visualização
  8. Nenhum dos recursos acima

Cenário 2: criar uma IU reativa

Para criar uma IU que responda às seleções do usuário e impeça que os usuários selecionem uma combinação de recursos não compatível, você pode consultar o suporte diretamente. A função abaixo verifica quais recursos são incompatíveis com as seleções atuais do usuário, permitindo que você desative os elementos de IU correspondentes.

/**

 * 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

}

Em seguida, você pode conectar essa lógica ao ViewModel ou ao controlador de IU para reagir à entrada do usuário e vincular novamente a câmera com uma configuração garantida.

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

        )

    )

}

Para conferir esses conceitos em um aplicativo funcional, você pode explorar nosso app de teste interno. Ele oferece uma implementação completa dos cenários de "melhor esforço" e "IU reativa" discutidos acima.

Observação: esse é um aplicativo de teste e não um exemplo com suporte oficial. Embora seja uma ótima referência para a API de grupo de recursos, ela não foi refinada para uso em produção.

Começar hoje mesmo

A API de grupo de recursos remove a ambiguidade de trabalhar com recursos avançados de câmera. Ao fornecer uma maneira determinística de consultar o suporte a recursos, você pode criar apps de câmera mais poderosos e confiáveis com confiança.

A API está disponível como experimental no CameraX 1.5 e está programada para se tornar totalmente estável na versão 1.6, com mais suporte e melhorias a caminho.

Para saber mais, consulte a documentação oficial. Não vemos a hora de descobrir o que você vai criar e esperamos seu feedback. Compartilhe suas ideias e informe problemas pelos seguintes canais:

Escrito por:

Continuar lendo