Más allá de las funciones individuales: Garantiza combinaciones de funciones con CameraX 1.5
Lectura de 6 min
Las apps de cámara modernas se definen por funciones potentes que se superponen. Los usuarios esperan grabar videos con un HDR impresionante, capturar movimientos fluidos a 60 FPS y obtener videos fluidos con la estabilización de la vista previa, a menudo todo al mismo tiempo.
Como desarrolladores, sabemos que la realidad es más compleja. ¿Cómo puedes garantizar que un dispositivo específico realmente admita una combinación determinada? Hasta ahora, habilitar varias funciones solía ser una apuesta. Podrías verificar la compatibilidad de las funciones individuales, pero combinarlas podría generar un comportamiento indefinido o, lo que es peor, una sesión de cámara fallida. Esta incertidumbre obliga a los desarrolladores a ser conservadores, lo que impide que los usuarios de dispositivos compatibles accedan a la mejor experiencia posible.
Por ejemplo, muy pocos dispositivos premium admiten de forma confiable videos en HDR y 60 FPS de forma simultánea. Por lo tanto, la mayoría de las apps evitan habilitar ambas opciones a la vez para impedir una experiencia del usuario deficiente en la mayoría de los teléfonos.
Para solucionar este problema, presentamos Feature Group en CameraX, una nueva API diseñada para eliminar estas conjeturas. Ahora puedes consultar si se admite una combinación específica de funciones antes de configurar la cámara o, simplemente, indicarle a CameraX tus prioridades y dejar que habilite la combinación más compatible para ti.
Para quienes no conocen CameraX
Antes de profundizar en la nueva API de Feature Group, repasemos brevemente qué es CameraX. CameraX es una biblioteca de compatibilidad de Jetpack creada para que el desarrollo de una app de cámara te resulte más fácil. Proporciona una plataforma de API coherente y fácil de usar que funciona en la mayoría de los dispositivos Android y ofrece retrocompatibilidad con Android 6.0 (nivel de API 23). Si es la primera vez que usas CameraX, te recomendamos que consultes la documentación oficial y pruebes el codelab para comenzar.
Qué puedes compilar con la API de Feature Group
Ya no necesitas probar combinaciones de funciones y puedes ofrecer con confianza las mejores experiencias de cámara posibles, como HDR simultáneo y video de 60 FPS en hardware compatible (p.ej., un Pixel 10 Pro), mientras evitas errores en dispositivos que no admiten la combinación.
Con la API de Feature Group, puedes hacer lo siguiente:
- Crea IU más inteligentes y dinámicas: Habilita o inhabilita de forma inteligente los parámetros de configuración de tu IU según la compatibilidad de hardware en tiempo real. Por ejemplo, si un usuario habilita el HDR, puedes inhabilitar de inmediato la opción de 60 FPS y mostrarla en gris si la combinación no es compatible con ese dispositivo.
- Ofrece un modo de "alta calidad" confiable: Configura la cámara con una lista priorizada de las funciones deseadas. CameraX busca y habilita automáticamente la combinación más compatible para cualquier dispositivo, lo que garantiza un resultado excelente sin una lógica compleja específica del dispositivo.
- Evita fallas en la sesión de la cámara: Si verificas la compatibilidad de antemano, evitas que la cámara intente configurar una combinación no compatible, lo que elimina una fuente común de fallas y ofrece una experiencia del usuario fluida.
Cómo funciona: Los componentes principales
La nueva API se centra en las adiciones clave a SessionConfig y CameraInfo.
- GroupableFeature: Esta API presenta un conjunto de funciones agrupables predefinidas, como HDR_HLG10, FPS_60, PREVIEW_STABILIZATION y IMAGE_ULTRA_HDR. Debido a las limitaciones de procesamiento, solo se puede agrupar un conjunto específico de funciones con el alto grado de confiabilidad que proporciona esta API. Estamos trabajando activamente para ampliar esta lista y, en versiones futuras, agregaremos compatibilidad con más funciones.
- Nuevos parámetros de SessionConfig: Esta clase, que se usa para iniciar una sesión de cámara, ahora acepta dos parámetros nuevos:
requiredFeatureGroup: Usa este valor para las funciones que deben admitirse para que la configuración se realice correctamente. Es ideal para las funciones que un usuario habilita de forma explícita, como activar un interruptor de "HDR". Para garantizar una experiencia determinística y coherente, la llamada abindToLifecyclearrojará unaIllegalArgumentExceptionsi no se admite la combinación solicitada, en lugar de ignorar de forma silenciosa una solicitud de función. Se debe usar la API deCameraInfo#isFeatureGroupSupported(detalles a continuación) para consultar este resultado de antemano.preferredFeatureGroup: Usa esta opción para las funciones que son deseables, pero opcionales, por ejemplo, cuando quieras implementar un modo predeterminado de "alta calidad". Proporcionas una lista de las funciones que deseas ordenadas según tus prioridades, y CameraX habilita automáticamente la combinación de mayor prioridad que admite el dispositivo.
- CameraInfo#isFeatureGroupSupported(): Este es el método de consulta principal para verificar de forma explícita si se admite un grupo de funciones, lo que es ideal para proporcionar solo opciones de funciones compatibles a los usuarios en la IU de tu app. Le pasas un
SessionConfigy devuelve un valor booleano que indica si se admite la combinación. Si quieres vincular unSessionConfigcon funciones obligatorias, primero debes usar esta API para asegurarte de que sea compatible.
Implementación en la práctica
Veamos cómo usar estos componentes para crear una mejor experiencia de cámara.
Situación 1: Modo de alta calidad "Mejor esfuerzo"
Si quieres habilitar las mejores funciones posibles de forma predeterminada, puedes proporcionar una lista priorizada a preferredFeatureGroup. En este ejemplo, le indicamos a CameraX que priorice el HDR, luego los 60 FPS y, por último, la estabilización de la vista previa. CameraX se encarga de la complejidad de verificar todas las combinaciones posibles y elegir la mejor que admita el dispositivo.
Por ejemplo, si un dispositivo puede controlar HDR y 60 FPS juntos, pero no con la estabilización de la vista previa, CameraX habilitará los dos primeros y descartará el tercero. De esta manera, obtendrás la mejor experiencia posible sin escribir verificaciones complejas específicas del 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)
}
}
)En este fragmento de código, CameraX intentará habilitar las combinaciones de funciones en el siguiente orden de prioridad y seleccionará la primera que el dispositivo admita por completo:
- HDR + 60 FPS + Estabilización de vista previa
- HDR + 60 FPS
- HDR y estabilización de la vista previa
- HDR
- 60 FPS y estabilización de la vista previa
- 60 FPS
- Estabilización de versión preliminar
- Ninguna de las funciones anteriores
Situación 2: Compila una IU reactiva
Para crear una IU que responda a las selecciones de los usuarios y evite que seleccionen una combinación de funciones no admitida, puedes consultar la compatibilidad directamente. La siguiente función verifica qué funciones son incompatibles con las selecciones actuales del usuario, lo que te permite inhabilitar los elementos de la IU correspondientes.
/**
* 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
}Luego, puedes conectar esta lógica a tu ViewModel o controlador de IU para reaccionar a la entrada del usuario y volver a vincular la cámara con una configuración que funcione de forma garantizada.
// 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 ver estos conceptos en una aplicación en funcionamiento, puedes explorar nuestra app de pruebas interna, que proporciona una implementación completa de las situaciones de "mejor esfuerzo" y "IU reactiva" que se mencionaron anteriormente.
Ten en cuenta que esta es una aplicación de prueba y no un ejemplo compatible de forma oficial. Si bien es una excelente referencia para la API de Feature Group, no se perfeccionó para su uso en producción.
Comienza hoy mismo
La API de Feature Group quita la ambigüedad de trabajar con funciones avanzadas de la cámara. Si proporcionas una forma determinística de consultar la compatibilidad con funciones, puedes compilar apps de cámara más potentes y confiables con confianza.
La API está disponible como experimental en CameraX 1.5 y se espera que sea completamente estable en la versión 1.6, con más compatibilidad y mejoras en camino.
Para obtener más información, consulta la documentación oficial. Tenemos muchas ganas de ver tus creaciones y esperamos tus comentarios. Comparte tus opiniones y, si tienes algún problema, infórmalo a través de los siguientes canales:
-
Novedades de productosLas apps que se orienten a la próxima versión de Android ya no podrán escribir directamente en los contactos con el permiso WRITE_CONTACTS.
Roxanna Aliabadi Walker • Lectura de 6 min -
Novedades de productosA medida que se acelera el desarrollo basado en agentes, la ingeniería de Android alcanza una nueva y emocionante frontera: pasar de la finalización de código asistida a agentes que ejecutan tareas de extremo a extremo bajo tu dirección. Tienes total libertad y flexibilidad para elegir los modelos y agentes que usas.
Jason Buchel • Lectura de 3 min -
Novedades de productosHoy, compartimos cómo estamos llevando nuestra visión de “más que una tienda” al siguiente nivel. Desde la pestaña Tú, que ahora es la base personal de más de 250 millones de usuarios activos por mes, hasta nuestra plataforma de juegos unificada que conecta a más de 700 millones de perfiles de gamer, Google Play llega a los usuarios dondequiera que estén.
Paul Feng • Lectura de 3 min
Recibe la información más reciente sobre el desarrollo de Android en tu bandeja de entrada todas las semanas.