Anteprima fotocamera

Nota: questa pagina fa riferimento al pacchetto Camera2. A meno che la tua app non richieda funzionalità specifiche di basso livello di Camera2, ti consigliamo di usare CameraX. Sia CameraX che Camera2 supportano Android 5.0 (livello API 21) e versioni successive.

Le fotocamere e le relative anteprime non hanno sempre lo stesso orientamento su Android dispositivi mobili.

Una videocamera è in una posizione fissa su un dispositivo, anche se quest'ultimo è un telefono, un tablet o un computer. Quando cambia l'orientamento del dispositivo, cambia l'orientamento della fotocamera.

Di conseguenza, le app della fotocamera di solito assumono una relazione fissa tra l'orientamento del dispositivo e le proporzioni dell'anteprima della fotocamera. Quando il telefono è in orientamento verticale, si presume che l'anteprima della fotocamera sia più alta piuttosto che largo. Quando lo smartphone e la fotocamera sono ruotati in orizzontale, il l'anteprima della fotocamera deve essere più larga dell'altezza.

Tuttavia, questi presupposti sono messi in discussione da nuovi fattori di forma, come foldable dispositivi mobili e modalità di visualizzazione come multi-finestra e multidisplay. I dispositivi pieghevoli cambiano le dimensioni del display e le proporzioni senza cambiare orientamento. La modalità multi-finestra vincola le app della fotocamera a una parte della schermo, ridimensionando l'anteprima della fotocamera indipendentemente dall'orientamento del dispositivo. La modalità multi-display consente di usare display secondari che potrebbero non nello stesso orientamento del display principale.

Orientamento della fotocamera

La Definizione di compatibilità Android specifica che il sensore fotografico di una fotocamera "DEVE essere orientato in modo tale che il della fotocamera si allinea alla dimensione lunga dello schermo. Ovvero, quando il dispositivo è tenuto in orientamento orizzontale, le videocamere DEVONO acquisire immagini in l'orientamento orizzontale. Ciò si applica a prescindere dalle impostazioni orientamento; vale a dire ai dispositivi principali per orientamento orizzontale e dispositivi principali con orientamento verticale".

La disposizione dalla fotocamera allo schermo ingrandisce l'area di visualizzazione della videocamera mirino in un'app Fotocamera. Inoltre, i sensori immagine in genere inviano i loro dati proporzioni orizzontali, 4:3 è il formato più comune.

Sensore dello smartphone e della fotocamera entrambi con orientamento verticale.
. Figura 1. Relazione tipica tra il sensore dello smartphone e della fotocamera orientamento.

L'orientamento naturale del sensore della fotocamera è orizzontale. Nella Figura 1, il sensore della fotocamera anteriore (quella che punta nella stessa direzione del display) sia ruotato di 270 gradi rispetto allo smartphone per rispettare le Definizione di compatibilità Android.

Per esporre la rotazione del sensore alle app, L'API camera2 include una SENSOR_ORIENTATION costante. Per la maggior parte degli smartphone e dei tablet, il dispositivo segnala l'orientamento del sensore di 270 gradi per le fotocamere anteriori e di 90 gradi (punto di vista dal retro del dispositivo) per le fotocamere posteriori, allineando il bordo lungo sensore con il bordo lungo del dispositivo. Le fotocamere dei laptop di solito segnalano orientato del sensore di 0 o 180 gradi.

Poiché i sensori immagine della fotocamera emettono i propri dati (un buffer di immagine) orientamento naturale (orizzontale) del sensore, il buffer di immagine deve essere ruotato numero di gradi specificato da SENSOR_ORIENTATION per l'anteprima della fotocamera vengono visualizzati in verticale nell'orientamento naturale del dispositivo. Per le fotocamere anteriori, la rotazione è in senso antiorario; per le fotocamere posteriori, in senso orario.

Ad esempio, per la fotocamera anteriore nella figura 1, il buffer prodotto dal sensore della fotocamera ha il seguente aspetto:

Sensore della fotocamera ruotato in orientamento orizzontale con immagine
            di lato, in alto a sinistra.

L'immagine deve essere ruotata di 270 gradi in senso antiorario per visualizzare l'anteprima l'orientamento corrisponde a quello del dispositivo:

Sensore della fotocamera in orientamento verticale con immagine rivolta verso l'alto.

Una fotocamera posteriore produrrebbe un buffer di immagine con lo stesso orientamento come il buffer sopra, ma SENSOR_ORIENTATION è 90 gradi. Di conseguenza, il buffer viene ruotato di 90 gradi in senso orario.

Rotazione del dispositivo

La rotazione del dispositivo è il numero di gradi in cui un dispositivo viene ruotato rispetto alla sua naturalezza orientamento. Ad esempio, un telefono con orientamento orizzontale ha un rotazione di 90 o 270 gradi, a seconda del senso di rotazione.

Un buffer d'immagine del sensore della fotocamera deve essere ruotato dello stesso numero di gradi del la rotazione del dispositivo (oltre ai gradi di orientamento del sensore) per dell'anteprima della fotocamera in verticale.

Calcolo dell'orientamento

Il corretto orientamento dell'anteprima della fotocamera prende in considerazione il sensore l'orientamento e la rotazione del dispositivo.

La rotazione complessiva del buffer di immagine del sensore può essere calcolata utilizzando seguente formula:

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

dove sign è 1 per le fotocamere anteriori e -1 per le fotocamere posteriori.

Per le fotocamere anteriori, il buffer di immagine viene ruotato in senso antiorario (da l'orientamento naturale del sensore). Per le fotocamere posteriori, il sensore buffer di immagine ruotato in senso orario.

L'espressione deviceOrientationDegrees * sign + 360 converte la rotazione dei dispositivi da antiorario a senso orario per le fotocamere posteriori (ad esempio, conversione di 270 gradi in senso antiorario a 90 gradi in senso orario). Il modulo scala il risultato a meno di 360 gradi (ad esempio, scalando 540 gradi di rotazione a 180).

API diverse registrano la rotazione dei dispositivi in modo diverso:

  • Display#getRotation() fornisce la rotazione antioraria del dispositivo (dal punto dell'utente di vista). Questo valore si collega così com'è alla formula precedente.
  • OrientationEventListener#onOrientationChanged() restituisce la rotazione in senso orario del dispositivo (dal punto di vista dell'utente). Annulla il valore da utilizzare nella formula riportata sopra.

Fotocamere anteriori

Anteprima della fotocamera e sensore con orientamento orizzontale e sensore
            sia con il lato destro.
. Figura 2. Anteprima della fotocamera e sensore con lo smartphone ruotato di 90 gradi a orientamento orizzontale.

Ecco il buffer di immagine prodotto dal sensore della fotocamera nella Figura 2:

Sensore della fotocamera in orientamento orizzontale con immagine rivolta verso l'alto.

Il buffer deve essere ruotato di 270 gradi in senso antiorario per regolare il sensore orientamento (vedi Orientamento fotocamera sopra):

Sensore della fotocamera ruotato in verticale con immagine ruotata
            in alto a destra.

Quindi il tampone viene ruotato di altri 90 gradi in senso antiorario per tiene conto della rotazione del dispositivo, determinando il corretto orientamento anteprima della fotocamera nella figura 2:

Sensore della fotocamera ruotato in orientamento orizzontale con immagine
            in posizione verticale.

Ecco la fotocamera girata a destra per passare all'orientamento orizzontale:

L'anteprima della fotocamera e il sensore sono entrambi in orientamento orizzontale, ma
            capovolto.
. Figura 3. Anteprima della fotocamera e sensore con telefono girato di 270 gradi (o -90 gradi) all'orientamento orizzontale.

Ecco il buffer dell'immagine:

Sensore della fotocamera ruotato in orientamento orizzontale con immagine capovolta
            verso il basso.

Il buffer deve essere ruotato di 270 gradi in senso antiorario per regolare il sensore orientamento:

Sensore della fotocamera con orientamento verticale con immagine ruotata,
            in alto a sinistra.

Quindi il buffer viene ruotato di altri 270 gradi in senso antiorario per tenere conto la rotazione del dispositivo:

Sensore della fotocamera ruotato in orientamento orizzontale con immagine
            in posizione verticale.

Fotocamere posteriori

Le fotocamere posteriori in genere hanno un orientamento del sensore di 90 gradi (come visto dal retro del dispositivo). Quando orienta l'anteprima della fotocamera, il valore il buffer di immagine del sensore viene ruotato in senso orario della quantità di rotazione del sensore (anziché in senso antiorario come le fotocamere anteriori), quindi l'immagine il buffer viene ruotato in senso antiorario per lo stesso numero di rotazione del dispositivo.

L'anteprima della fotocamera e il sensore sono entrambi in orientamento orizzontale, ma
            capovolto.
. Figura 4. Smartphone con fotocamera posteriore in orientamento orizzontale (ruotato di 270 o -90 gradi).

Ecco il buffer di immagine del sensore della fotocamera nella Figura 4:

Sensore della fotocamera ruotato in orientamento orizzontale con immagine capovolta
            verso il basso.

Il buffer deve essere ruotato di 90 gradi in senso orario per regolarlo in base al sensore orientamento:

Sensore della fotocamera con orientamento verticale con immagine ruotata,
            in alto a sinistra.

Quindi il buffer viene ruotato di 270 gradi in senso antiorario per tenere conto del dispositivo rotazione:

Sensore della fotocamera ruotato in orientamento orizzontale con immagine
            in posizione verticale.

Proporzioni

Le proporzioni del display cambiano anche quando cambia l'orientamento del dispositivo i pieghevoli si piegano e si aprono quando le finestre vengono ridimensionate in modalità multi-finestra ambienti e quando le app si aprono su display secondari.

Il buffer d'immagine del sensore della fotocamera deve essere orientato e scalato in modo da corrispondere orientamento e proporzioni dell'elemento UI del mirino come UI cambia l'orientamento in modo dinamico, con o senza cambio di dispositivo orientamento.

In nuovi fattori di forma o in ambienti multi-finestra o multi-display, se l'app presuppone che l'anteprima della fotocamera abbia lo stesso orientamento del dispositivo (orizzontale o verticale) l'anteprima potrebbe essere orientata o ridimensionata in modo errato in modo errato, o entrambe le cose.

Dispositivo pieghevole aperto con l'anteprima della fotocamera verticale attivata
            di lato.
. Figura 5. Il dispositivo pieghevole passa dalla modalità verticale a quella orizzontale proporzioni, ma il sensore della fotocamera rimane in orientamento verticale.

Nella figura 5, l'applicazione ha ipotizzato erroneamente che il dispositivo fosse ruotato di 90 gradi gradi in senso antiorario; per cui l'app ha ruotato l'anteprima dello stesso numero.

Dispositivo pieghevole aperto con l'anteprima della fotocamera in verticale, ma schiacciata
            a causa di una scalabilità errata.
. Figura 6. Il dispositivo pieghevole passa dalla modalità verticale a quella orizzontale proporzioni, ma il sensore della fotocamera rimane in orientamento verticale.

Nella Figura 6, l'app non ha regolato le proporzioni del buffer di immagine per consente di ridimensionarla in modo adeguato alle nuove dimensioni dell'interfaccia utente di anteprima della fotocamera .

Le app della fotocamera con orientamento fisso di solito riscontrano problemi sui pieghevoli e Altri dispositivi con schermi di grandi dimensioni, come i laptop:

L'anteprima della fotocamera sul laptop è in verticale, ma l'UI dell'app è ruotata.
. Figura 7. App verticale con orientamento fisso su un computer laptop.

Nella Figura 7, l'UI dell'app Fotocamera è ruotata perché l'orientamento dell'app è limitato solo alla modalità verticale. L'immagine del mirino è orientata correttamente rispetto al sensore della fotocamera.

Inserisci la modalità Ritratto

App fotocamera che non supportano la modalità multi-finestra (resizeableActivity="false") e limitarne l'orientamento (screenOrientation="portrait") o screenOrientation="landscape") può essere attivata in modalità Ritratto sui dispositivi con schermi grandi per orientarsi correttamente l'anteprima della fotocamera.

Inserimento di app solo con orientamento verticale in modalità verticale anche se le proporzioni del display sono orizzontali. Le app solo in orizzontale hanno un formato letterbox con orientamento orizzontale anche se le proporzioni del display sono verticali. L'immagine della fotocamera viene ruotata per allinearla con l'interfaccia utente dell'app, ritagliata per adattarla alle proporzioni dell'anteprima della fotocamera e e ridimensionato per riempire l'anteprima.

La modalità Ritratto inserita viene attivata quando le proporzioni dell'immagine della fotocamera tra il sensore e le proporzioni dell'attività principale dell'applicazione non corrispondono.

Anteprima della fotocamera e UI dell'app con il corretto orientamento verticale sul laptop.
            L'immagine di anteprima larga viene ridimensionata e ritagliata per essere adattata al formato verticale
            orientamento.
. Figura 8. App Ritratto con orientamento fisso in modalità Ritratto inserita su un laptop.

Nella Figura 8, l'app della fotocamera solo verticale è stata ruotata per visualizzare l'UI in posizione verticale sul display del laptop. L'app è in formato letterbox a causa della differenza di proporzioni tra l'app verticale e la visualizzazione orizzontale. La fotocamera l'immagine di anteprima è stata ruotata per compensare la rotazione dell'interfaccia utente dell'app (a causa inserisci la modalità Ritratto) e l'immagine è stata ritagliata e ridimensionata per adattarsi verticale, per ridurre il campo visivo.

Ruota, ritaglia, ridimensiona

La modalità Ritratto inserita viene attivata per un'app della fotocamera solo verticale su un display con proporzioni orizzontali:

L'anteprima della fotocamera sul laptop è in verticale, ma l'UI dell'app è ruotata.
. Figura 9. App verticale con orientamento fisso su un laptop.

L'app ha un letterbox con orientamento verticale:

App ruotata in orientamento verticale e letterbox. L'immagine è
            lateralmente, in alto a destra.

L'immagine della fotocamera viene ruotata di 90 gradi per regolare il riorientamento della dell'app:

Immagine del sensore ruotata di 90 gradi per mantenerla in verticale.

L'immagine viene ritagliata in base alle proporzioni dell'anteprima della fotocamera, quindi ridimensionata a riempi l'anteprima (il campo visivo è ridotto):

Immagine della fotocamera ritagliata per riempire l'anteprima della fotocamera.

Sui dispositivi pieghevoli, l'orientamento del sensore della fotocamera può essere verticale mentre le proporzioni del display sono orizzontali:

Anteprima della fotocamera e UI dell'app ruotate lateralmente rispetto al display largo e aperto.
. Figura 10. Dispositivo aperto con app della fotocamera solo in verticale e proporzioni diverse del sensore e del display della fotocamera.

Poiché l'anteprima della fotocamera viene ruotata per regolare l'orientamento del sensore, l'immagine sia orientata correttamente nel mirino, mentre l'app solo Ritratto è ruotata.

La modalità Ritratto inserita richiede l'inserimento dell'app in formato Lettera solo con orientamento verticale per orientare correttamente l'anteprima dell'app e della fotocamera:

App in formato Letterbox con orientamento verticale con anteprima della fotocamera
            in posizione verticale sul dispositivo pieghevole.

API

A partire da Android 12 (livello API 31) le app possono anche controllare esplicitamente il formato verticale mediante SCALER_ROTATE_AND_CROP proprietà del CaptureRequest .

Il valore predefinito è SCALER_ROTATE_AND_CROP_AUTO, che consente al sistema di richiamare la modalità verticale integrata. SCALER_ROTATE_AND_CROP_90 è il comportamento del riquadro in modalità Ritratto, come descritto sopra.

Non tutti i dispositivi supportano tutti i valori SCALER_ROTATE_AND_CROP. Per ottenere un elenco dei valori supportati, CameraCharacteristics#SCALER_AVAILABLE_ROTATE_AND_CROP_MODES

FotocameraX

La raccolta Jetpack CameraX consente di creare un mirino della fotocamera che si adatti all'orientamento del sensore la rotazione dei dispositivi è un'attività semplice.

L'elemento di layout PreviewView crea un'anteprima della fotocamera, regolando automaticamente l'orientamento del sensore, la rotazione e il ridimensionamento dei dispositivi. PreviewView mantiene le proporzioni del dell'immagine della fotocamera FILL_CENTER tipo di scala, che centra l'immagine, ma potrebbe ritagliarla per farla corrispondere alle dimensioni di PreviewView. Per modificare l'immagine della fotocamera in modalità letterbox, imposta il tipo di scala su FIT_CENTER

Per apprendere le nozioni di base sulla creazione di un'anteprima della fotocamera con PreviewView, consulta Implementa un'anteprima.

Per un'implementazione di esempio completa, consulta CameraXBasic su GitHub.

Mirino per fotocamera

Analogamente al caso d'uso dell'Anteprima, il CameraViewfinder offre una serie di strumenti per semplificare la creazione di un'anteprima della fotocamera. Non dipende da CameraX Core, quindi puoi integrarlo perfettamente nel tuo il codebase Camera2 esistente.

Invece di utilizzare Surface puoi utilizzare CameraViewfinder per visualizzare il feed videocamera per Camera2.

CameraViewfinder utilizza internamente TextureView o SurfaceView per visualizzare il feed della videocamera e applica su di esse le trasformazioni richieste visualizzare correttamente il mirino. Ciò comporta la correzione di proporzioni, scala e rotazione.

Per richiedere la piattaforma dall'oggetto CameraViewfinder, devi: crea un ViewfinderSurfaceRequest.

Questa richiesta contiene i requisiti relativi alla risoluzione della superficie e al dispositivo della fotocamera informazioni da CameraCharacteristics.

Chiamata a requestSurfaceAsync() in corso... invia la richiesta al fornitore di Surface, che è un TextureView o SurfaceView e riceve ListenableFuture di Surface.

Chiamata a markSurfaceSafeToRelease() in corso... comunica al fornitore della piattaforma che la piattaforma non è necessaria e correlata possono essere svincolate.

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

Visualizzazione di superficie

SurfaceView è un approccio diretto alla creazione dell'anteprima della fotocamera se quest'ultima non richiedono l'elaborazione e non sono animati.

SurfaceView ruota automaticamente il buffer d'immagine del sensore della fotocamera per adattarlo l'orientamento del display, tenendo conto sia dell'orientamento del sensore che del dispositivo la rotazione. Tuttavia, il buffer di immagine viene ridimensionato per adattarsi a SurfaceView dimensioni senza alcuna considerazione delle proporzioni.

Devi assicurarti che le proporzioni del buffer di immagine corrispondano di SurfaceView, che puoi ottenere scalando i contenuti di SurfaceView nella classe onMeasure() :

(il codice sorgente di computeRelativeRotation() è in Rotazione relativa di seguito.

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

Per ulteriori dettagli sull'implementazione di SurfaceView come anteprima della fotocamera, consulta Orientamenti fotocamera.

Visualizzazione texture

TextureView ha prestazioni inferiori SurfaceView—e altro ancora, ma TextureView offre il massimo controllo dell'anteprima della fotocamera.

TextureView ruota il buffer d'immagine del sensore in base all'orientamento, ma non gestisce la rotazione del dispositivo o il ridimensionamento dell'anteprima.

La scalabilità e la rotazione possono essere codificate Trasformazione della matrice. Per scoprire come scalare e ruotare correttamente un TextureView, consulta Supportare le superfici ridimensionabili nell'app Fotocamera

Rotazione relativa

La rotazione relativa del sensore della videocamera è il tempo di rotazione necessario per allinea l'output del sensore della fotocamera all'orientamento del dispositivo.

La rotazione relativa viene utilizzata da componenti quali SurfaceView e TextureView per determinare i fattori di ridimensionamento x e y per l'immagine di anteprima. È utilizzata anche per specificare la rotazione del buffer immagine del sensore.

La CameraCharacteristics e Le classi Surface consentono il calcolo Rotazione relativa del sensore della videocamera:

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

Metriche finestra

Le dimensioni dello schermo non devono essere utilizzate per determinare le dimensioni della fotocamera mirino; l'app Fotocamera potrebbe essere in esecuzione in una parte dello schermo in modalità multi-finestra sui dispositivi mobili o in modalità libero su ChromeOS.

WindowManager#getCurrentWindowMetrics() (aggiunto nel livello API 30) restituisce la dimensione della finestra dell'applicazione anziché le dimensioni dello schermo. Metodi della libreria Jetpack WindowManager WindowMetricsCalculator#computeCurrentWindowMetrics() e WindowInfoTracker#currentWindowMetrics() offrono un supporto simile, con compatibilità con le versioni precedenti al livello API 14.

Rotazione: 180°

Una rotazione di 180 gradi di un dispositivo (ad esempio, dall'orientamento naturale a l'orientamento naturale al contrario) non attiva onConfigurationChanged() di Google. Di conseguenza, l'anteprima della fotocamera potrebbe essere capovolta.

Per rilevare una rotazione di 180 gradi, implementa una DisplayListener e controlla la rotazione del dispositivo con una chiamata Display#getRotation() nel onDisplayChanged() di Google.

Risorse esclusive

Prima di Android 10, solo l'attività più in alto visibile in una modalità multi-finestra era nello stato RESUMED. Questo non era chiaro per gli utenti perché il sistema non ha fornito alcuna indicazione di quale attività è stata ripresa.

Android 10 (livello API 29) ha introdotto il ripristino multiplo in cui tutte le attività visibili sono nello stato RESUMED. Le attività visibili possono comunque accedere all'PAUSED ad esempio se, ad esempio, un'attività trasparente si trova sopra l'attività o non sia possibile mettere a fuoco l'attività, ad esempio in modalità Picture in picture (vedi supporto di Picture in picture).

Un'applicazione che utilizza la fotocamera, il microfono o qualsiasi altra funzione la risorsa singleton con livello API 29 o successivo deve supportare la ripresa multipla. Per Ad esempio, se vuoi usare la fotocamera per tre attività riprese, solo una potrà per accedere a questa risorsa esclusiva. Ogni attività deve implementare un onDisconnected() per essere a conoscenza dell'accesso preventivo alla videocamera da una priorità più elevata attività.

Per ulteriori informazioni, vedi Riprendi multipli.

Risorse aggiuntive