Vista previa de cámara

Nota: Esta página hace referencia al paquete Camera2. A menos que la app requiera funciones específicas y de bajo nivel de Camera2, te recomendamos que uses CameraX. CameraX y Camera2 admiten Android 5.0 (nivel de API 21) y versiones posteriores.

En Android, las cámaras y las vistas previas no siempre están en la misma orientación. dispositivos.

Una cámara se encuentra en una posición fija en un dispositivo, sin importar si este es un teléfono, una tablet o una computadora. Cuando cambia la orientación del dispositivo, el que cambie la orientación de la cámara.

Como resultado, las apps de cámara generalmente suponen una relación fija entre la orientación del dispositivo y la relación de aspecto de la vista previa de la cámara. Cuando un elemento el teléfono está en orientación vertical, se supone que la vista previa de la cámara es más alta que su ancho. Cuando el teléfono (y la cámara) se rotan a la posición horizontal, el Se espera que la vista previa de la cámara sea más ancha que alta.

Pero estas suposiciones se enfrentan a nuevos factores de forma, como dispositivos plegables dispositivos y modos de visualización. como, por ejemplo, multiventana y pantallas múltiples. Los dispositivos plegables cambian el tamaño de la pantalla y la relación de aspecto sin cambiar orientación. El modo multiventana restringe las apps de cámara a una parte de la y ajustar la vista previa de la cámara, independientemente de la orientación del dispositivo. El modo de varias pantallas permite el uso de pantallas secundarias que podrían no tener estar en la misma orientación que la pantalla principal.

Orientación de la cámara

El Definición de compatibilidad de Android especifica que un sensor de imagen de la cámara "SE DEBE orientar para que la longitud de la cámara se alinee con la dimensión larga de la pantalla. Es decir, cuando el dispositivo se mantiene en orientación horizontal, las cámaras DEBEN capturar imágenes en la orientación horizontal. Esto se aplica independientemente de la naturaleza orientación; es decir, se aplica a los dispositivos principales horizontales y a los principales dispositivos principales verticales".

La disposición de cámara a pantalla maximiza el área de visualización de la cámara visor en una app de cámara. Además, los sensores de imagen suelen generar sus datos relaciones de aspecto horizontales, 4:3 es la más común.

Sensor del teléfono y de la cámara en orientación vertical.
Figura 1: Relación típica del teléfono y el sensor de la cámara orientación.

La orientación natural del sensor de la cámara es horizontal. En la figura 1, el sensor de la cámara frontal (la cámara apunta en la misma dirección que el pantalla) se rote 270 grados con relación al teléfono para cumplir con la Definición de compatibilidad de Android.

Para exponer la rotación del sensor a las apps, el La API de camera2 incluye una SENSOR_ORIENTATION constante. En la mayoría de los teléfonos y tablets, el dispositivo informa la orientación de un sensor. de 270 grados para las cámaras frontales y de 90 grados (punto de vista desde la parte posterior del dispositivo) para las cámaras traseras, que alinea el borde largo de la con el borde largo del dispositivo. Las cámaras de las laptops suelen informar orientación del sensor de 0 o 180 grados.

Debido a que los sensores de imagen de la cámara generan datos (un búfer de imagen) en la en la orientación natural del sensor (horizontal), el búfer de imagen se debe rotar la cantidad de grados especificados por SENSOR_ORIENTATION para la vista previa de la cámara en aparezcan en posición vertical en la orientación natural del dispositivo. En el caso de las cámaras frontales, la rotación es en el sentido contrario a las manecillas del reloj; para las cámaras posteriores, en el sentido de las manecillas del reloj.

Por ejemplo, para la cámara frontal de la figura 1, el búfer de imagen que produce el sensor de la cámara se ve de la siguiente manera:

Se rotó el sensor de la cámara a la orientación horizontal con la imagen
            hacia un lado, en la parte superior izquierda.

La imagen se debe girar 270 grados a la izquierda para que la vista previa la orientación coincide con la del dispositivo:

Sensor de la cámara en orientación vertical con imagen en posición vertical.

Una cámara posterior produciría un búfer de imagen con la misma orientación. que el búfer anterior, pero SENSOR_ORIENTATION es de 90 grados. Como resultado, el se rota 90 grados en el sentido de las manecillas del reloj.

Rotación del dispositivo

La rotación del dispositivo es la cantidad de grados en los que se rota un dispositivo respecto de su rotación natural orientación. Por ejemplo, un teléfono en orientación horizontal tiene un dispositivo de 90 o 270 grados, según la dirección de rotación.

Un búfer de imagen del sensor de la cámara se debe rotar la misma cantidad de grados que el de rotación del dispositivo (además de los grados de orientación del sensor) para la que la vista previa de la cámara se vea en posición vertical.

Cálculo de orientación

La orientación correcta de la vista previa de la cámara tiene en cuenta el sensor. y la rotación del dispositivo.

La rotación general del búfer de imagen del sensor se puede calcular con el siguiente fórmula:

rotation = (sensorOrientationDegrees - deviceOrientationDegrees * sign + 360) % 360

donde sign es 1 para las cámaras frontales y -1 para las cámaras posteriores.

Para las cámaras frontales, el búfer de imagen se rota en sentido contrario a las manecillas del reloj (desde la orientación natural del sensor). Para las cámaras posteriores, el sensor el búfer de imagen se rota en el sentido de las manecillas del reloj.

La expresión deviceOrientationDegrees * sign + 360 convierte la rotación del dispositivo. de las manecillas del reloj a las agujas del reloj para las cámaras traseras (por ejemplo, convirtiendo 270 grados en sentido antihorario a 90 grados en el sentido de las manecillas del reloj). El módulo escala el resultado a menos de 360 grados (por ejemplo, escala 540) grados de rotación a 180).

Las diferentes APIs informan la rotación de dispositivos de manera diferente:

  • Display#getRotation() Proporciona la rotación del dispositivo en el sentido contrario a las manecillas del reloj (desde el punto del usuario visual). Este valor se agrega a la fórmula anterior tal como está.
  • OrientationEventListener#onOrientationChanged() muestra la rotación en el sentido de las manecillas del reloj del dispositivo (desde el punto de vista del usuario). Negar el valor que se usará en la fórmula anterior

Cámaras frontales

Vista previa de la cámara y sensor en orientación horizontal y sensor
            está bien.
Figura 2: Vista previa de la cámara y sensor con el teléfono girado a 90 grados para con orientación horizontal.

En la figura 2, se muestra el búfer de imagen producido por el sensor de la cámara:

Sensor de la cámara en orientación horizontal con imagen en posición vertical.

El búfer se debe girar 270 grados en sentido antihorario para ajustarse al sensor. orientación (consulta Orientación de la cámara más arriba):

Se rotó el sensor de la cámara a la orientación de retrato con la imagen girada,
            en la parte superior derecha.

Luego, el búfer se rota 90 grados adicionales en sentido antihorario para tienen en cuenta la rotación del dispositivo, lo que da como resultado la orientación correcta de la vista previa de la cámara en la figura 2:

Se rotó el sensor de la cámara a la orientación horizontal con la imagen
            en posición vertical.

Aquí está la cámara girada hacia la derecha en orientación horizontal:

La vista previa de la cámara y el sensor están en orientación horizontal, pero
            que el sensor esté invertido.
Figura 3: Vista previa de la cámara y sensor con el teléfono girado a 270 grados (o -90 grados) a la orientación horizontal.

Este es el búfer de imagen:

Se rotó el sensor de la cámara a la orientación horizontal con la imagen invertida
            fuera de servicio.

El búfer se debe rotar 270 grados en sentido antihorario para ajustarse al sensor orientación:

Sensor de cámara clasificado para orientación vertical con imagen girada,
            en la parte superior izquierda.

Luego, el búfer se rota otros 270 grados en sentido antihorario para tener en cuenta la rotación del dispositivo:

Se rotó el sensor de la cámara a la orientación horizontal con la imagen
            en posición vertical.

Cámaras posteriores

Las cámaras traseras generalmente tienen una orientación de sensor de 90 grados (como se ve desde la parte posterior del dispositivo). Cuando se orienta la vista previa de la cámara, el el búfer de imagen del sensor se rota en el sentido de las manecillas del reloj según la rotación del sensor (en lugar de en el sentido contrario a las manecillas del reloj, como las cámaras frontales) y, luego, la imagen el búfer se rota en sentido contrario a las manecillas del reloj según la rotación del dispositivo.

La vista previa de la cámara y el sensor están en orientación horizontal, pero
            que el sensor esté invertido.
Figura 4: Teléfono con cámara posterior en orientación horizontal (girado a 270 o -90 grados).

En la figura 4, se muestra el búfer de imagen del sensor de la cámara:

Se rotó el sensor de la cámara a la orientación horizontal con la imagen invertida
            fuera de servicio.

El búfer se debe rotar 90 grados en el sentido de las manecillas del reloj para ajustarse al sensor orientación:

Sensor de cámara clasificado para orientación vertical con imagen girada,
            en la parte superior izquierda.

Luego, el búfer se rota 270 grados en sentido contrario a las manecillas del reloj para tener en cuenta el dispositivo. rotación:

Se rotó el sensor de la cámara a la orientación horizontal con la imagen
            en posición vertical.

Relación de aspecto

La relación de aspecto de la pantalla cambia cuando cambia la orientación del dispositivo, pero también cuando Los dispositivos plegables se pliegan y se despliegan cuando se cambia el tamaño de las ventanas en el modo multiventana y cuando las apps se abren en pantallas secundarias.

El búfer de imagen del sensor de la cámara se debe orientar y ajustar para que coincida con la orientación y relación de aspecto del elemento de la IU del visor como la IU Cambia la orientación de forma dinámica, con o sin que el dispositivo cambie. orientación.

En factores de forma nuevos o en entornos multiventana o de varias pantallas, si tu app asume que la vista previa de la cámara tiene la misma orientación que la del dispositivo (horizontal o vertical), es posible que la vista previa esté orientada o ajustada de forma incorrecta incorrectamente o ambas.

Dispositivo plegable desplegado con la vista previa de la cámara vertical activada
            giran.
Figura 5: Transiciones de dispositivos plegables de vertical a horizontal relación de aspecto, pero el sensor de la cámara permanece en orientación vertical.

En la figura 5, la aplicación supone erróneamente que el dispositivo se rotó 90 grados en el sentido contrario a las manecillas del reloj; Por lo tanto, la app giró la vista previa del mismo modo.

Dispositivo plegable desplegado con la vista previa de la cámara en posición vertical, pero aplastado
            debido al escalamiento incorrecto.
Figura 6: Transiciones de dispositivos plegables de vertical a horizontal relación de aspecto, pero el sensor de la cámara permanece en orientación vertical.

En la figura 6, la app no ajustó la relación de aspecto del búfer de imagen a permitir que se ajuste correctamente a las nuevas dimensiones de la IU de vista previa de la cámara .

Las apps de cámaras con orientación fija suelen experimentar problemas en dispositivos plegables y otros dispositivos con pantalla grande, como laptops,

La vista previa de la cámara de la laptop es vertical, pero la IU de la app está girada.
Figura 7: App vertical con orientación fija en una laptop

En la figura 7, la IU de la app de cámara es lateral porque la orientación de la app está restringido al modo vertical. La imagen del visor está orientada correctamente en relación con el sensor de la cámara.

Modo vertical insertado

Apps de cámara que no admiten el modo multiventana (resizeableActivity="false") y restringir su orientación (screenOrientation="portrait") o screenOrientation="landscape") se puede colocar en modo vertical insertado en dispositivos con pantalla grande para orientar correctamente la vista previa de la cámara.

Inserciones en formato letterbox (inserciones) en modo vertical para apps solo con orientación vertical en orientación vertical orientación, aunque la relación de aspecto de la pantalla sea horizontal. Las apps que solo funcionan con formato horizontal tienen formato letterbox en orientación horizontal aunque la relación de aspecto de la pantalla sea vertical. Se rota la imagen de la cámara para alinearla con la IU de la app, recortada para que coincida con la relación de aspecto de la vista previa de la cámara y, luego, ajustarlo para llenar la vista previa.

El modo Retrato insertado se activa cuando la relación de aspecto de la imagen de la cámara y la relación de aspecto de la actividad principal de la aplicación no coinciden.

Vista previa de la cámara e IU de la app en orientación vertical adecuada en una laptop.
            La imagen de vista previa ancha se ajusta y se recorta para ajustarse al modo vertical
            orientación.
Figura 8: App vertical con orientación fija en modo vertical con inserción activado en una laptop.

En la figura 8, se rotó la app de cámara solo con orientación vertical para mostrar la IU. en posición vertical en la pantalla de la laptop. La app tiene formato letterbox debido a la diferencia en la relación de aspecto entre la app vertical y la pantalla horizontal. La cámara se rotó la imagen de vista previa para compensar la rotación de la IU de la app (debido a modo vertical de inserción), y la imagen se recortó y se ajustó para adaptarla al con orientación vertical, lo que reduce el campo visual.

Rotar, recortar, ajustar

Se invoca el modo vertical de inserción para una app de cámara solo con modo vertical en una pantalla. que tiene una relación de aspecto horizontal:

La vista previa de la cámara de la laptop es vertical, pero la IU de la app está girada.
Figura 9: App vertical con orientación fija en una laptop

La app tiene formato letterbox en orientación vertical:

Se rotó la app a la orientación vertical y al formato letterbox. La imagen es
            de lado, de arriba a la derecha.

La imagen de la cámara se rota 90 grados para ajustarse a la reorientación de la app:

La imagen del sensor se rotó 90 grados para que quede vertical.

La imagen se recorta según la relación de aspecto de la vista previa de la cámara y, luego, se ajusta a rellenar la vista previa (se reduce el campo visual):

Se recortó la imagen de la cámara para llenar la vista previa.

En dispositivos plegables, la orientación del sensor de la cámara puede ser vertical. mientras que la relación de aspecto de la pantalla es horizontal:

La vista previa de la cámara y la IU de la app están giradas hacia un lado de la pantalla ancha y desplegada.
Figura 10: Dispositivo desplegado con la app de cámara solo vertical y diferentes relaciones de aspecto del sensor de la cámara y la pantalla.

Debido a que la vista previa de la cámara se rota para ajustarse a la orientación del sensor, la imagen esté orientada correctamente en el visor, pero la app está de lado.

El modo vertical para inserción solo necesita aplicar formato letterbox a la app en orientación vertical. para orientar correctamente la app y la vista previa de la cámara:

App en formato letterbox en orientación de retrato con vista previa de la cámara
            en posición vertical en un dispositivo plegable.

API

A partir de Android 12 (nivel de API 31), las apps también pueden controlar de forma explícita la inserción vertical mediante el SCALER_ROTATE_AND_CROP propiedad de CaptureRequest clase.

El valor predeterminado es SCALER_ROTATE_AND_CROP_AUTO: que le permite al sistema invocar el modo vertical con inserción. SCALER_ROTATE_AND_CROP_90 es el comportamiento del modo vertical insertado como se describió anteriormente.

No todos los dispositivos admiten todos los valores SCALER_ROTATE_AND_CROP. Cómo obtener una lista de valores admitidos, los valores de referencia CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES

CameraX

La biblioteca de Jetpack CameraX permite crear un visor de cámara que se adapta a la orientación de los sensores y rotación del dispositivo es una tarea sencilla.

El elemento de diseño PreviewView crea una vista previa de la cámara y se ajusta automáticamente según la orientación del sensor. la rotación y el escalamiento del dispositivo. PreviewView mantiene la relación de aspecto de la imagen de la cámara aplicando el FILL_CENTER tipo de escala, que centra la imagen, pero podría recortarla para que coincida con las dimensiones de la PreviewView. Para aplicar formato letterbox a la imagen de la cámara, establece el tipo de escala en FIT_CENTER

Para aprender los conceptos básicos de la creación de una vista previa de la cámara con PreviewView, consulta Implementa una vista previa.

Para ver una implementación de muestra completa, consulta la CameraXBasic en un repositorio de GitHub.

Visor de la cámara

Al igual que en el caso de uso de Preview, el CameraViewfinder proporciona un conjunto de herramientas para simplificar la creación de una vista previa de la cámara. No depende de CameraX Core, por lo que puedes integrarlo sin problemas en tu base de código de Camera2 existente.

En lugar de usar Surface directamente, puedes usar el CameraViewfinder para mostrar el feed de la cámara de Camera2.

CameraViewfinder usa de forma interna un TextureView o un SurfaceView. para mostrar el feed de la cámara y aplica las transformaciones requeridas a ellas mostrar correctamente el visor. Esto implica corregir su relación de aspecto, escala y rotación.

Para solicitar la superficie del objeto CameraViewfinder, debes hacer lo siguiente: crea un ViewfinderSurfaceRequest.

Esta solicitud contiene requisitos para la resolución de superficie y el dispositivo de cámara información de CameraCharacteristics.

Llamando a requestSurfaceAsync() envía la solicitud al proveedor de superficie, que es un TextureView o SurfaceView y obtiene un ListenableFuture de Surface.

Llamando a markSurfaceSafeToRelease() notifica al proveedor de superficies que la superficie no es necesaria y está relacionada se pueden liberar recursos.

Kotlin


fun startCamera(){
    val previewResolution = Size(width, height)
    val viewfinderSurfaceRequest =
        ViewfinderSurfaceRequest(previewResolution, characteristics)
    val surfaceListenableFuture =
        cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest)

    Futures.addCallback(surfaceListenableFuture, object : FutureCallback<Surface> {
        override fun onSuccess(surface: Surface) {
            /* create a CaptureSession using this surface as usual */
        }
        override fun onFailure(t: Throwable) { /* something went wrong */}
    }, ContextCompat.getMainExecutor(context))
}

Java


    void startCamera(){
        Size previewResolution = new Size(width, height);
        ViewfinderSurfaceRequest viewfinderSurfaceRequest =
                new ViewfinderSurfaceRequest(previewResolution, characteristics);
        ListenableFuture<Surface> surfaceListenableFuture =
                cameraViewfinder.requestSurfaceAsync(viewfinderSurfaceRequest);

        Futures.addCallback(surfaceListenableFuture, new FutureCallback<Surface>() {
            @Override
            public void onSuccess(Surface result) {
                /* create a CaptureSession using this surface as usual */
            }
            @Override public void onFailure(Throwable t) { /* something went wrong */}
        },  ContextCompat.getMainExecutor(context));
    }

SurfaceView

SurfaceView es un enfoque directo para crear una vista previa de la cámara si esta no requieren procesamiento y no están animadas.

SurfaceView rota automáticamente el búfer de imagen del sensor de la cámara para que coincida. la orientación de la pantalla, teniendo en cuenta tanto la orientación del sensor como la y la rotación de claves. Sin embargo, el búfer de imagen se ajusta para adaptarse a SurfaceView dimensiones sin considerar la relación de aspecto.

Debes asegurarte de que la relación de aspecto del búfer de imagen coincida con el proporción de SurfaceView, que puedes lograr escalando el contenido de SurfaceView en el archivo onMeasure() método:

(El código fuente computeRelativeRotation() está en Rotación relativa a continuación).

Kotlin

override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
    val width = MeasureSpec.getSize(widthMeasureSpec)
    val height = MeasureSpec.getSize(heightMeasureSpec)

    val relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees)

    if (previewWidth > 0f && previewHeight > 0f) {
        /* Scale factor required to scale the preview to its original size on the x-axis. */
        val scaleX =
            if (relativeRotation % 180 == 0) {
                width.toFloat() / previewWidth
            } else {
                width.toFloat() / previewHeight
            }
        /* Scale factor required to scale the preview to its original size on the y-axis. */
        val scaleY =
            if (relativeRotation % 180 == 0) {
                height.toFloat() / previewHeight
            } else {
                height.toFloat() / previewWidth
            }

        /* Scale factor required to fit the preview to the SurfaceView size. */
        val finalScale = min(scaleX, scaleY)

        setScaleX(1 / scaleX * finalScale)
        setScaleY(1 / scaleY * finalScale)
    }
    setMeasuredDimension(width, height)
}

Java

@Override
void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int width = MeasureSpec.getSize(widthMeasureSpec);
    int height = MeasureSpec.getSize(heightMeasureSpec);

    int relativeRotation = computeRelativeRotation(characteristics, surfaceRotationDegrees);

    if (previewWidth > 0f && previewHeight > 0f) {

        /* Scale factor required to scale the preview to its original size on the x-axis. */
        float scaleX = (relativeRotation % 180 == 0)
                       ? (float) width / previewWidth
                       : (float) width / previewHeight;

        /* Scale factor required to scale the preview to its original size on the y-axis. */
        float scaleY = (relativeRotation % 180 == 0)
                       ? (float) height / previewHeight
                       : (float) height / previewWidth;

        /* Scale factor required to fit the preview to the SurfaceView size. */
        float finalScale = Math.min(scaleX, scaleY);

        setScaleX(1 / scaleX * finalScale);
        setScaleY(1 / scaleY * finalScale);
    }
    setMeasuredDimension(width, height);
}

Para obtener más detalles sobre cómo implementar SurfaceView como vista previa de la cámara, consulta Orientaciones de la cámara:

Vista de textura

TextureView tiene un rendimiento menor que SurfaceView, y más trabajo, pero TextureView le brinda el máximo control de la vista previa de la cámara.

TextureView rota el búfer de imagen del sensor según la orientación del sensor, pero No controla la rotación del dispositivo ni el escalamiento de la vista previa.

El escalamiento y la rotación se pueden codificar Transformación de Matrix. Para aprender a hacer lo siguiente: escalar y rotar correctamente un TextureView, consulta Cómo brindar compatibilidad con superficies redimensionables en tu app de cámara

Rotación relativa

La rotación relativa del sensor de la cámara es la cantidad de rotación necesaria para alinea la salida del sensor de la cámara con la orientación del dispositivo.

Componentes como SurfaceView y TextureView usan la rotación relativa para determinar los factores de escala x e y para la imagen de vista previa. También se usa para especifica la rotación del búfer de imagen del sensor.

El CameraCharacteristics y Las clases Surface permiten el cálculo de la rotación relativa del sensor de la cámara:

Kotlin

/**
 * Computes rotation required to transform the camera sensor output orientation to the
 * device's current orientation in degrees.
 *
 * @param characteristics The CameraCharacteristics to query for the sensor orientation.
 * @param surfaceRotationDegrees The current device orientation as a Surface constant.
 * @return Relative rotation of the camera sensor output.
 */
public fun computeRelativeRotation(
    characteristics: CameraCharacteristics,
    surfaceRotationDegrees: Int
): Int {
    val sensorOrientationDegrees =
        characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!!

    // Reverse device orientation for back-facing cameras.
    val sign = if (characteristics.get(CameraCharacteristics.LENS_FACING) ==
        CameraCharacteristics.LENS_FACING_FRONT
    ) 1 else -1

    // Calculate desired orientation relative to camera orientation to make
    // the image upright relative to the device orientation.
    return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360
}

Java

/**
 * Computes rotation required to transform the camera sensor output orientation to the
 * device's current orientation in degrees.
 *
 * @param characteristics The CameraCharacteristics to query for the sensor orientation.
 * @param surfaceRotationDegrees The current device orientation as a Surface constant.
 * @return Relative rotation of the camera sensor output.
 */
public int computeRelativeRotation(
    CameraCharacteristics characteristics,
    int surfaceRotationDegrees
){
    Integer sensorOrientationDegrees =
        characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

    // Reverse device orientation for back-facing cameras.
    int sign = characteristics.get(CameraCharacteristics.LENS_FACING) ==
        CameraCharacteristics.LENS_FACING_FRONT ? 1 : -1;

    // Calculate desired orientation relative to camera orientation to make
    // the image upright relative to the device orientation.
    return (sensorOrientationDegrees - surfaceRotationDegrees * sign + 360) % 360;
}

Métricas de la ventana

No debe usarse el tamaño de la pantalla para determinar las dimensiones de la cámara visor; es posible que la app de cámara se esté ejecutando en una parte de la pantalla, ya sea en el modo multiventana en dispositivos móviles o en el modo gratuito en ChromeOS.

WindowManager#getCurrentWindowMetrics() (agregado en el nivel de API 30) muestra el tamaño de la ventana de la aplicación en lugar de el tamaño de la pantalla. Los métodos de la biblioteca de WindowManager de Jetpack WindowMetricsCalculator#computeCurrentWindowMetrics() y WindowInfoTracker#currentWindowMetrics() proporcionan una compatibilidad similar con retrocompatibilidad con el nivel de API 14.

Rotación de 180 grados

Rotación de 180 grados de un dispositivo (por ejemplo, de la orientación natural a orientación natural al revés) no activa el onConfigurationChanged() devolución de llamada. Como resultado, la vista previa de la cámara puede estar al revés.

Para detectar una rotación de 180 grados, implementa una DisplayListener y comprueba la rotación del dispositivo con una llamada a Display#getRotation() en la onDisplayChanged() devolución de llamada.

Recursos exclusivos

Antes de Android 10, solo la actividad visible superior en un modo multiventana estaba en el estado RESUMED. Esto era confuso para los usuarios porque el sistema no proporcionó ninguna indicación de qué actividad se reanudó.

Android 10 (nivel de API 29) introdujo la reanudación múltiple, en la que todas las actividades visibles están en el estado RESUMED. Las actividades visibles aún pueden ingresar a la PAUSED estado si, por ejemplo, una actividad transparente está sobre la actividad o la actividad no se puede enfocar, como en el modo de pantalla en pantalla (consulta Compatibilidad con pantalla en pantalla).

Una aplicación que utiliza la cámara, el micrófono o cualquier función exclusiva o El recurso singleton en el nivel de API 29 o versiones posteriores debe admitir la reanudación múltiple. Para ejemplo, si tres actividades reanudadas quieren usar la cámara, solo una puede para acceder a este recurso exclusivo. Cada actividad debe implementar un onDisconnected() para mantenerse al tanto del acceso preventivo a la cámara mediante una prioridad más alta actividad.

Para obtener más información, consulta Reanudación múltiple:

Recursos adicionales