Questo argomento illustra come configurare i casi d'uso di CameraX all'interno dell'app per:
immagini con le informazioni di rotazione corrette, che provengano da
ImageAnalysis
o il caso d'uso ImageCapture
. Così:
- Il valore
Analyzer
del caso d'usoImageAnalysis
dovrebbe ricevere i frame con la rotazione corretta. - Il caso d'uso
ImageCapture
deve scattare foto con la rotazione corretta.
Terminologia
Questo argomento utilizza la seguente terminologia, quindi è importante comprendere il significato di ogni termine è importante:
- Orientamento del display
- Si riferisce a quale lato del dispositivo è rivolto verso l'alto e può essere Uno dei quattro valori: verticale, orizzontale, verticale invertito o inversa. panorama.
- Rotazione del display
- Questo è il valore restituito da
Display.getRotation()
e rappresenta i gradi di rotazione del dispositivo in senso antiorario da il suo orientamento naturale. - Rotazione target
- Rappresenta il numero di gradi di rotazione il dispositivo in senso orario per raggiungere il suo orientamento naturale.
Come determinare la rotazione target
I seguenti esempi mostrano come determinare la rotazione target di un dispositivo in base al suo orientamento naturale.
Esempio 1: orientamento naturale verticale
Esempio di dispositivo: Pixel 3 XL | |
---|---|
Orientamento naturale = verticale Rotazione del display = 0 |
|
Orientamento naturale = verticale Rotazione del display = 90 |
Esempio 2: orientamento naturale orizzontale
Esempio di dispositivo: Pixel C | |
---|---|
Orientamento naturale = orizzontale Rotazione del display = 0 |
|
Orientamento naturale = orizzontale Rotazione del display = 270 |
Rotazione dell'immagine
Qual è il punto giusto? In Android l'orientamento del sensore è una costante che rappresenta i gradi (0, 90, 180, 270) da cui viene ruotato il sensore nella parte superiore del dispositivo quando si trova in una posizione naturale. Per tutte le nei diagrammi, la rotazione dell'immagine descrive come dovrebbero essere ruotato in senso orario per apparire in verticale.
I seguenti esempi mostrano come deve essere la rotazione dell'immagine in base al orientamento del sensore della fotocamera. Inoltre, presuppongono che la rotazione target sia impostata sul la rotazione del display.
Esempio 1: sensore ruotato di 90 gradi
Esempio di dispositivo: Pixel 3 XL | |
---|---|
Rotazione del display = 0 |
|
Rotazione del display = 90 |
Esempio 2: sensore ruotato di 270 gradi
Esempio di dispositivo: Nexus 5X | |
---|---|
Rotazione del display = 0 |
|
Rotazione del display = 90 |
Esempio 3: sensore ruotato di 0 gradi
Esempio di dispositivo: Pixel C (tablet) | |
---|---|
Rotazione del display = 0 |
|
Rotazione del display = 270 |
Calcolo della rotazione di un'immagine
Analisi delle immagini
Il dispositivo Analyzer
di ImageAnalysis
riceve immagini dalla fotocamera sotto forma di
ImageProxy
sec. Ogni immagine contiene informazioni sulla rotazione, a cui è possibile accedere
tramite:
val rotation = imageProxy.imageInfo.rotationDegrees
Questo valore rappresenta i gradi di rotazione dell'immagine
in senso orario per corrispondere alla rotazione target di ImageAnalysis
. Nel contesto di un
Per l'app per Android, la rotazione target di ImageAnalysis
corrisponde in genere a
l'orientamento dello schermo.
Acquisizione di immagini
Un callback è collegato a un'istanza ImageCapture
per segnalare quando un'acquisizione
che il risultato sia pronto. Il risultato può essere l'immagine acquisita o un errore.
Quando scatti una foto, il callback fornito può essere uno dei seguenti: tipi:
OnImageCapturedCallback
: riceve un'immagine con accesso in memoria nel diImageProxy
.OnImageSavedCallback
: richiamata quando l'immagine acquisita è stata richiamata archiviati correttamente nella località specificataImageCapture.OutputFileOptions
. Le opzioni possono specificare unFile
, unOutputStream
o una località pressoMediaStore
.
La rotazione dell'immagine acquisita, indipendentemente dal formato (ImageProxy
,
File
, OutputStream
, MediaStore Uri
) rappresenta i gradi di rotazione per
che deve essere ruotata in senso orario per l'immagine acquisita per farla corrispondere a quella di ImageCapture
la rotazione target, che di solito nel contesto di un'app per Android
corrispondano all'orientamento dello schermo.
Per recuperare la rotazione dell'immagine acquisita, procedi in uno dei seguenti modi: modi:
ImageProxy
val rotation = imageProxy.imageInfo.rotationDegrees
File
val exif = Exif.createFromFile(file) val rotation = exif.rotation
OutputStream
val byteArray = outputStream.toByteArray() val exif = Exif.createFromInputStream(ByteArrayInputStream(byteArray)) val rotation = exif.rotation
MediaStore uri
val inputStream = contentResolver.openInputStream(outputFileResults.savedUri) val exif = Exif.createFromInputStream(inputStream) val rotation = exif.rotation
Verificare la rotazione di un'immagine
I casi d'uso ImageAnalysis
e ImageCapture
ricevono ImageProxy
dal
videocamera dopo che la richiesta di acquisizione è andata a buon fine. ImageProxy
aggrega un'immagine e
informazioni su quest'ultimo, inclusa la rotazione. Queste informazioni sulla rotazione
rappresenta i gradi di rotazione dell'immagine per adattarla all'uso
la rotazione target della richiesta.
Linee guida sulla rotazione target per Image Capture/ImageAnalysis
Poiché molti dispositivi non ruotano per l'orientamento verticale o orizzontale invertito per impostazione predefinita, alcune app Android non supportano questi orientamenti. Indica se un'app la supporti o meno cambia il modo in cui la rotazione target dei casi d'uso può essere aggiornato.
Di seguito sono riportate due tabelle che definiscono come mantenere sincronizzata la rotazione dei target dei casi d'uso con la rotazione del display. La prima mostra come farlo supportando quattro orientamenti: la seconda gestisce solo gli orientamenti di rotazione del dispositivo per impostazione predefinita.
Per scegliere quali linee guida seguire nella tua app:
Verifica se la fotocamera
Activity
dell'app ha un orientamento bloccato, una orientamento sbloccato o se sostituisce le modifiche alla configurazione dell'orientamento.Decidi se la videocamera
Activity
dell'app deve gestire tutti e quattro i dispositivi orientamenti (verticale, verticale, orizzontale e orizzontale invertito), o, se deve gestire solo gli orientamenti, supporta per impostazione predefinita.
Supporta tutti e quattro gli orientamenti
Questa tabella cita alcune linee guida da seguire nei casi in cui il dispositivo non viene ruotata in verticale. Lo stesso vale per i dispositivi non ruotare in orizzontale.
Scenario | Linee guida | Modalità a finestra singola | Modalità schermo diviso multi-finestra |
---|---|---|---|
Orientamento sbloccato |
Configura i casi d'uso ogni
volta che viene creato Activity , ad esempio
Callback onCreate() di Activity .
|
||
Usa le app di OrientationEventListener
onOrientationChanged()
All'interno del callback, aggiorna la rotazione target dei casi d'uso. In questo modo vengono gestiti i casi in cui il sistema
ricrea l'Activity anche dopo un cambio di orientamento, ad esempio
ad esempio quando il dispositivo
viene ruotato di 180 gradi.
|
Gestisce anche quando il display è invertito l'orientamento verticale e il dispositivo non si ruota per invertire l'orientamento verticale predefinito. |
Gestisce anche i casi in cui Activity non è
ricreata quando il dispositivo ruota (ad esempio di 90 gradi). Ciò si verifica il giorno
dispositivi con fattori di forma piccoli quando l'app occupa metà dello schermo e su schermi più grandi
quando l'app occupa due terzi dello schermo.
|
|
(Facoltativo) Imposta il valore screenOrientation di Activity
proprietà a fullSensor nella zona AndroidManifest
.
|
In questo modo l'UI è in posizione verticale quando il dispositivo è invertito.
verticale e consente che l'elemento Activity venga ricreato
ogni volta che il dispositivo viene ruotato di 90 gradi.
|
Non ha effetto sui dispositivi che non ruotano in orientamento verticale inverso predefinito. La modalità multi-finestra non è supportata quando il display è in una invertito l'orientamento verticale. | |
Orientamento bloccato |
I casi d'uso devono essere configurati una sola volta,
Activity viene creato per la prima volta, ad esempio nell'Activity
Chiamata onCreate() .
|
||
Usa le app di OrientationEventListener
onOrientationChanged()
All'interno del callback, aggiorna la rotazione target dei casi d'uso, ad eccezione di Anteprima.
|
Gestisce anche i casi in cui Activity non è
ricreata quando il dispositivo ruota (ad esempio di 90 gradi). Ciò si verifica il giorno
dispositivi con fattori di forma piccoli quando l'app occupa metà dello schermo e su schermi più grandi
quando l'app occupa due terzi dello schermo.
|
||
Modifiche all'orientamento sostituite |
I casi d'uso devono essere configurati una sola volta,
Activity viene creato per la prima volta, ad esempio nell'Activity
Chiamata onCreate() .
|
||
Usa le app di OrientationEventListener
onOrientationChanged()
All'interno del callback, aggiorna la rotazione target dei casi d'uso.
|
Gestisce anche i casi in cui Activity non è
ricreata quando il dispositivo ruota (ad esempio di 90 gradi). Ciò si verifica il giorno
dispositivi con fattori di forma piccoli quando l'app occupa metà dello schermo e su schermi più grandi
quando l'app occupa due terzi dello schermo.
|
||
(Facoltativo) Imposta la proprietà screenOrientation dell'attività su fullSensor in il file AndroidManifest. | Consente che l'UI sia in posizione verticale quando il dispositivo è in verticale. | Non ha effetto sui dispositivi che non ruotano in orientamento verticale inverso predefinito. La modalità multi-finestra non è supportata quando il display è in una invertito l'orientamento verticale. |
Sono supportati solo gli orientamenti supportati dal dispositivo
Supporta solo gli orientamenti supportati per impostazione predefinita dal dispositivo (ad esempio, potrebbero non includere l'orientamento verticale/orizzontale inverso).
Scenario | Linee guida | Modalità schermo diviso multi-finestra |
---|---|---|
Orientamento sbloccato |
Configura i casi d'uso ogni
volta che viene creato Activity , ad esempio
Callback onCreate() di Activity .
|
|
Usa le app di DisplayListener
onDisplayChanged() All'interno
il callback di destinazione, aggiorna la rotazione target dei casi d'uso, ad esempio quando
dispositivo ruotato di 180 gradi.
|
Gestisce anche i casi in cui Activity non è
ricreata quando il dispositivo ruota (ad esempio di 90 gradi). Ciò si verifica il giorno
dispositivi con fattori di forma piccoli quando l'app occupa metà dello schermo e su schermi più grandi
quando l'app occupa due terzi dello schermo.
|
|
Orientamento bloccato |
I casi d'uso devono essere configurati una sola volta,
Activity viene creato per la prima volta, ad esempio nell'Activity
Chiamata onCreate() .
|
|
Usa le app di OrientationEventListener
onOrientationChanged()
All'interno del callback, aggiorna la rotazione target dei casi d'uso.
|
Gestisce anche i casi in cui Activity non è
ricreata quando il dispositivo ruota (ad esempio di 90 gradi). Ciò si verifica il giorno
dispositivi con fattori di forma piccoli quando l'app occupa metà dello schermo e su schermi più grandi
quando l'app occupa due terzi dello schermo.
|
|
Modifiche all'orientamento sostituite |
I casi d'uso devono essere configurati una sola volta,
Activity viene creato per la prima volta, ad esempio nell'Activity
Chiamata onCreate() .
|
|
Usa le app di DisplayListener
onDisplayChanged() All'interno
il callback di destinazione, aggiorna la rotazione target dei casi d'uso, ad esempio quando
dispositivo ruotato di 180 gradi.
|
Gestisce anche i casi in cui Activity non è
ricreata quando il dispositivo ruota (ad esempio di 90 gradi). Ciò si verifica il giorno
dispositivi con fattori di forma piccoli quando l'app occupa metà dello schermo e su schermi più grandi
quando l'app occupa due terzi dello schermo.
|
Orientamento sbloccato
Activity
ha un orientamento sbloccato quando si trova nell'orientamento del display
(orizzontale o verticale) corrisponda all'orientamento fisico del dispositivo, con
tranne per l'orientamento verticale/orizzontale, che non è supportato da alcuni dispositivi
per impostazione predefinita. Per forzare la rotazione del dispositivo in tutti e quattro gli orientamenti, imposta il valore
proprietà screenOrientation
di Activity
a fullSensor
.
In modalità multi-finestra, un dispositivo che non supporta la modalità verticale/orizzontale invertita
per impostazione predefinita non viene ruotata in verticale/orizzontale, anche quando
La proprietà screenOrientation
è impostata su fullSensor
.
<!-- The Activity has an unlocked orientation, but might not rotate to reverse portrait/landscape in single-window mode if the device doesn't support it by default. --> <activity android:name=".UnlockedOrientationActivity" /> <!-- The Activity has an unlocked orientation, and will rotate to all four orientations in single-window mode. --> <activity android:name=".UnlockedOrientationActivity" android:screenOrientation="fullSensor" />
Orientamento bloccato
Un display ha un orientamento bloccato quando rimane nello stesso orientamento
(orizzontale o verticale) a prescindere dall'orientamento fisico
dispositivo. Puoi farlo specificando un valore screenOrientation
di Activity
all'interno della relativa dichiarazione nel file AndroidManifest.xml
.
Quando il display è bloccato, il sistema non distrugge e
ricrea Activity
mentre il dispositivo viene ruotato.
<!-- The Activity keeps a portrait orientation even as the device rotates. --> <activity android:name=".LockedOrientationActivity" android:screenOrientation="portrait" />
Modifiche alla configurazione dell'orientamento sostituite
Quando un elemento Activity
sostituisce le modifiche alla configurazione dell'orientamento, il sistema
non lo distrugge e lo ricrea quando cambia l'orientamento fisico del dispositivo.
Il sistema aggiorna però l'UI in base all'orientamento fisico del dispositivo.
<!-- The Activity's UI might not rotate in reverse portrait/landscape if the device doesn't support it by default. --> <activity android:name=".OrientationConfigChangesOverriddenActivity" android:configChanges="orientation|screenSize" /> <!-- The Activity's UI will rotate to all 4 orientations in single-window mode. --> <activity android:name=".OrientationConfigChangesOverriddenActivity" android:configChanges="orientation|screenSize" android:screenOrientation="fullSensor" />
Configurazione dei casi d'uso della fotocamera
Negli scenari descritti sopra, i casi d'uso della fotocamera possono essere configurati quando
Activity
è stato creato per la prima volta.
Nel caso di un Activity
con orientamento sbloccato, questa configurazione è completa
ogni volta che il dispositivo viene ruotato, mentre il sistema distrugge e ricrea la
Activity
sulle modifiche di orientamento. Ciò porta ai casi d'uso che impostano
la rotazione del target in modo che corrisponda all'orientamento del display per impostazione predefinita.
Nel caso di Activity
con orientamento bloccato o con override
la configurazione dell'orientamento cambia. Questa configurazione viene eseguita una sola volta, quando Activity
viene creato prima di tutto.
class CameraActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val cameraProcessFuture = ProcessCameraProvider.getInstance(this) cameraProcessFuture.addListener(Runnable { val cameraProvider = cameraProcessFuture.get() // By default, the use cases set their target rotation to match the // display’s rotation. val preview = buildPreview() val imageAnalysis = buildImageAnalysis() val imageCapture = buildImageCapture() cameraProvider.bindToLifecycle( this, cameraSelector, preview, imageAnalysis, imageCapture) }, mainExecutor) } }
Configurazione di OrientationEventListener
L'utilizzo di un OrientationEventListener
ti consente di aggiornare continuamente il target
la rotazione dei casi d'uso della fotocamera quando cambia l'orientamento del dispositivo.
class CameraActivity : AppCompatActivity() { private val orientationEventListener by lazy { object : OrientationEventListener(this) { override fun onOrientationChanged(orientation: Int) { if (orientation == ORIENTATION_UNKNOWN) { return } val rotation = when (orientation) { in 45 until 135 -> Surface.ROTATION_270 in 135 until 225 -> Surface.ROTATION_180 in 225 until 315 -> Surface.ROTATION_90 else -> Surface.ROTATION_0 } imageAnalysis.targetRotation = rotation imageCapture.targetRotation = rotation } } } override fun onStart() { super.onStart() orientationEventListener.enable() } override fun onStop() { super.onStop() orientationEventListener.disable() } }
Configurazione di DisplayListener
L'uso di DisplayListener
ti consente di aggiornare la rotazione del target della videocamera
casi d'uso in determinate situazioni, ad esempio quando il sistema non elimina
e ricrea Activity
dopo che il dispositivo ruota di 180 gradi.
class CameraActivity : AppCompatActivity() { private val displayListener = object : DisplayManager.DisplayListener { override fun onDisplayChanged(displayId: Int) { if (rootView.display.displayId == displayId) { val rotation = rootView.display.rotation imageAnalysis.targetRotation = rotation imageCapture.targetRotation = rotation } } override fun onDisplayAdded(displayId: Int) { } override fun onDisplayRemoved(displayId: Int) { } } override fun onStart() { super.onStart() val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager displayManager.registerDisplayListener(displayListener, null) } override fun onStop() { super.onStop() val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager displayManager.unregisterDisplayListener(displayListener) } }