Aperçu de l'appareil photo

Remarque : Cette page fait référence au package Camera2. À moins que votre application ne nécessite des fonctionnalités spécifiques de bas niveau de Camera2, nous vous recommandons d'utiliser CameraX. 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 caméra ne sont pas toujours dans la même orientation sur les appareils Android.

Une caméra se trouve dans une position fixe sur un appareil, qu'il s'agisse d'un téléphone, d'une tablette ou d'un ordinateur. Lorsque l'orientation de l'appareil change, l'orientation de la caméra change également.

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

Toutefois, ces présomptions sont remises en question par de nouveaux facteurs de forme, tels que les appareils pliables, et de nouveaux modes d'affichage, tels que les modes multifenêtre et multiécran. Les appareils pliables modifient la taille d'affichage et le format sans changer l'orientation. Le mode multifenêtre limite les applications d'appareil photo à une partie de l'écran, en mettant à l'échelle 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 ne sont pas forcément dans la même orientation que l'écran principal.

Orientation de l'appareil photo

La Définition de compatibilité Android spécifie que le capteur d'image d'un appareil photo "DOIT être orienté de sorte à faire correspondre la dimension longue de l'appareil photo à la dimension longue de l'écran". Autrement dit, lorsque l'appareil est tenu en mode paysage, les caméras DOIVENT capturer des images en mode paysage. Cela s'applique quelle que soit l'orientation naturelle de l'appareil, c'est-à-dire aux appareils principalement en mode paysage, ainsi qu'aux appareils principalement en mode portrait."

La disposition de l'appareil photo par rapport à l'écran maximise la zone d'affichage du viseur de l'appareil photo dans une application d'appareil photo. De plus, les capteurs d'image affichent généralement leurs données au format paysage, le format 4:3 étant le plus courant.

Le téléphone et le capteur de l'appareil photo sont tous deux en mode portrait.
Figure 1. Relation typique entre l'orientation du téléphone et celle du capteur de l'appareil photo.

L'orientation naturelle du capteur de l'appareil photo est en mode paysage. Dans la figure 1, le capteur de la caméra avant (la caméra pointant dans la même direction que l'écran) est pivoté de 270 degrés par rapport au téléphone pour respecter la définition de compatibilité Android.

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

Étant donné que les capteurs d'image de l'appareil photo génèrent leurs données (un tampon d'image) dans l'orientation naturelle du capteur (paysage), le tampon d'image doit être pivoté du nombre de degrés spécifié par SENSOR_ORIENTATION pour que l'aperçu de l'appareil photo s'affiche à l'endroit 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, elle s'effectue dans le sens des aiguilles d'une montre.

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

Capteur de l'appareil photo pivoté en orientation paysage avec l'image sur le côté, en haut à gauche.
Figure 2 : Tampon d'image brute d'un capteur de caméra avant dans son orientation paysage naturelle.

L'image doit être pivotée de 270 degrés dans le sens inverse des aiguilles d'une montre pour que l'orientation de l'aperçu corresponde à celle de l'appareil :

Capteur de l'appareil photo en mode portrait avec l'image à l'endroit.
Figure 3 : Tampon d'image de la caméra avant pivoté de 270 degrés dans le sens inverse des aiguilles d'une montre pour correspondre à l'orientation de l'appareil en mode portrait.

Une caméra arrière produirait un tampon d'image avec la même orientation que le tampon précédent, mais SENSOR_ORIENTATION est de 90 degrés. Par conséquent, le tampon est pivoté 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 d'un appareil par rapport à son orientation naturelle. Par exemple, un téléphone en mode paysage a une rotation de 90 ou 270 degrés, selon le sens de rotation.

Un tampon d'image du capteur de l'appareil photo doit être pivoté du même nombre de degrés que la rotation de l'appareil (en plus des degrés d'orientation du capteur) pour que l'aperçu de l'appareil photo apparaisse à la verticale.

Calcul de l'orientation

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

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

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

où sign correspond à 1 pour les caméras avant et à -1 pour les caméras arrière.

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

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

Différentes API signalent la rotation de l'appareil de différentes manières :

  • Display#getRotation() fournit la rotation de l'appareil dans le sens inverse des aiguilles d'une montre (du point de vue de l'utilisateur). Cette valeur est insérée telle quelle dans la formule précédente.
  • OrientationEventListener#onOrientationChanged() renvoie la rotation de l'appareil dans le sens des aiguilles d'une montre (du point de vue de l'utilisateur). Inversez la valeur pour l'utiliser dans la formule précédente.

Caméras frontales

L'aperçu de l'appareil photo et le capteur sont tous deux en mode paysage, et le capteur est à l'endroit.
Figure 4 : Aperçu de l'appareil photo et capteur avec le téléphone pivoté de 90 degrés en mode paysage.

Voici le tampon d'image produit par le capteur de l'appareil photo dans la figure 4 :

Capteur de l'appareil photo en mode paysage avec l'image à l'endroit.
Figure 5 : Tampon d'image produit par le capteur de la caméra avant lorsque le téléphone est incliné de 90 degrés dans le sens inverse des aiguilles d'une montre.

Le tampon doit être pivoté de 270 degrés dans le sens inverse des aiguilles d'une montre pour s'adapter à l'orientation du capteur (voir Orientation de l'appareil photo ci-dessus) :

Capteur de l'appareil photo orienté en mode portrait avec l'image sur le côté, en haut à droite.
Figure 6 : Rotation du tampon d'image de 270 degrés dans le sens inverse des aiguilles d'une montre pour l'ajuster à l'orientation du capteur.

Ensuite, le tampon est pivoté de 90 degrés supplémentaires dans le sens inverse des aiguilles d'une montre pour tenir compte de la rotation de l'appareil, ce qui permet d'obtenir l'orientation correcte de l'aperçu de l'appareil photo dans la figure 4 :

Capteur de l'appareil photo pivoté en mode paysage avec l'image à l'endroit.
Image 7. Tampon d'image après une rotation supplémentaire de 90 degrés dans le sens inverse des aiguilles d'une montre pour l'orientation de l'appareil.

Voici l'appareil photo tourné vers la droite en mode paysage :

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

Voici le tampon d'image :

Capteur de l'appareil photo pivoté en orientation paysage avec l'image à l'envers.
Figure 9 : Tampon d'image produit par le capteur de la caméra avant lorsque le téléphone est tourné de 270 degrés dans le sens inverse des aiguilles d'une montre.

Le tampon doit être pivoté de 270 degrés dans le sens inverse des aiguilles d'une montre pour s'adapter à l'orientation du capteur :

Capteur de l'appareil photo pivoté en mode Portrait avec l'image sur le côté, en haut à gauche.
Figure 10. Rotation du tampon d'image de 270 degrés dans le sens inverse des aiguilles d'une montre pour l'ajuster à l'orientation du capteur.

Ensuite, le tampon est pivoté de 270 degrés supplémentaires dans le sens inverse des aiguilles d'une montre pour tenir compte de la rotation de l'appareil :

Capteur de l'appareil photo pivoté en mode paysage avec l'image à l'endroit.
Figure 11 : Tampon d'image après une rotation supplémentaire de 270 degrés dans le sens inverse des aiguilles d'une montre pour l'orientation de l'appareil.

Caméras arrière

Les caméras arrière ont généralement une orientation de capteur de 90 degrés (vue de l'arrière de l'appareil). Lors de l'orientation de l'aperçu de l'appareil photo, le tampon d'image du capteur est pivoté dans le sens des aiguilles d'une montre en fonction de la rotation du capteur (plutôt que dans le sens inverse des aiguilles d'une montre comme pour les caméras avant), puis le tampon d'image est pivoté dans le sens inverse des aiguilles d'une montre en fonction de la rotation de l'appareil.

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

Voici le tampon d'image du capteur de la caméra de la figure 12 :

Capteur de l'appareil photo pivoté en orientation paysage avec l'image à l'envers.
Figure 13. Tampon d'image produit par le capteur de la caméra arrière lorsque le téléphone est en mode paysage.

Le tampon doit être pivoté de 90 degrés dans le sens des aiguilles d'une montre pour s'adapter à l'orientation du capteur :

Capteur de l'appareil photo pivoté en mode Portrait avec l'image sur le côté, en haut à gauche.
Figure 14 : Tampon d'image pivoté de 90 degrés dans le sens des aiguilles d'une montre pour s'adapter à l'orientation du capteur arrière.

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

Capteur de l'appareil photo pivoté en mode paysage avec l'image à l'endroit.
Figure 15 : Tampon d'image après une rotation de 270 degrés dans le sens inverse des aiguilles d'une montre pour l'orientation de l'appareil.

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.

Le tampon d'image du capteur de l'appareil photo doit être orienté et mis à l'échelle pour correspondre à l'orientation et au format de l'élément d'interface utilisateur du viseur, car l'interface utilisateur change d'orientation de manière dynamique, que l'appareil change d'orientation ou non.

Sur les nouveaux facteurs de forme ou dans les environnements en mode multifenêtre ou multiécrans, si votre application suppose que l'aperçu de l'appareil photo a la même orientation que l'appareil (portrait ou paysage), l'aperçu peut être mal orienté, mal mis à l'échelle, ou les deux.

Appareil pliable déplié avec l'aperçu de l'appareil photo en mode portrait tourné sur le côté.
Figure 16 : L'appareil pliable passe du format portrait au format paysage, mais le capteur de l'appareil photo reste en mode portrait.

Dans la figure 16, l'application a supposé à tort que l'appareil avait été pivoté de 90 degrés dans le sens inverse des aiguilles d'une montre. Elle a donc fait pivoter l'aperçu de la même valeur.

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 17 : L'appareil pliable passe du format portrait au format paysage avec un aperçu de l'appareil photo mal mis à l'échelle.

Dans la figure 17, l'application n'a pas ajusté le format du tampon d'image pour lui permettre d'adapter correctement l'échelle aux nouvelles dimensions de l'élément d'interface utilisateur de l'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 d'autres appareils à grand écran, tels que les ordinateurs portables :

L'aperçu de l'appareil photo sur l'ordinateur portable est à l'endroit, mais l'UI de l'application est sur le côté.
Figure 18 : Application en mode portrait fixe sur un ordinateur portable.

Dans la figure 18, l'UI de l'application Appareil photo est sur le côté, car l'orientation de l'application est limitée au mode portrait. L'image du viseur est correctement orientée par rapport au capteur de la caméra.

Mode Portrait incrusté

Les applications d'appareil photo qui ne sont pas compatibles avec le mode multifenêtre (resizeableActivity="false") et qui limitent leur orientation (screenOrientation="portrait" ou screenOrientation="landscape") peuvent être placées en mode Portrait en incrustation sur les appareils à grand écran pour orienter correctement l'aperçu de l'appareil photo.

Le mode Portrait en incrustation affiche les applications en mode portrait uniquement dans l'orientation portrait, même si le format d'affichage est en mode paysage. Les applications en mode paysage uniquement sont mises au format letterbox en mode paysage, même si le format d'affichage est en mode portrait. L'image de l'appareil photo est pivotée pour s'aligner sur 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 du capteur d'image de l'appareil photo et celui de l'activité principale de l'application ne correspondent pas.

Aperçu de l'appareil photo et UI de l'application correctement orientés en mode portrait sur un ordinateur portable.
            L'image d'aperçu large est mise à l'échelle et recadrée pour s'adapter à l'orientation portrait.
Figure 19 : Application en mode portrait fixe dans un encart en mode portrait sur un ordinateur portable.

Dans la figure 19, l'application Appareil photo en mode portrait uniquement a été pivotée pour afficher l'UI à la verticale sur l'écran de l'ordinateur portable. L'application est affichée au format letterbox en raison de la différence de format entre l'application en mode portrait et l'écran en mode paysage. L'image d'aperçu de l'appareil photo a été pivotée pour compenser la rotation de l'UI de l'application (en raison du mode portrait encastré). 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, redimensionner

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

L'aperçu de l'appareil photo sur l'ordinateur portable est à l'endroit, mais l'UI de l'application est sur le côté.
Figure 20 : Application en mode portrait 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é, le haut est à droite.
Figure 21 : Application en mode portrait uniquement, pivotée et mise au format letterbox sur un écran en mode paysage, avant la rotation de l'image du capteur.

L'image de la caméra est pivotée de 90 degrés pour s'adapter à la réorientation de l'application :

Image du capteur pivotée de 90 degrés pour la redresser.
Figure 22 : Image de la caméra pivotée de 90 degrés pour s'aligner sur l'UI de l'application réorientée.

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) :

Image de l'appareil photo recadrée et mise à l'échelle pour remplir l'aperçu de l'appareil photo.
Figure 23 : Image de l'appareil photo recadrée et mise à l'échelle pour remplir l'aperçu de l'appareil photo en mode portrait.

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

L'aperçu de l'appareil photo et l'UI de l'application sont orientés sur le côté de l'écran large déplié.
Figure 24 : Appareil déplié avec une application d'appareil photo en mode portrait uniquement, et différents formats de capteur et d'é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 sur le côté.

Le mode Portrait en incrustation n'a besoin que de mettre l'application au format letterbox en mode portrait pour orienter correctement l'application et l'aperçu de l'appareil photo :

Application en mode letterbox en orientation portrait avec l'aperçu de l'appareil photo à la verticale sur un appareil pliable.
Figure 25 : Une application au format portrait uniquement mise au format letterbox en mode portrait sur un appareil pliable déplié.

API

À partir d'Android 12 (niveau d'API 31), les applications peuvent également contrôler explicitement le mode Portrait en incrustation à l'aide de la propriété SCALER_ROTATE_AND_CROP de la classe CaptureRequest.

La valeur par défaut est SCALER_ROTATE_AND_CROP_AUTO, ce qui permet au système d'appeler le mode Portrait en incrustation. SCALER_ROTATE_AND_CROP_90 est le comportement du mode Portrait en incrustation, comme décrit précédemment.

Tous les appareils ne sont pas compatibles avec toutes les valeurs SCALER_ROTATE_AND_CROP. Pour obtenir la liste des valeurs acceptées, consultez CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES.

CameraX

La bibliothèque Jetpack CameraX permet de créer facilement un viseur d'appareil photo qui s'adapte à l'orientation du capteur et à la rotation de l'appareil.

L'élément de mise en page PreviewView crée un aperçu de l'appareil photo, en s'ajustant automatiquement à l'orientation du capteur, à la rotation de l'appareil et à la mise à l'échelle. PreviewView conserve le format de l'image de l'appareil photo en appliquant le type de mise à l'échelle FILL_CENTER, qui centre l'image, mais peut la recadrer pour qu'elle corresponde aux dimensions de PreviewView. Pour ajouter des bandes noires à l'image de la caméra, définissez le type d'échelle sur FIT_CENTER.

Pour apprendre à créer un aperçu de l'appareil photo avec PreviewView, consultez Implémenter un aperçu.

Pour obtenir un exemple d'implémentation complet, consultez le dépôt CameraXBasic sur GitHub.

CameraViewfinder

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

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

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

Pour demander la surface à partir de l'objet CameraViewfinder, vous devez créer un ViewfinderSurfaceRequest.

Cette requête contient des exigences concernant la résolution de la surface et les informations sur l'appareil photo de CameraCharacteristics.

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

L'appel de markSurfaceSafeToRelease() informe le fournisseur de surface que la surface n'est pas nécessaire et que les ressources associées peuvent être libérées.

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

SurfaceView

SurfaceView est une approche simple pour créer un aperçu de l'appareil photo si l'aperçu ne nécessite pas de traitement et n'est pas animé.

SurfaceView fait automatiquement pivoter le tampon d'image du capteur de la caméra pour qu'il corresponde à l'orientation de l'écran, en tenant compte à la fois de l'orientation du capteur et de la rotation de l'appareil. Cependant, le tampon d'image est mis à l'échelle pour s'adapter aux dimensions de SurfaceView sans tenir compte du format.

Vous devez vous assurer que le format du tampon d'image correspond au format de SurfaceView, ce que vous pouvez faire en mettant à l'échelle le contenu de SurfaceView dans la méthode onMeasure() du composant :

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

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

Pour en savoir plus sur l'implémentation de SurfaceView en tant qu'aperçu de l'appareil photo, consultez Orientations de l'appareil photo.

TextureView

TextureView est moins performant que SurfaceView et demande plus de travail, mais TextureView vous offre un contrôle maximal sur l'aperçu de l'appareil photo.

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

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

Rotation relative

La rotation relative du capteur de la caméra correspond à la rotation requise pour aligner la sortie du capteur de la caméra avec l'orientation de l'appareil.

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

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

/**
 * 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) ?: 0

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

Métriques sur les fenêtres

La taille de l'écran ne doit pas être utilisée pour déterminer les dimensions du viseur de l'appareil photo. L'application Appareil photo peut s'exécuter sur une partie de l'écran, soit en mode multifenêtre sur les appareils mobiles, soit en mode libre sur ChromeOS.

WindowManager#getCurrentWindowMetrics() (ajouté au niveau d'API 30) renvoie la taille de la fenêtre de l'application plutôt que celle de l'écran. Les méthodes de la bibliothèque Jetpack WindowManager WindowMetricsCalculator#computeCurrentWindowMetrics() et WindowInfoTracker#currentWindowMetrics() offrent une assistance similaire avec rétrocompatibilité jusqu'au niveau d'API 14.

Rotation à 180 degrés

Une rotation de 180 degrés d'un appareil (par exemple, de l'orientation naturelle à l'orientation naturelle inversée) ne déclenche pas le rappel 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 un DisplayListener et vérifiez la rotation de l'appareil en appelant Display#getRotation() dans le rappel onDisplayChanged().

Ressources exclusives

Avant Android 10, seule l'activité visible la plus élevée en mode multifenêtre était à l'état RESUMED. Cela prêtait à confusion pour les utilisateurs, car le système n'indiquait pas quelle activité était reprise.

Android 10 (niveau d'API 29) a introduit la fonctionnalité de multireprise, dans laquelle toutes les activités visibles sont à l'état RESUMED. Les activités visibles peuvent toujours passer à l'état PAUSED si, par exemple, une activité transparente se superpose ou si l'activité ne peut pas être sélectionnée, comme en mode Picture-in-picture (voir Compatibilité avec le mode Picture-in-picture).

Une application utilisant l'appareil photo, le micro ou toute ressource exclusive ou singleton au niveau d'API 29 ou supérieur doit être compatible avec la reprise multiple. Par exemple, si trois activités réactivées souhaitent utiliser l'appareil photo, une seule peut accéder à cette ressource exclusive. Chaque activité doit implémenter un rappel onDisconnected() pour rester informée de l'accès préemptif à l'appareil photo par une activité de priorité plus élevée.

Pour en savoir plus, consultez Multi-reprise.

Ressources supplémentaires