BookinglyTech News
Infraestructura

CameraX: un agente de código descubre que ImageAnalysis.targetRotation no se actualiza al girar el tablet

El bug se originó porque ImageAnalysis no cambiaba su targetRotation al girar el dispositivo 180°, y la solución requirió mapear correctamente la rotación del sensor.

2 min de lecturaDev.to0 vistas

El problema

Un escáner de códigos de barras en Android, basado en CameraX, mostraba la vista previa correctamente tras girar el tablet 180°, pero los fotogramas analizados llegaban invertidos. El error no se veía en la UI, solo en los frames que llegaban al ImageAnalysis. La raíz era que ImageAnalysis.targetRotation permanecía con la rotación previa.

La investigación con un agente de código

El agente de código automatizó la mayoría de los pasos: arrancó adb logcat, añadió instrumentación, ejecutó la prueba física y recogió los valores de estado. Los estados claves que se compararon fueron:

  • Configuration.orientation
  • displayRotation
  • Preview.targetRotation
  • ImageAnalysis.targetRotation
  • ImageProxy.rotationDegrees

Los logs mostraron que tras rotar el tablet, displayRotation cambió de 1 a 3, pero ImageAnalysis.targetRotation se quedó en 1. El agente concluyó que era necesario esperar a que previewView.display.rotation se actualizara antes de rebinding.

La solución

Se sustituyó la lógica de rebinding por una que actualiza directamente los targetRotation de Preview e ImageAnalysis cuando se detecta un cambio de orientación:

OrientationEventListener {
    val calculatedRotation = mapRotation(orientationDegrees)
    preview.targetRotation = calculatedRotation
    imageAnalysis.targetRotation = calculatedRotation
}

La función mapRotation convierte los grados del listener a los constantes Surface.ROTATION_*, con un mapeo especial: 45‑134° se convierten a ROTATION_270 en lugar de ROTATION_90.

Validación

Se repitió el experimento físico. Antes: displayRotation=1, previewTargetRotation=1, analysisTargetRotation=1. Después: displayRotation=3, previewTargetRotation=3, analysisTargetRotation=3, y imageRotation cambió de 0 a 180° sin necesidad de recrear los casos de uso.

Por qué importa

La corrección elimina la dependencia de postDelayed, unbindAll() y bindToLifecycle(), reduciendo latencia y complejidad. Además, muestra un patrón de depuración reproducible: identificar estados que deben coincidir, capturarlos, y repetir la prueba tras el cambio.

Próximos pasos

Aunque funciona en el dispositivo probado, la lógica de mapeo puede variar en otros tablets. Se recomienda documentar la transformación de grados a Surface.ROTATION_* y probar en múltiples modelos.

Repositorio con el agente de código y los scripts de prueba