Aperçu de l'appareil photo

Remarque:Cette page fait référence au package Camera2. Nous vous recommandons d'utiliser CameraX, sauf si votre application nécessite des fonctionnalités spécifiques de base de Camera2. CameraX et Camera2 sont compatibles avec Android 5.0 (niveau d'API 21) ou version ultérieure.

Les caméras et les aperçus de l'appareil photo ne sont pas toujours dans la même orientation sur Android appareils.

Une caméra est dans une position fixe sur un appareil, que celui-ci est un téléphone, une tablette ou un ordinateur. Lorsque l'orientation de l'appareil change, l'orientation de la caméra.

Par conséquent, les applications d'appareil photo supposent généralement une relation fixe entre les l'orientation de l'appareil et le format de l'aperçu de l'appareil photo. Lorsqu'un le téléphone est en mode portrait, l'aperçu de l'appareil photo est supposé être plus grand que large. Lorsque vous faites pivoter le téléphone (et l'appareil photo) en mode paysage, l'aperçu de l'appareil photo doit être plus large que haut.

Mais ces hypothèses sont remises en question par de nouveaux facteurs de forme, comme les appareils pliables appareils et modes d'affichage tels que mode multifenêtre et multi-écran. Les appareils pliables changent la taille d'affichage et le format sans changer l'orientation. Le mode multifenêtre restreint les applications d'appareil photo à une partie à l'écran, en redimensionnant l'aperçu de l'appareil photo, quelle que soit l'orientation de l'appareil. Le mode multi-écran permet d'utiliser des écrans secondaires qui peuvent ne pas être dans la même orientation que l'écran principal.

Orientation de l'appareil photo

La Définition de compatibilité Android spécifie qu'un capteur d'image de l'appareil photo "DOIT être orienté de sorte que le long la dimension de l'appareil photo s'aligne sur la dimension longue de l'écran. C'est-à-dire, lorsque l'appareil est tenu en mode paysage, les appareils DOIVENT capturer des images l'orientation paysage. Cela s'applique quelle que soit la orientation; Autrement dit, elle s'applique aux appareils principaux en mode paysage "portrait-primary",

L'agencement de la caméra par rapport à l'écran maximise la zone d'affichage de la caméra viseur dans une application d'appareil photo. De plus, les capteurs d'image émettent généralement leurs données en mode paysage, 4:3 étant le plus courant.

Capteur du téléphone et de l'appareil photo en mode portrait.
Image 1. Relation habituelle entre le téléphone et le capteur de l'appareil photo l'orientation.

L'orientation naturelle du capteur photo est en mode paysage. Sur la figure 1, le capteur de la caméra frontale (la caméra orientée dans la même direction que écran) pivote de 270 degrés par rapport au téléphone afin de respecter les Définition de compatibilité Android.

Pour indiquer aux applications la rotation du capteur, le L'API camera2 inclut un SENSOR_ORIENTATION constante. Pour la plupart des téléphones et des tablettes, l'appareil indique l'orientation du capteur. de 270 degrés pour les caméras avant et de 90 degrés (point de vue du arrière de l'appareil) pour les caméras arrière, ce qui aligne le bord long du avec le bord long de l'appareil. Les caméras des ordinateurs portables signalent généralement l'orientation du capteur est de 0 ou 180 degrés.

Comme les capteurs d'image de l'appareil photo envoient leurs données (tampon d'image) dans la l'orientation naturelle du capteur (paysage), le tampon d'image doit faire pivoter nombre de degrés spécifié par SENSOR_ORIENTATION pour que l'aperçu de l'appareil photo à la verticale dans l'orientation naturelle de l'appareil. Pour les caméras avant, la rotation s'effectue dans le sens inverse des aiguilles d'une montre. pour les caméras arrière, dans le sens des aiguilles d'une montre.

Par exemple, pour la caméra avant de la figure 1, la mémoire tampon de l'image produit par le capteur de l'appareil photo se présente comme suit:

Capteur de l'appareil photo pivoté en mode paysage avec une image
            sur le côté, en haut à gauche.

L'image doit pivoter de 270 degrés dans le sens inverse des aiguilles d'une montre correspond à l'orientation de l'appareil:

Capteur de l'appareil photo en mode portrait avec l'image à l'endroit.

Une caméra arrière créerait un tampon d'image avec la même orientation comme le tampon ci-dessus, mais SENSOR_ORIENTATION est de 90 degrés. Par conséquent, la mémoire tampon est pivotée de 90 degrés dans le sens des aiguilles d'une montre.

Rotation de l'appareil

La rotation de l'appareil correspond au nombre de degrés de rotation de l'appareil par rapport à sa valeur naturelle l'orientation. Par exemple, un téléphone en mode paysage possède un appareil un angle de rotation de 90 ou 270 degrés, selon le sens de la rotation.

La rotation de la mémoire tampon d'image d'un capteur photo doit être égale au même nombre de degrés que la rotation de l'appareil (en plus des degrés d'orientation du capteur) l'aperçu de l'appareil photo pour qu'il s'affiche à la verticale.

Calcul de l'orientation

L'orientation correcte de l'aperçu de l'appareil photo tient compte du capteur l'orientation et la rotation de l'appareil.

La rotation globale du tampon d'image du capteur peut être calculée à l'aide de la méthode la formule suivante:

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

sign est 1 pour les caméras avant et -1 pour les caméras arrière.

Pour les caméras avant, la mémoire tampon image est pivotée dans le sens inverse des aiguilles d'une montre (de l'orientation naturelle du capteur). Sur les caméras arrière, le capteur la mémoire tampon de l'image est pivotée dans le sens des aiguilles d'une montre.

L'expression deviceOrientationDegrees * sign + 360 convertit la rotation de l'appareil dans le sens inverse des aiguilles d'une montre pour les caméras arrière conversion de 270 degrés dans le sens inverse des aiguilles d'une montre à 90 degrés dans le sens des aiguilles d'une montre). Le modulo redimensionne le résultat à moins de 360 degrés (par exemple, une mise à l'échelle à 540 degrés de rotation à 180).

Les différentes API signalent la rotation des appareils différemment:

  • Display#getRotation() permet de faire pivoter l'appareil dans le sens inverse des aiguilles d'une montre (du point de l'utilisateur de vue). Cette valeur s'intègre telle quelle dans la formule ci-dessus.
  • OrientationEventListener#onOrientationChanged() renvoie la rotation dans le sens des aiguilles d'une montre de l'appareil (du point de vue de l'utilisateur). N'annule pas la valeur à utiliser dans la formule ci-dessus.

Caméras avant

Aperçu de l'appareil photo et capteur en mode paysage, avec un capteur
            est à l'endroit.
Figure 2 : Aperçu de l'appareil photo et capteur avec le téléphone orienté de 90 degrés sur en mode paysage.

Voici le tampon d'image produit par le capteur photo de l'image 2:

Capteur de l'appareil photo en mode paysage avec l'image à l'endroit.

Vous devez faire pivoter la mémoire tampon de 270 degrés dans le sens inverse des aiguilles d'une montre pour s'adapter au capteur (voir la section Orientation de la caméra ci-dessus):

Capteur de l'appareil photo pivoté en fonction de l'orientation du portrait, image dans le mauvais sens
            en haut à droite.

Ensuite, le tampon fait pivoter de 90 degrés supplémentaires dans le sens inverse des aiguilles d'une montre tenir compte de la rotation de l'appareil, ce qui entraîne l'orientation correcte aperçu de l'appareil photo de la figure 2:

Capteur de l'appareil photo pivoté en mode paysage avec une image
            à la verticale.

Voici la caméra tournée à droite, en mode paysage:

L'aperçu de l'appareil photo et le capteur sont en mode paysage,
            est à l'envers.
Figure 3 : Aperçu de l'appareil photo et capteur avec le téléphone tourné à 270 degrés (ou -90 degrés) en mode paysage.

Voici la mémoire tampon de l'image:

Capteur de l'appareil photo orienté en mode paysage avec l'image à l'envers
            vers le bas.

Faites pivoter la mémoire tampon de 270 degrés dans le sens inverse des aiguilles d'une montre pour s'adapter au capteur. orientation:

Le capteur de l'appareil photo fonctionne en mode portrait avec l'image orientée de côté.
            en haut à gauche.

Ensuite, le tampon fait encore pivoter de 270 degrés dans le sens inverse des aiguilles d'une montre pour tenir compte la rotation de l'appareil:

Capteur de l'appareil photo pivoté en mode paysage avec une image
            à la verticale.

Caméras arrière

Les caméras arrière ont généralement un capteur d'orientation de 90 degrés (comme vu depuis l'arrière de l'appareil). Lorsque vous orientez l'aperçu de l'appareil photo, la mémoire tampon de l'image du capteur est pivotée dans le sens des aiguilles d'une montre en fonction de l'intensité de rotation du capteur. (plutôt que dans le sens inverse des aiguilles d'une montre comme les caméras avant), l'image la mémoire tampon est pivotée dans le sens inverse des aiguilles d'une montre en fonction du degré de rotation de l'appareil.

L'aperçu de l'appareil photo et le capteur sont en mode paysage,
            est à l'envers.
Figure 4 : Téléphone avec la caméra arrière en mode paysage (tournée de 270 ou -90 degrés).

Voici la mémoire tampon de l'image du capteur de l'appareil photo de l'image 4:

Capteur de l'appareil photo orienté en mode paysage avec l'image à l'envers
            vers le bas.

Vous devez faire pivoter la mémoire tampon de 90 degrés dans le sens des aiguilles d'une montre pour tenir compte du capteur orientation:

Le capteur de l'appareil photo fonctionne en mode portrait avec l'image orientée de côté.
            en haut à gauche.

Ensuite, le tampon fait pivoter de 270 degrés dans le sens inverse des aiguilles d'une montre pour tenir compte rotation:

Capteur de l'appareil photo pivoté en mode paysage avec une image
            à la verticale.

Format

Le format d'affichage change lorsque l'orientation de l'appareil change, mais aussi lorsque les appareils pliables se plient et se déplient, lorsque les fenêtres sont redimensionnées en mode multifenêtre et lorsque les applications s'ouvrent sur des écrans secondaires.

La mémoire tampon de l'image du capteur de l'appareil photo doit être orientée et mise à l'échelle pour correspondre à l'orientation et le format de l'élément d'interface utilisateur du viseur en tant qu'interface utilisateur modifie l'orientation de manière dynamique, avec ou sans l'appareil. l'orientation.

Sur de nouveaux facteurs de forme, ou dans des environnements multifenêtres ou multi-écrans, l'application suppose que l'aperçu de l'appareil photo a la même orientation que l'appareil (portrait ou paysage) il est possible que votre aperçu ne soit pas correctement orienté ou mis à l'échelle. incorrectement, ou les deux.

Appareil pliable déplié avec l'aperçu de l'appareil photo en mode portrait activé
            mal orientée.
Figure 5 : Les appareils pliables passent du mode portrait au mode paysage mais le capteur reste en mode portrait.

Dans la figure 5, l'application a supposé à tort que l'appareil avait fait l'objet d'une rotation de 90 degrés dans le sens inverse des aiguilles d'une montre ; et donc, l'application a fait pivoter l'aperçu de la même quantité.

Appareil pliable déplié avec l'aperçu de l'appareil photo à la verticale, mais écrasé
            en raison d'une mise à l'échelle incorrecte.
Figure 6 : Les appareils pliables passent du mode portrait au mode paysage mais le capteur reste en mode portrait.

Dans la figure 6, l'application n'a pas ajusté le format du tampon d'image à permettent-lui de s'adapter correctement aux nouvelles dimensions de l'UI d'aperçu de l'appareil photo .

Les applications d'appareil photo à orientation fixe rencontrent généralement des problèmes sur les appareils pliables et Autres appareils à grand écran, tels que les ordinateurs portables:

L'aperçu de l'appareil photo sur un ordinateur portable est à la verticale, mais l'interface utilisateur de l'application est orientée de côté.
Image 7. Application en mode portrait à orientation fixe sur un ordinateur portable

Dans la figure 7, l'interface utilisateur de l'application d'appareil photo est orientée de côté, car l'orientation de l'application est limité au mode portrait. L'image du viseur est correctement orientée. par rapport au capteur de l'appareil photo.

Mode Portrait en incrustation

Applications d'appareil photo non compatibles avec le mode multifenêtre (resizeableActivity="false") et limiter leur orientation (screenOrientation="portrait") ou screenOrientation="landscape") peuvent être placés en mode Portrait en incrustation sur les appareils à grand écran pour s'orienter correctement l'aperçu de l'appareil photo.

Boîtes aux lettres en mode Portrait en incrustation (encarts) pour les applications en mode portrait uniquement en mode Portrait même si l'écran est au format paysage. Les applications en mode paysage sont affichées au format letterbox en mode paysage, même si le format de l'écran est en mode portrait. L'image de l'appareil photo est pivotée pour s'aligner avec l'UI de l'application, recadrée pour correspondre au format de l'aperçu de l'appareil photo ; puis mise à l'échelle pour remplir l'aperçu.

Le mode Portrait en incrustation est déclenché lorsque le format de l'image de l'appareil photo et le format de l'activité principale de l'application ne correspondent pas.

Aperçu de l'appareil photo et interface utilisateur de l'application en mode portrait sur un ordinateur portable.
            L'aperçu large est mis à l'échelle et recadré pour s'adapter au format portrait
            l'orientation.
Figure 8 : Application Portrait à orientation fixe en mode Portrait en incrustation activée ordinateur portable.

Dans la figure 8, l'application d'appareil photo en mode portrait a fait l'objet d'une rotation pour afficher l'UI. sur l'écran de l'ordinateur portable. L'application est mise au format letterbox en raison de la différence. entre l'application en mode portrait et l'écran en mode paysage. L'appareil photo l'image d'aperçu a été pivotée pour compenser la rotation de l'interface utilisateur de l'application (en raison de mode Portrait incrusté), et l'image a été recadrée et mise à l'échelle pour s'adapter l'orientation portrait, ce qui réduit le champ de vision.

Faire pivoter, recadrer, mettre à l'échelle

Le mode Portrait en encart est appelé pour une application d'appareil photo en mode portrait sur un écran. au format paysage:

L'aperçu de l'appareil photo sur un ordinateur portable est à la verticale, mais l'interface utilisateur de l'application est orientée de côté.
Figure 9 : Application en mode portrait à orientation fixe sur un ordinateur portable

L'application est mise au format letterbox en mode portrait:

Application pivotée en mode portrait et mise au format letterbox. L'image est
            sur le côté, de haut 
à droite.

L'image de la caméra fait l'objet d'une rotation de 90 degrés pour ajuster la réorientation de application:

L'image du capteur a fait l'objet d'une rotation de 90 degrés pour la placer à la verticale.

L'image est recadrée au format de l'aperçu de l'appareil photo, puis mise à l'échelle pour remplir l'aperçu (le champ de vision est réduit):

L'image de l'appareil photo recadrée a été mise à l'échelle pour remplir l'aperçu de l'appareil photo.

Sur les appareils pliables, l'orientation du capteur de l'appareil photo peut être en mode portrait. alors que l'écran est au format paysage:

Aperçu de l'appareil photo et interface utilisateur de l'application tournées sur le côté d'un grand écran déplié.
Figure 10. Appareil déplié avec l'application Appareil photo en mode portrait et différents formats du capteur de l'appareil photo et de l'écran.

Comme l'aperçu de l'appareil photo est pivoté pour s'adapter à l'orientation du capteur, l'image est correctement orientée dans le viseur, mais l'application en mode portrait uniquement est de travers.

Le mode Portrait en incrustation n'a besoin d'utiliser le format letterbox que pour l'application en mode Portrait. pour orienter correctement l'application et l'aperçu de l'appareil photo:

Application au format letterbox en mode portrait avec aperçu de l'appareil photo
            sur un appareil pliable.

API

À partir d'Android 12 (niveau d'API 31), les applis peuvent aussi contrôler explicitement l'encart portrait à l'aide du SCALER_ROTATE_AND_CROP propriété de CaptureRequest .

La valeur par défaut est SCALER_ROTATE_AND_CROP_AUTO qui permet au système d'invoquer le mode Portrait en incrustation. SCALER_ROTATE_AND_CROP_90 correspond au comportement du mode Portrait en incrustation, tel que décrit ci-dessus.

Tous les appareils ne sont pas compatibles avec toutes les valeurs SCALER_ROTATE_AND_CROP. Pour obtenir une liste des valeurs acceptées, reportez-vous CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES

CameraX

Bibliothèque Jetpack CameraX permet de créer un viseur d'appareil photo qui s'adapte à l'orientation du capteur la rotation des appareils une tâche simple.

L'élément de mise en page PreviewView crée un aperçu de l'appareil photo qui ajuste automatiquement l'orientation du capteur, la rotation des appareils et le scaling. PreviewView conserve le format de l'élément l'image de l'appareil photo en appliquant la FILL_CENTER Le type d'échelle permet de centrer l'image, mais peut être recadré pour l'adapter aux dimensions. de PreviewView. Pour afficher l'image de l'appareil photo au format letterbox, définissez le type d'échelle sur FIT_CENTER

Pour découvrir les bases de la création d'un aperçu d'appareil photo avec PreviewView, consultez Implémenter un aperçu

Pour obtenir un exemple complet d'implémentation, consultez la CameraXBasic sur GitHub.

CameraViewfinder

Comme pour le cas d'utilisation Preview, CameraViewfinder propose un ensemble d'outils permettant de simplifier la création d'un aperçu d'appareil photo. Il ne dépend pas de CameraX Core. Vous pouvez donc l'intégrer facilement à votre le codebase Camera2 existant.

Au lieu d'utiliser Surface vous pouvez utiliser CameraViewfinder pour afficher le flux de la caméra de Camera2.

CameraViewfinder utilise TextureView ou SurfaceView en interne. pour afficher le flux de la caméra et applique les transformations requises à pour afficher correctement le viseur. Cela implique de corriger leurs proportions, leur échelle et leur rotation.

Pour demander la surface de l'objet CameraViewfinder, vous devez : créer un ViewfinderSurfaceRequest ;

Cette demande contient les exigences liées à la résolution de la surface et à la caméra informations de CameraCharacteristics.

Vous appelez requestSurfaceAsync() envoie la requête au fournisseur de surface, qui est un TextureView ou SurfaceView et obtient un ListenableFuture de Surface.

Vous appelez markSurfaceSafeToRelease() informe le fournisseur de surfaces qu'elle n'est pas nécessaire peuvent être libérées.

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 est un(e) simple pour créer un aperçu de l'appareil photo ne doivent pas être traitées et ne sont pas animées.

SurfaceView fait pivoter automatiquement la mémoire tampon de l'image du capteur de l'appareil photo en conséquence l'orientation de l'écran, en tenant compte à la fois de l'orientation du capteur et de l'appareil ; la rotation des clés. Toutefois, le tampon d'image est mis à l'échelle pour s'adapter à SurfaceView sans tenir compte du format.

Vous devez vous assurer que les proportions du tampon d'image correspondent aux proportions le ratio de SurfaceView, que vous pouvez obtenir en redimensionnant le contenu de SurfaceView dans l'objet onMeasure() méthode:

(Le code source computeRelativeRotation() se trouve dans Rotation relative ci-dessous.)

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);
}

Pour savoir comment implémenter SurfaceView en tant qu'aperçu de l'appareil photo, consultez Orientation de la caméra.

TextureView

TextureView est moins performant que SurfaceView (et plus d'efforts), mais TextureView vous offre la valeur maximale de l'aperçu de l'appareil photo.

TextureView fait pivoter la mémoire tampon de l'image du capteur en fonction de l'orientation du capteur, mais ne gère pas la rotation de l'appareil ni le scaling de l'aperçu.

La mise à l'échelle et la rotation peuvent être encodées Transformation Matrix (Matrix) Pour savoir comment mettre à l'échelle et faire pivoter une TextureView correctement, consultez Prendre en charge les surfaces redimensionnables dans votre application d'appareil photo

Rotation relative

La rotation relative du capteur de l'appareil photo correspond au degré de rotation requis pour aligner la sortie du capteur de l'appareil photo sur l'orientation de l'appareil.

La rotation relative est utilisée par des composants tels que SurfaceView et TextureView afin de déterminer les facteurs de mise à l'échelle x et y pour l'image d'aperçu. Il est également utilisé pour permet de spécifier la rotation du tampon d'image du capteur.

La CameraCharacteristics et Les classes Surface permettent de calculer le rotation relative du capteur de l'appareil photo:

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étriques sur les fenêtres

La taille de l'écran ne doit pas être utilisée pour déterminer les dimensions de la caméra. viseur il est possible que l'application Appareil photo s'exécute sur une partie de l'écran, en mode multifenêtre sur les appareils mobiles ou en mode sans frais sur ChromeOS.

WindowManager#getCurrentWindowMetrics() (ajoutée au niveau d'API 30) renvoie la taille de la fenêtre de l'application au lieu de la taille de l'écran. Méthodes de la bibliothèque Jetpack WindowManager WindowMetricsCalculator#computeCurrentWindowMetrics() et WindowInfoTracker#currentWindowMetrics() offrent un support similaire avec la rétrocompatibilité jusqu'au niveau d'API 14.

Rotation à 180 degrés

Rotation à 180 degrés d'un appareil (par exemple, de l'orientation naturelle à l'orientation naturelle à l'envers) ne déclenche pas onConfigurationChanged() . Par conséquent, l'aperçu de l'appareil photo peut être à l'envers.

Pour détecter une rotation de 180 degrés, implémentez une DisplayListener et vérifiez la rotation de l'appareil en appelant Display#getRotation() dans onDisplayChanged() .

Ressources exclusives

Avant Android 10, seule l'activité la plus visible était visible dans un mode multifenêtre. était à l'état RESUMED. Cela était déroutant pour les utilisateurs parce que le système n'a fourni aucune indication sur l'activité réactivée.

Android 10 (niveau d'API 29) introduit la multireprise, où toutes les activités visibles sont à l'état RESUMED ; Les activités visibles peuvent toujours être incluses dans le PAUSED si, par exemple, une activité transparente se superpose à l'activité l'activité ne peut pas être mise au point, par exemple en mode Picture-in-picture (voir fonctionnalité Picture-in-picture).

Une application utilisant l'appareil photo, le micro ou tout autre logiciel La ressource singleton au niveau d'API 29 ou supérieur doit être compatible avec la multireprise. Pour Par exemple, si trois activités réactivées souhaitent utiliser la caméra, une seule peut pour accéder à cette ressource exclusive. Chaque activité doit mettre en œuvre onDisconnected() rappel pour savoir si un accès préventif à l'appareil photo est accordé avec une priorité plus élevée activité.

Pour en savoir plus, consultez Multireprise :

Ressources supplémentaires