Il framework Android include il supporto per varie videocamere e funzionalità della videocamera disponibili sui dispositivi, consentendoti di acquisire immagini e video nelle tue applicazioni. Questo documento descrive un approccio rapido e semplice all'acquisizione di immagini e video e delinea un approccio avanzato per creare esperienze fotografiche personalizzate per gli utenti.
Nota:questa pagina descrive la
classe Camera
, che è stata ritirata. Ti consigliamo di utilizzare la libreria Jetpack CameraX o, per casi d'uso specifici, la classe camera2
. CameraX e Camera2 funzionano su Android 5.0 (livello API 21) e versioni successive.
Consulta le seguenti risorse correlate:
Considerazioni
Prima di consentire alla tua applicazione di utilizzare le videocamere sui dispositivi Android, devi considerare alcune domande su come la tua app intende utilizzare questa funzionalità hardware.
- Requisito fotocamera: l'utilizzo di una fotocamera è così importante per la tua applicazione che non vuoi che venga installata su un dispositivo che non ne ha una? In questo caso, devi dichiarare il requisito della videocamera nel manifest.
- Foto rapida o Fotocamera personalizzata: in che modo la tua applicazione utilizzerà la fotocamera? Ti interessa solo scattare una foto o registrare un breve video o la tua applicazione fornirà un nuovo modo di utilizzare le fotocamere? Per scattare una foto o registrare un breve video, valuta la possibilità di Utilizzare le app fotocamera esistenti. Per sviluppare una funzionalità della videocamera personalizzata, consulta la sezione Creare un'app fotocamera.
- Requisito per i servizi in primo piano: quando la tua app interagisce con la fotocamera? Su Android 9 (livello API 28) e versioni successive, le app in esecuzione in background non possono accedere alla fotocamera. Pertanto, devi utilizzare la fotocamera quando la tua app è in primo piano o come parte di un servizio in primo piano.
- Spazio di archiviazione: le immagini o i video generati dalla tua applicazione sono destinati a essere visibili solo alla tua applicazione o condivisi in modo che altre applicazioni come Galleria o altre app multimediali e social possano utilizzarli? Vuoi che le immagini e i video siano disponibili anche se la tua applicazione è disinstallata? Consulta la sezione Salvataggio dei file multimediali per scoprire come implementare queste opzioni.
Nozioni di base
Il framework Android supporta l'acquisizione di immagini e video tramite l'API android.hardware.camera2
o la fotocamera Intent
. Ecco le classi
pertinenti:
android.hardware.camera2
- Questo pacchetto è l'API principale per il controllo delle videocamere del dispositivo. Può essere utilizzato per scattare foto o registrare video quando crei un'applicazione per la fotocamera.
Camera
- Questa classe è l'API precedente ritirata per il controllo delle videocamere del dispositivo.
SurfaceView
- Questa classe viene utilizzata per presentare all'utente un'anteprima della videocamera in tempo reale.
MediaRecorder
- Questa classe viene utilizzata per registrare video dalla videocamera.
Intent
- Un tipo di azione di intent
MediaStore.ACTION_IMAGE_CAPTURE
oMediaStore.ACTION_VIDEO_CAPTURE
può essere utilizzato per acquisire immagini o video senza utilizzare direttamente l'oggettoCamera
.
Dichiarazioni del manifest
Prima di iniziare lo sviluppo dell'applicazione con l'API Camera, devi assicurarti che il manifest contenga le dichiarazioni appropriate per consentire l'utilizzo dell'hardware della videocamera e di altre funzionalità correlate.
- Autorizzazione fotocamera: la tua applicazione deve richiedere l'autorizzazione per utilizzare la fotocamera di un dispositivo.
<uses-permission android:name="android.permission.CAMERA" />
Nota:se utilizzi la videocamera richiamando un'app per la videocamera esistente, la tua applicazione non deve richiedere questa autorizzazione.
- Funzionalità della fotocamera: la tua applicazione deve anche dichiarare l'utilizzo delle funzionalità della fotocamera,
ad esempio:
<uses-feature android:name="android.hardware.camera" />
Per un elenco delle funzionalità della videocamera, consulta il manifest Features Reference.
L'aggiunta di funzionalità della fotocamera al manifest fa sì che Google Play impedisca l'installazione dell'applicazione su dispositivi che non includono una fotocamera o non supportano le funzionalità della fotocamera che specifichi. Per saperne di più sull'utilizzo del filtro basato sulle funzionalità con Google Play, consulta Google Play e il filtro basato sulle funzionalità.
Se la tua applicazione può utilizzare una fotocamera o una funzionalità della fotocamera per il corretto funzionamento, ma non la richiede, devi specificarlo nel manifest includendo l'attributo
android:required
e impostandolo sufalse
:<uses-feature android:name="android.hardware.camera" android:required="false" />
- Autorizzazione di archiviazione: la tua applicazione può salvare immagini o video nella
memoria esterna del dispositivo (scheda SD) se ha come target Android 10 (livello API 29) o
versioni precedenti e specifica quanto segue nel manifest.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- Autorizzazione di registrazione audio: per registrare l'audio con l'acquisizione video, la tua
applicazione deve richiedere l'autorizzazione di acquisizione audio.
<uses-permission android:name="android.permission.RECORD_AUDIO" />
-
Autorizzazione di accesso alla posizione: se la tua applicazione tagga le immagini con informazioni sulla posizione GPS, devi richiedere l'autorizzazione
ACCESS_FINE_LOCATION
. Tieni presente che, se la tua app ha come target Android 5.0 (livello API 21) o versioni successive, devi anche dichiarare che utilizza il GPS del dispositivo:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ... <!-- Needed only if your app targets Android 5.0 (API level 21) or higher. --> <uses-feature android:name="android.hardware.location.gps" />
Per saperne di più su come ottenere la posizione dell'utente, consulta Strategie di localizzazione.
Utilizzo di app per la fotocamera esistenti
Un modo rapido per attivare l'acquisizione di immagini o video nella tua applicazione senza molto codice aggiuntivo
è utilizzare un Intent
per richiamare un'applicazione fotocamera Android esistente.
I dettagli sono descritti nelle lezioni di addestramento
Scattare foto in modo semplice e
Registrare video in modo semplice.
Creazione di un'app fotocamera
Alcuni sviluppatori potrebbero richiedere un'interfaccia utente della videocamera personalizzata in base all'aspetto della loro applicazione o che fornisca funzionalità speciali. Scrivere il proprio codice di acquisizione delle immagini può offrire un'esperienza più coinvolgente per gli utenti.
Nota: la seguente guida riguarda l'API Camera
precedente, deprecata. Per applicazioni della fotocamera nuove o avanzate, è consigliata l'API android.hardware.camera2
più recente.
I passaggi generali per creare un'interfaccia della videocamera personalizzata per la tua applicazione sono i seguenti:
- Rileva e accedi alla fotocamera: crea codice per verificare l'esistenza di fotocamere e richiedere l'accesso.
- Crea una classe di anteprima: crea una classe di anteprima della videocamera che estende
SurfaceView
e implementa l'interfacciaSurfaceHolder
. Questa classe mostra l'anteprima delle immagini in diretta della videocamera. - Crea un layout di anteprima: una volta creata la classe di anteprima della videocamera, crea un layout di visualizzazione che incorpori l'anteprima e i controlli dell'interfaccia utente che preferisci.
- Configura i listener per l'acquisizione: collega i listener per i controlli dell'interfaccia per avviare l'acquisizione di immagini o video in risposta alle azioni dell'utente, ad esempio la pressione di un pulsante.
- Acquisizione e salvataggio di file: configura il codice per acquisire immagini o video e salvare l'output.
- Rilascia la fotocamera: dopo aver utilizzato la fotocamera, l'applicazione deve rilasciarla correttamente per l'utilizzo da parte di altre applicazioni.
L'hardware della fotocamera è una risorsa condivisa che deve essere gestita con attenzione in modo che la tua applicazione non entri in conflitto con altre applicazioni che potrebbero volerla utilizzare. Le sezioni seguenti descrivono come rilevare l'hardware della videocamera, come richiedere l'accesso a una videocamera, come acquisire immagini o video e come rilasciare la videocamera quando l'applicazione ha terminato di utilizzarla.
Attenzione: ricordati di rilasciare l'oggetto Camera
chiamando Camera.release()
quando la tua
applicazione non lo usa più. Se l'applicazione non rilascia correttamente la fotocamera, tutti
i tentativi successivi di accesso alla fotocamera, inclusi quelli della tua applicazione, non andranno a buon fine e potrebbero
causare l'arresto della tua applicazione o di altre applicazioni.
Rilevamento dell'hardware della videocamera
Se la tua applicazione non richiede specificamente una fotocamera utilizzando una dichiarazione manifest, devi
controllare se una fotocamera è disponibile in fase di runtime. Per eseguire questo controllo, utilizza il metodo PackageManager.hasSystemFeature()
, come mostrato nel codice di esempio riportato di seguito:
Kotlin
/** Check if this device has a camera */ private fun checkCameraHardware(context: Context): Boolean { if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) { // this device has a camera return true } else { // no camera on this device return false } }
Java
/** Check if this device has a camera */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ // this device has a camera return true; } else { // no camera on this device return false; } }
I dispositivi Android possono avere più fotocamere, ad esempio una fotocamera posteriore per la fotografia e una
fotocamera anteriore per le videochiamate. Android 2.3 (livello API 9) e versioni successive ti consentono di controllare il
numero di fotocamere disponibili su un dispositivo utilizzando il metodo Camera.getNumberOfCameras()
.
Accesso alle videocamere
Se hai stabilito che il dispositivo su cui viene eseguita l'applicazione ha una fotocamera, devi
richiedere l'accesso ottenendo un'istanza di Camera
(a meno che tu non
stia utilizzando un intent per accedere alla fotocamera).
Per accedere alla videocamera principale, utilizza il metodo Camera.open()
e assicurati di rilevare eventuali eccezioni, come mostrato nel codice riportato di seguito:
Kotlin
/** A safe way to get an instance of the Camera object. */ fun getCameraInstance(): Camera? { return try { Camera.open() // attempt to get a Camera instance } catch (e: Exception) { // Camera is not available (in use or does not exist) null // returns null if camera is unavailable } }
Java
/** A safe way to get an instance of the Camera object. */ public static Camera getCameraInstance(){ Camera c = null; try { c = Camera.open(); // attempt to get a Camera instance } catch (Exception e){ // Camera is not available (in use or does not exist) } return c; // returns null if camera is unavailable }
Attenzione:controlla sempre le eccezioni quando utilizzi Camera.open()
. Se non vengono controllate le eccezioni se la videocamera è in
uso o non esiste, l'applicazione verrà chiusa dal sistema.
Sui dispositivi con Android 2.3 (livello API 9) o versioni successive, puoi accedere a videocamere specifiche utilizzando
Camera.open(int)
. Il codice di esempio riportato sopra accederà
alla prima fotocamera posteriore su un dispositivo con più di una fotocamera.
Controllare le funzionalità della videocamera
Una volta ottenuto l'accesso a una videocamera, puoi ottenere ulteriori informazioni sulle sue funzionalità utilizzando
il metodo Camera.getParameters()
e controllando
l'oggetto Camera.Parameters
restituito per le funzionalità supportate. Quando utilizzi
il livello API 9 o versioni successive, utilizza Camera.getCameraInfo()
per determinare se una videocamera si trova sulla parte anteriore
o posteriore del dispositivo e l'orientamento dell'immagine.
Creare un corso di anteprima
Per scattare foto o registrare video in modo efficace, gli utenti devono essere in grado di vedere ciò che vede la videocamera del dispositivo. Una classe di anteprima della videocamera è un SurfaceView
che può visualizzare i dati
dell'immagine in tempo reale provenienti da una videocamera, in modo che gli utenti possano inquadrare e acquisire un'immagine o un video.
Il seguente codice di esempio mostra come creare una classe di anteprima della videocamera di base che può essere
essere inclusa in un layout View
. Questa classe implementa SurfaceHolder.Callback
per acquisire gli eventi di callback
per la creazione e l'eliminazione della visualizzazione, necessari per assegnare l'input di anteprima della videocamera.
Kotlin
/** A basic Camera preview class */ class CameraPreview( context: Context, private val mCamera: Camera ) : SurfaceView(context), SurfaceHolder.Callback { private val mHolder: SurfaceHolder = holder.apply { // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. addCallback(this@CameraPreview) // deprecated setting, but required on Android versions prior to 3.0 setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS) } override fun surfaceCreated(holder: SurfaceHolder) { // The Surface has been created, now tell the camera where to draw the preview. mCamera.apply { try { setPreviewDisplay(holder) startPreview() } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } } override fun surfaceDestroyed(holder: SurfaceHolder) { // empty. Take care of releasing the Camera preview in your activity. } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.surface == null) { // preview surface does not exist return } // stop preview before making changes try { mCamera.stopPreview() } catch (e: Exception) { // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings mCamera.apply { try { setPreviewDisplay(mHolder) startPreview() } catch (e: Exception) { Log.d(TAG, "Error starting camera preview: ${e.message}") } } } }
Java
/** A basic Camera preview class */ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } }
Se vuoi impostare una dimensione specifica per l'anteprima della videocamera, impostala nel metodo surfaceChanged()
come indicato nei commenti precedenti. Quando imposti le dimensioni dell'anteprima, devi
utilizzare i valori di getSupportedPreviewSizes()
.
Non impostare valori arbitrari nel metodo setPreviewSize()
.
Nota:
Con l'introduzione della funzionalità
Multi-Window in Android 7.0 (livello API 24) e versioni successive, non puoi
più presupporre che le proporzioni dell'anteprima siano le stesse della tua attività
anche dopo aver chiamato setDisplayOrientation()
.
A seconda delle dimensioni e delle proporzioni della finestra, potresti dover adattare un'ampia
anteprima della videocamera a un layout con orientamento verticale o viceversa, utilizzando un
layout letterbox.
Posizionamento dell'anteprima in un layout
Una classe di anteprima della videocamera, come l'esempio mostrato nella sezione precedente, deve essere inserita nel layout di un'attività insieme ad altri controlli dell'interfaccia utente per scattare una foto o registrare un video. Questa sezione mostra come creare un layout e un'attività di base per l'anteprima.
Il seguente codice di layout fornisce una visualizzazione molto semplice che può essere utilizzata per visualizzare un'anteprima della videocamera. In questo esempio, l'elemento FrameLayout
deve essere il
contenitore per la classe di anteprima della videocamera. Questo tipo di layout viene utilizzato per sovrapporre informazioni
o controlli aggiuntivi dell'immagine alle immagini di anteprima della videocamera in diretta.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent" > <FrameLayout android:id="@+id/camera_preview" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1" /> <Button android:id="@+id/button_capture" android:text="Capture" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" /> </LinearLayout>
Sulla maggior parte dei dispositivi, l'orientamento predefinito dell'anteprima della videocamera è orizzontale. Questo esempio di layout specifica un layout orizzontale e il codice riportato di seguito corregge l'orientamento dell'applicazione in orizzontale. Per semplificare il rendering di un'anteprima della videocamera, devi modificare l'orientamento dell'attività di anteprima dell'applicazione in orizzontale aggiungendo quanto segue al manifest.
<activity android:name=".CameraActivity" android:label="@string/app_name" android:screenOrientation="landscape"> <!-- configure this activity to use landscape orientation --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
Nota: l'anteprima della videocamera non deve essere in modalità orizzontale.
A partire da Android 2.2 (livello API 8), puoi utilizzare il metodo setDisplayOrientation()
per impostare la
rotazione dell'immagine di anteprima. Per modificare l'orientamento dell'anteprima quando l'utente riorienta lo
smartphone, all'interno del metodo surfaceChanged()
della classe di anteprima, interrompi prima l'anteprima con Camera.stopPreview()
, modifica l'orientamento e poi
avvia di nuovo l'anteprima con Camera.startPreview()
.
Nell'attività per la visualizzazione della videocamera, aggiungi la classe di anteprima all'elemento FrameLayout
mostrato nell'esempio precedente. L'attività della videocamera deve anche
garantire il rilascio della videocamera quando è in pausa o spenta. L'esempio seguente mostra come modificare un'attività della videocamera per allegare la classe di anteprima mostrata in Creazione di una classe di anteprima.
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? = null private var mPreview: CameraPreview? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Create an instance of Camera mCamera = getCameraInstance() mPreview = mCamera?.let { // Create our Preview view CameraPreview(this, it) } // Set the Preview view as the content of our activity. mPreview?.also { val preview: FrameLayout = findViewById(R.id.camera_preview) preview.addView(it) } } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private CameraPreview mPreview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create an instance of Camera mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); } }
Nota:il metodo getCameraInstance()
nell'esempio precedente
si riferisce al metodo di esempio mostrato in Accesso alle videocamere.
Acquisizione di immagini
Dopo aver creato una classe di anteprima e un layout di visualizzazione in cui visualizzarla, puoi iniziare ad acquisire immagini con la tua applicazione. Nel codice dell'applicazione, devi configurare i listener per i controlli dell'interfaccia utente in modo che rispondano a un'azione dell'utente scattando una foto.
Per recuperare un'immagine, utilizza il metodo Camera.takePicture()
. Questo metodo accetta tre parametri che ricevono i dati dalla videocamera.
Per ricevere i dati in formato JPEG, devi implementare un'interfaccia Camera.PictureCallback
per ricevere i dati dell'immagine e
scriverli in un file. Il seguente codice mostra un'implementazione di base dell'interfaccia Camera.PictureCallback
per salvare un'immagine ricevuta dalla videocamera.
Kotlin
private val mPicture = Camera.PictureCallback { data, _ -> val pictureFile: File = getOutputMediaFile(MEDIA_TYPE_IMAGE) ?: run { Log.d(TAG, ("Error creating media file, check storage permissions")) return@PictureCallback } try { val fos = FileOutputStream(pictureFile) fos.write(data) fos.close() } catch (e: FileNotFoundException) { Log.d(TAG, "File not found: ${e.message}") } catch (e: IOException) { Log.d(TAG, "Error accessing file: ${e.message}") } }
Java
private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); if (pictureFile == null){ Log.d(TAG, "Error creating media file, check storage permissions"); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); } } };
Attiva l'acquisizione di un'immagine chiamando il metodo Camera.takePicture()
. Il seguente esempio di codice mostra come chiamare questo metodo da un pulsante View.OnClickListener
.
Kotlin
val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { // get an image from the camera mCamera?.takePicture(null, null, picture) }
Java
// Add a listener to the Capture button Button captureButton = (Button) findViewById(R.id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // get an image from the camera mCamera.takePicture(null, null, picture); } } );
Nota:il membro mPicture
nel seguente esempio si riferisce
al codice di esempio riportato sopra.
Attenzione: ricordati di rilasciare l'oggetto Camera
chiamando Camera.release()
quando la tua
applicazione non lo usa più. Per informazioni su come sganciare la videocamera, vedi Sganciare la videocamera.
Registrazione di video
L'acquisizione video utilizzando il framework Android richiede una gestione accurata dell'oggetto Camera
e il coordinamento con la classe MediaRecorder
. Quando registri video con Camera
, devi gestire le chiamate Camera.lock()
e Camera.unlock()
per consentire a MediaRecorder
l'accesso all'hardware della videocamera,
oltre alle chiamate Camera.open()
e Camera.release()
.
Nota: a partire da Android 4.0 (livello API 14), le chiamate Camera.lock()
e Camera.unlock()
vengono gestite automaticamente.
A differenza dell'acquisizione di immagini con la fotocamera di un dispositivo, l'acquisizione di video richiede un ordine di chiamata molto particolare. Per preparare e acquisire correttamente il video con la tua applicazione, devi seguire un ordine di esecuzione specifico, come descritto di seguito.
- Apri fotocamera: utilizza
Camera.open()
per ottenere un'istanza dell'oggetto fotocamera. - Anteprima connessione: prepara un'anteprima dell'immagine della videocamera in diretta collegando un
SurfaceView
alla videocamera tramiteCamera.setPreviewDisplay()
. - Avvia anteprima: chiama
Camera.startPreview()
per iniziare a visualizzare le immagini della videocamera in diretta. - Avvia registrazione video: i seguenti passaggi devono essere completati in
ordine per registrare correttamente il video:
- Sblocca la videocamera: sblocca la videocamera per l'utilizzo da parte di
MediaRecorder
chiamando il numeroCamera.unlock()
. - Configura MediaRecorder: chiama i seguenti metodi
MediaRecorder
in questo ordine. Per saperne di più, consulta la documentazione di riferimento diMediaRecorder
.setCamera()
: imposta la fotocamera da utilizzare per l'acquisizione video, utilizza l'istanza corrente dell'applicazione diCamera
.setAudioSource()
- Imposta l'origine audio, utilizzaMediaRecorder.AudioSource.CAMCORDER
.setVideoSource()
- Imposta l'origine video, utilizzaMediaRecorder.VideoSource.CAMERA
.- Imposta il formato e la codifica dell'output video. Per Android 2.2 (livello API 8) e versioni successive, utilizza il metodo
MediaRecorder.setProfile
e ottieni un'istanza del profilo utilizzandoCamcorderProfile.get()
. Per le versioni di Android precedenti alla 2.2, devi impostare il formato di output video e i parametri di codifica:setOutputFormat()
- Imposta il formato di output, specifica l'impostazione predefinita oMediaRecorder.OutputFormat.MPEG_4
.setAudioEncoder()
- Imposta il tipo di codifica audio, specifica l'impostazione predefinita oMediaRecorder.AudioEncoder.AMR_NB
.setVideoEncoder()
: imposta il tipo di codifica video, specifica l'impostazione predefinita oMediaRecorder.VideoEncoder.MPEG_4_SP
.
setOutputFile()
- Imposta il file di output, utilizzagetOutputMediaFile(MEDIA_TYPE_VIDEO).toString()
dal metodo di esempio nella sezione Salvataggio dei file multimediali.setPreviewDisplay()
: specifica l'elemento del layout di anteprimaSurfaceView
per la tua applicazione. Utilizza lo stesso oggetto specificato per Anteprima connessione.
Attenzione:devi chiamare questi metodi di configurazione di
MediaRecorder
in questo ordine, altrimenti la tua applicazione riscontrerà errori e la registrazione non andrà a buon fine. - Prepare MediaRecorder: prepara
MediaRecorder
con le impostazioni di configurazione fornite chiamandoMediaRecorder.prepare()
. - Start MediaRecorder: avvia la registrazione video chiamando
MediaRecorder.start()
.
- Sblocca la videocamera: sblocca la videocamera per l'utilizzo da parte di
- Stop Recording Video: chiama i seguenti metodi in ordine per
completare correttamente una registrazione video:
- Stop MediaRecorder: interrompe la registrazione video chiamando
MediaRecorder.stop()
. - Reset MediaRecorder: se vuoi, rimuovi le impostazioni di configurazione dal registratore chiamando
MediaRecorder.reset()
. - Release MediaRecorder: rilascia
MediaRecorder
chiamandoMediaRecorder.release()
. - Blocca la videocamera: blocca la videocamera in modo che le sessioni future di
MediaRecorder
possano utilizzarla chiamandoCamera.lock()
. A partire da Android 4.0 (livello API 14), questa chiamata non è necessaria a meno che la chiamataMediaRecorder.prepare()
non vada a buon fine.
- Stop MediaRecorder: interrompe la registrazione video chiamando
- Interrompi l'anteprima: quando hai terminato di utilizzare la videocamera, interrompi l'anteprima utilizzando
Camera.stopPreview()
. - Release Camera: rilascia la fotocamera in modo che altre applicazioni possano utilizzarla chiamando
Camera.release()
.
Nota:è possibile utilizzare MediaRecorder
senza creare prima un'anteprima della videocamera e saltare i primi passaggi di questa procedura. Tuttavia,
poiché gli utenti in genere preferiscono vedere un'anteprima prima di iniziare una registrazione, questa procedura non
è descritta qui.
Suggerimento: se la tua applicazione viene in genere utilizzata per la registrazione di video, imposta
setRecordingHint(boolean)
su true
prima di iniziare
l'anteprima. Questa impostazione può contribuire a ridurre il tempo necessario per avviare la registrazione.
Configurazione di MediaRecorder
Quando utilizzi la classe MediaRecorder
per registrare video, devi eseguire i passaggi di configurazione in un ordine specifico e poi chiamare il metodo MediaRecorder.prepare()
per controllare e implementare la configurazione. Il seguente codice di esempio mostra come configurare e preparare correttamente la
classe MediaRecorder
per la registrazione video.
Kotlin
private fun prepareVideoRecorder(): Boolean { mediaRecorder = MediaRecorder() mCamera?.let { camera -> // Step 1: Unlock and set camera to MediaRecorder camera?.unlock() mediaRecorder?.run { setCamera(camera) // Step 2: Set sources setAudioSource(MediaRecorder.AudioSource.CAMCORDER) setVideoSource(MediaRecorder.VideoSource.CAMERA) // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)) // Step 4: Set output file setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()) // Step 5: Set the preview output setPreviewDisplay(mPreview?.holder?.surface) setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) // Step 6: Prepare configured MediaRecorder return try { prepare() true } catch (e: IllegalStateException) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } catch (e: IOException) { Log.d(TAG, "IOException preparing MediaRecorder: ${e.message}") releaseMediaRecorder() false } } } return false }
Java
private boolean prepareVideoRecorder(){ mCamera = getCameraInstance(); mediaRecorder = new MediaRecorder(); // Step 1: Unlock and set camera to MediaRecorder mCamera.unlock(); mediaRecorder.setCamera(mCamera); // Step 2: Set sources mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH)); // Step 4: Set output file mediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString()); // Step 5: Set the preview output mediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface()); // Step 6: Prepare configured MediaRecorder try { mediaRecorder.prepare(); } catch (IllegalStateException e) { Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } catch (IOException e) { Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage()); releaseMediaRecorder(); return false; } return true; }
Prima di Android 2.2 (livello API 8), devi impostare direttamente i parametri del formato di output e dei formati di codifica anziché utilizzare CamcorderProfile
. Questo approccio è
illustrato nel seguente codice:
Kotlin
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder?.apply { setOutputFormat(MediaRecorder.OutputFormat.MPEG_4) setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT) setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT) }
Java
// Step 3: Set output format and encoding (for versions prior to API Level 8) mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT); mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
I seguenti parametri di registrazione video per MediaRecorder
sono impostati
come predefiniti, ma potresti volerli modificare per la tua applicazione:
setVideoEncodingBitRate()
setVideoSize()
setVideoFrameRate()
setAudioEncodingBitRate()
setAudioChannels()
setAudioSamplingRate()
Avvio e arresto di MediaRecorder
Quando avvii e interrompi la registrazione di video utilizzando la classe MediaRecorder
,
devi seguire un ordine specifico, come elencato di seguito.
- Sbloccare la videocamera con
Camera.unlock()
- Configura
MediaRecorder
come mostrato nell'esempio di codice precedente - Inizia a registrare utilizzando
MediaRecorder.start()
- Registrare il video
- Interrompi la registrazione utilizzando
MediaRecorder.stop()
- Rilascia il registratore multimediale con
MediaRecorder.release()
- Bloccare la videocamera utilizzando
Camera.lock()
Il seguente codice di esempio mostra come collegare un pulsante per avviare e interrompere correttamente
la registrazione video utilizzando la fotocamera e la classe MediaRecorder
.
Nota: quando completi una registrazione video, non rilasciare la videocamera altrimenti l'anteprima verrà interrotta.
Kotlin
var isRecording = false val captureButton: Button = findViewById(R.id.button_capture) captureButton.setOnClickListener { if (isRecording) { // stop recording and release camera mediaRecorder?.stop() // stop the recording releaseMediaRecorder() // release the MediaRecorder object mCamera?.lock() // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture") isRecording = false } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder?.start() // inform the user that recording has started setCaptureButtonText("Stop") isRecording = true } else { // prepare didn't work, release the camera releaseMediaRecorder() // inform user } } }
Java
private boolean isRecording = false; // Add a listener to the Capture button Button captureButton = (Button) findViewById(id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (isRecording) { // stop recording and release camera mediaRecorder.stop(); // stop the recording releaseMediaRecorder(); // release the MediaRecorder object mCamera.lock(); // take camera access back from MediaRecorder // inform the user that recording has stopped setCaptureButtonText("Capture"); isRecording = false; } else { // initialize video camera if (prepareVideoRecorder()) { // Camera is available and unlocked, MediaRecorder is prepared, // now you can start recording mediaRecorder.start(); // inform the user that recording has started setCaptureButtonText("Stop"); isRecording = true; } else { // prepare didn't work, release the camera releaseMediaRecorder(); // inform user } } } } );
Nota:nell'esempio precedente, il metodo prepareVideoRecorder()
si riferisce al codice di esempio mostrato in Configurazione di MediaRecorder. Questo metodo si occupa di bloccare
la videocamera, configurare e preparare l'istanza MediaRecorder
.
Rilasciare la videocamera
Le fotocamere sono una risorsa condivisa dalle applicazioni su un dispositivo. La tua applicazione può utilizzare la fotocamera dopo aver ottenuto un'istanza di Camera
e devi prestare particolare attenzione a rilasciare l'oggetto fotocamera quando la tua applicazione smette di utilizzarlo e non appena l'applicazione viene sospesa (Activity.onPause()
). Se la tua applicazione non rilascia correttamente la fotocamera, tutti i tentativi successivi di accesso alla fotocamera, inclusi quelli della tua applicazione, non andranno a buon fine e potrebbero causare l'arresto della tua applicazione o di altre applicazioni.
Per rilasciare un'istanza dell'oggetto Camera
, utilizza il metodo Camera.release()
, come mostrato nel codice di esempio riportato di seguito.
Kotlin
class CameraActivity : Activity() { private var mCamera: Camera? private var preview: SurfaceView? private var mediaRecorder: MediaRecorder? override fun onPause() { super.onPause() releaseMediaRecorder() // if you are using MediaRecorder, release it first releaseCamera() // release the camera immediately on pause event } private fun releaseMediaRecorder() { mediaRecorder?.reset() // clear recorder configuration mediaRecorder?.release() // release the recorder object mediaRecorder = null mCamera?.lock() // lock camera for later use } private fun releaseCamera() { mCamera?.release() // release the camera for other applications mCamera = null } }
Java
public class CameraActivity extends Activity { private Camera mCamera; private SurfaceView preview; private MediaRecorder mediaRecorder; ... @Override protected void onPause() { super.onPause(); releaseMediaRecorder(); // if you are using MediaRecorder, release it first releaseCamera(); // release the camera immediately on pause event } private void releaseMediaRecorder(){ if (mediaRecorder != null) { mediaRecorder.reset(); // clear recorder configuration mediaRecorder.release(); // release the recorder object mediaRecorder = null; mCamera.lock(); // lock camera for later use } } private void releaseCamera(){ if (mCamera != null){ mCamera.release(); // release the camera for other applications mCamera = null; } } }
Attenzione:se l'applicazione non rilascia correttamente la fotocamera, tutti i tentativi successivi di accesso alla fotocamera, inclusi quelli della tua applicazione, non andranno a buon fine e potrebbero causare l'arresto della tua applicazione o di altre applicazioni.
Salvataggio dei file multimediali
I file multimediali creati dagli utenti, come immagini e video, devono essere salvati nella directory di archiviazione esterna (scheda SD) di un dispositivo per risparmiare spazio di sistema e consentire agli utenti di accedere a questi file senza il dispositivo. Esistono molte posizioni possibili per salvare i file multimediali su un dispositivo, tuttavia, in qualità di sviluppatore, devi considerare solo due posizioni standard:
Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_PICTURES
): questo metodo restituisce la posizione standard, condivisa e consigliata per il salvataggio di immagini e video. Questa directory è condivisa (pubblica), quindi altre applicazioni possono facilmente scoprire, leggere, modificare ed eliminare i file salvati in questa posizione. Se l'applicazione viene disinstallata dall'utente, i file multimediali salvati in questa posizione non verranno rimossi. Per evitare di interferire con le immagini e i video esistenti degli utenti, devi creare una sottodirectory per i file multimediali della tua applicazione all'interno di questa directory, come mostrato nell'esempio di codice riportato di seguito. Questo metodo è disponibile in Android 2.2 (livello API 8). Per chiamate equivalenti nelle versioni precedenti dell'API, consulta Salvataggio di file condivisi.Context.getExternalFilesDir
(Environment.DIRECTORY_PICTURES
): questo metodo restituisce una posizione standard per il salvataggio di immagini e video associati alla tua applicazione. Se la tua applicazione viene disinstallata, tutti i file salvati in questa posizione vengono rimossi. La sicurezza non viene applicata ai file in questa posizione e altre applicazioni potrebbero leggerli, modificarli ed eliminarli.
Il seguente codice di esempio mostra come creare una posizione File
o Uri
per un file multimediale che può essere utilizzata quando si richiama la fotocamera di un dispositivo con un Intent
o come parte di una creazione di un'app fotocamera.
Kotlin
val MEDIA_TYPE_IMAGE = 1 val MEDIA_TYPE_VIDEO = 2 /** Create a file Uri for saving an image or video */ private fun getOutputMediaFileUri(type: Int): Uri { return Uri.fromFile(getOutputMediaFile(type)) } /** Create a File for saving an image or video */ private fun getOutputMediaFile(type: Int): File? { // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. val mediaStorageDir = File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp" ) // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist mediaStorageDir.apply { if (!exists()) { if (!mkdirs()) { Log.d("MyCameraApp", "failed to create directory") return null } } } // Create a media file name val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) return when (type) { MEDIA_TYPE_IMAGE -> { File("${mediaStorageDir.path}${File.separator}IMG_$timeStamp.jpg") } MEDIA_TYPE_VIDEO -> { File("${mediaStorageDir.path}${File.separator}VID_$timeStamp.mp4") } else -> null } }
Java
public static final int MEDIA_TYPE_IMAGE = 1; public static final int MEDIA_TYPE_VIDEO = 2; /** Create a file Uri for saving an image or video */ private static Uri getOutputMediaFileUri(int type){ return Uri.fromFile(getOutputMediaFile(type)); } /** Create a File for saving an image or video */ private static File getOutputMediaFile(int type){ // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory( Environment.DIRECTORY_PICTURES), "MyCameraApp"); // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist if (! mediaStorageDir.exists()){ if (! mediaStorageDir.mkdirs()){ Log.d("MyCameraApp", "failed to create directory"); return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; if (type == MEDIA_TYPE_IMAGE){ mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg"); } else if(type == MEDIA_TYPE_VIDEO) { mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4"); } else { return null; } return mediaFile; }
Nota:Environment.getExternalStoragePublicDirectory()
è disponibile in Android 2.2 (livello API 8) o
versioni successive. Se scegli come target dispositivi con versioni precedenti di Android, utilizza Environment.getExternalStorageDirectory()
in alternativa. Per ulteriori informazioni, vedi Salvataggio dei file condivisi.
Per fare in modo che l'URI supporti i profili di lavoro, devi prima
convertire l'URI del file in un URI dei contenuti. Quindi, aggiungi l'URI dei contenuti a
EXTRA_OUTPUT
di un Intent
.
Per saperne di più sul salvataggio dei file su un dispositivo Android, vedi Archiviazione dei dati.
Funzionalità della fotocamera
Android supporta un'ampia gamma di funzionalità della fotocamera che puoi controllare con l'applicazione fotocamera,
come il formato dell'immagine, la modalità flash, le impostazioni di messa a fuoco e molte altre. Questa sezione elenca le funzionalità comuni
della videocamera e spiega brevemente come utilizzarle. La maggior parte delle funzionalità della videocamera può essere accessibile e impostata
utilizzando l'oggetto Camera.Parameters
. Tuttavia, esistono diverse funzionalità importanti che richiedono più di semplici impostazioni in Camera.Parameters
. Queste funzionalità sono trattate nelle sezioni seguenti:
Per informazioni generali su come utilizzare le funzionalità controllate tramite Camera.Parameters
, consulta la sezione Utilizzo delle funzionalità della fotocamera. Per informazioni più dettagliate su come utilizzare le funzionalità controllate tramite l'oggetto
parametri della videocamera, segui i link nell'elenco delle funzionalità riportato di seguito alla documentazione
di riferimento dell'API.
Tabella 1. Funzionalità comuni della videocamera ordinate in base al livello API Android in cui sono state introdotte.
Funzionalità | Livello API | Descrizione |
---|---|---|
Rilevamento dei volti | 14 | Identificare i volti umani all'interno di un'immagine e utilizzarli per la messa a fuoco, la misurazione e il bilanciamento del bianco |
Aree di misurazione | 14 | Specifica una o più aree all'interno di un'immagine per calcolare il bilanciamento del bianco |
Aree d'intervento | 14 | Imposta una o più aree all'interno di un'immagine da utilizzare per la messa a fuoco |
White Balance Lock |
14 | Interrompere o avviare le regolazioni automatiche del bilanciamento del bianco |
Exposure Lock |
14 | Interrompere o avviare le regolazioni automatiche dell'esposizione |
Video Snapshot |
14 | Scattare una foto durante la registrazione di un video (estrazione di un frame) |
Video time-lapse | 11 | Registra fotogrammi con ritardi impostati per registrare un video in time-lapse |
Multiple Cameras |
9 | Supporto di più di una fotocamera su un dispositivo, incluse le fotocamere anteriore e posteriore |
Focus Distance |
9 | Indica le distanze tra la videocamera e gli oggetti che sembrano essere a fuoco |
Zoom |
8 | Impostare l'ingrandimento dell'immagine |
Exposure
Compensation |
8 | Aumentare o diminuire il livello di esposizione alla luce |
GPS Data |
5 | Includere o omettere i dati sulla posizione geografica con l'immagine |
White Balance |
5 | Imposta la modalità di bilanciamento del bianco, che influisce sui valori di colore nell'immagine acquisita |
Focus Mode |
5 | Imposta la messa a fuoco della fotocamera su un soggetto, ad esempio automatica, fissa, macro o infinito. |
Scene Mode |
5 | Applica una modalità preimpostata per tipi specifici di situazioni fotografiche, come scene notturne, in spiaggia, sulla neve o a lume di candela |
JPEG Quality |
5 | Imposta il livello di compressione per un'immagine JPEG, che aumenta o diminuisce la qualità e le dimensioni del file di output dell'immagine |
Flash Mode |
5 | Attivare o disattivare il flash o utilizzare l'impostazione automatica |
Color Effects |
5 | Applica un effetto colore all'immagine acquisita, ad esempio bianco e nero, tonalità seppia o negativo. |
Anti-Banding |
5 | Riduce l'effetto di banding nei gradienti di colore a causa della compressione JPEG |
Picture Format |
1 | Specifica il formato file dell'immagine |
Picture Size |
1 | Specifica le dimensioni in pixel dell'immagine salvata |
Nota:queste funzionalità non sono supportate su tutti i dispositivi a causa di differenze hardware e implementazione software. Per informazioni su come controllare la disponibilità delle funzionalità sul dispositivo su cui è in esecuzione l'applicazione, vedi Controllo della disponibilità delle funzionalità.
Verifica della disponibilità delle funzionalità in corso…
La prima cosa da capire quando si utilizzano le funzionalità della fotocamera sui dispositivi Android è che non tutte le funzionalità della fotocamera sono supportate su tutti i dispositivi. Inoltre, i dispositivi che supportano una determinata funzionalità potrebbero supportarla a livelli diversi o con opzioni diverse. Pertanto, parte del processo decisionale durante lo sviluppo di un'applicazione per la fotocamera consiste nel decidere quali funzionalità della fotocamera vuoi supportare e a quale livello. Dopo aver preso questa decisione, devi pianificare l'inclusione di codice nell'applicazione della videocamera che controlla se l'hardware del dispositivo supporta queste funzionalità e non funziona correttamente se una funzionalità non è disponibile.
Puoi controllare la disponibilità delle funzionalità della videocamera ottenendo un'istanza dell'oggetto dei parametri di una videocamera e controllando i metodi pertinenti. Il seguente esempio di codice mostra come ottenere un
oggetto Camera.Parameters
e controllare se la fotocamera supporta la
funzionalità di messa a fuoco automatica:
Kotlin
val params: Camera.Parameters? = camera?.parameters val focusModes: List<String>? = params?.supportedFocusModes if (focusModes?.contains(Camera.Parameters.FOCUS_MODE_AUTO) == true) { // Autofocus mode is supported }
Java
// get Camera parameters Camera.Parameters params = camera.getParameters(); List<String> focusModes = params.getSupportedFocusModes(); if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) { // Autofocus mode is supported }
Puoi utilizzare la tecnica mostrata sopra per la maggior parte delle funzionalità della videocamera. L'oggetto
Camera.Parameters
fornisce un metodo getSupported...()
, is...Supported()
o getMax...()
per determinare se (e in che misura) una funzionalità è
supportata.
Se la tua applicazione richiede determinate funzionalità della fotocamera per funzionare correttamente, puoi richiederle tramite aggiunte al manifest dell'applicazione. Quando dichiari l'utilizzo di funzionalità specifiche della fotocamera, come flash e messa a fuoco automatica, Google Play impedisce l'installazione della tua applicazione su dispositivi che non supportano queste funzionalità. Per un elenco delle funzionalità della videocamera che possono essere dichiarate nel manifest dell'app, consulta il manifest Features Reference.
Utilizzare le funzionalità della fotocamera
La maggior parte delle funzionalità della videocamera viene attivata e controllata utilizzando un oggetto Camera.Parameters
. Ottieni questo oggetto recuperando prima un'istanza dell'oggetto Camera
, chiamando il metodo getParameters()
, modificando l'oggetto parametro restituito e poi impostandolo di nuovo nell'oggetto fotocamera, come mostrato nel seguente esempio di codice:
Kotlin
val params: Camera.Parameters? = camera?.parameters params?.focusMode = Camera.Parameters.FOCUS_MODE_AUTO camera?.parameters = params
Java
// get Camera parameters Camera.Parameters params = camera.getParameters(); // set the focus mode params.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO); // set Camera parameters camera.setParameters(params);
Questa tecnica funziona per quasi tutte le funzionalità della fotocamera e la maggior parte dei parametri può essere modificata in qualsiasi
momento dopo aver ottenuto un'istanza dell'oggetto Camera
. Le modifiche ai
parametri sono in genere visibili immediatamente all'utente nell'anteprima della videocamera dell'applicazione.
A livello software, le modifiche ai parametri potrebbero richiedere diversi fotogrammi per diventare effettive, in quanto
l'hardware della videocamera elabora le nuove istruzioni e poi invia i dati aggiornati dell'immagine.
Importante:alcune funzionalità della videocamera non possono essere modificate a piacimento. In particolare, la modifica delle dimensioni o dell'orientamento dell'anteprima della videocamera richiede di interrompere l'anteprima, modificare le dimensioni dell'anteprima e quindi riavviarla. A partire da Android 4.0 (livello API 14), l'orientamento dell'anteprima può essere modificato senza riavviarla.
Altre funzionalità della videocamera richiedono più codice per l'implementazione, tra cui:
- Misurazione e aree di messa a fuoco
- Riconoscimento facciale
- Video in time-lapse
Nelle sezioni seguenti viene fornita una rapida panoramica su come implementare queste funzionalità.
Misurazione e aree di messa a fuoco
In alcuni scenari fotografici, la messa a fuoco automatica e la misurazione della luce potrebbero non produrre i risultati desiderati. A partire da Android 4.0 (livello API 14), l'applicazione fotocamera può fornire controlli aggiuntivi per consentire all'app o agli utenti di specificare le aree di un'immagine da utilizzare per determinare le impostazioni di messa a fuoco o del livello di luce e passare questi valori all'hardware della fotocamera per l'utilizzo nell'acquisizione di immagini o video.
Le aree per la misurazione e la messa a fuoco funzionano in modo molto simile ad altre funzionalità della videocamera, in quanto le controlli
tramite i metodi nell'oggetto Camera.Parameters
. Il seguente codice
mostra l'impostazione di due aree di misurazione della luce per un'istanza di
Camera
:
Kotlin
// Create an instance of Camera camera = getCameraInstance() // set Camera parameters val params: Camera.Parameters? = camera?.parameters params?.apply { if (maxNumMeteringAreas > 0) { // check that metering areas are supported meteringAreas = ArrayList<Camera.Area>().apply { val areaRect1 = Rect(-100, -100, 100, 100) // specify an area in center of image add(Camera.Area(areaRect1, 600)) // set weight to 60% val areaRect2 = Rect(800, -1000, 1000, -800) // specify an area in upper right of image add(Camera.Area(areaRect2, 400)) // set weight to 40% } } camera?.parameters = this }
Java
// Create an instance of Camera camera = getCameraInstance(); // set Camera parameters Camera.Parameters params = camera.getParameters(); if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supported List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>(); Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of image meteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60% Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of image meteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40% params.setMeteringAreas(meteringAreas); } camera.setParameters(params);
L'oggetto Camera.Area
contiene due parametri di dati: un oggetto Rect
per specificare un'area all'interno del campo visivo della videocamera e un valore di peso, che indica alla videocamera il livello di importanza da assegnare a questa area nel calcolo dell'esposizione o della messa a fuoco.
Il campo Rect
in un oggetto Camera.Area
descrive una forma rettangolare mappata su una griglia di unità 2000 x 2000. Le coordinate -1000, -1000
rappresentano l'angolo in alto a sinistra dell'immagine della videocamera, mentre le coordinate 1000, 1000 rappresentano
l'angolo in basso a destra dell'immagine della videocamera, come mostrato nell'illustrazione di seguito.
Figura 1. Le linee rosse illustrano il sistema di coordinate per specificare un
Camera.Area
all'interno di un'anteprima della videocamera. Il riquadro blu mostra la posizione e
la forma di un'area della videocamera con i valori Rect
333,333,667,667.
I limiti di questo sistema di coordinate corrispondono sempre al bordo esterno dell'immagine visibile nell'anteprima della videocamera e non si restringono o espandono con il livello di zoom. Allo stesso modo, la rotazione dell'anteprima dell'immagine utilizzando Camera.setDisplayOrientation()
non rimappa il sistema di coordinate.
Riconoscimento facciale
Per le foto che includono persone, i volti sono in genere la parte più importante dell'immagine e devono essere utilizzati per determinare sia la messa a fuoco che il bilanciamento del bianco durante l'acquisizione di un'immagine. Il framework Android 4.0 (livello API 14) fornisce API per identificare i volti e calcolare le impostazioni delle immagini utilizzando la tecnologia di riconoscimento facciale.
Nota:mentre è in esecuzione la funzionalità di rilevamento volto,
setWhiteBalance(String)
,
setFocusAreas(List<Camera.Area>)
e
setMeteringAreas(List<Camera.Area>)
non hanno alcun effetto.
L'utilizzo della funzionalità di rilevamento dei volti nell'applicazione della videocamera richiede alcuni passaggi generali:
- Controlla che il rilevamento dei volti sia supportato sul dispositivo
- Crea un listener di rilevamento dei volti
- Aggiungi il listener di rilevamento del volto all'oggetto videocamera
- Avvia il riconoscimento facciale dopo l'anteprima (e dopo ogni riavvio dell'anteprima)
La funzionalità di rilevamento del volto non è supportata su tutti i dispositivi. Puoi verificare che questa funzionalità
sia supportata chiamando il numero getMaxNumDetectedFaces()
. Un esempio di questo controllo è mostrato nel metodo di esempio startFaceDetection()
di seguito.
Per ricevere una notifica e rispondere al rilevamento di un volto, l'applicazione della videocamera deve impostare
un listener per gli eventi di rilevamento dei volti. Per farlo, devi creare una classe listener che
implementi l'interfaccia Camera.FaceDetectionListener
come mostrato nel
codice di esempio riportato di seguito.
Kotlin
internal class MyFaceDetectionListener : Camera.FaceDetectionListener { override fun onFaceDetection(faces: Array<Camera.Face>, camera: Camera) { if (faces.isNotEmpty()) { Log.d("FaceDetection", ("face detected: ${faces.size}" + " Face 1 Location X: ${faces[0].rect.centerX()}" + "Y: ${faces[0].rect.centerY()}")) } } }
Java
class MyFaceDetectionListener implements Camera.FaceDetectionListener { @Override public void onFaceDetection(Face[] faces, Camera camera) { if (faces.length > 0){ Log.d("FaceDetection", "face detected: "+ faces.length + " Face 1 Location X: " + faces[0].rect.centerX() + "Y: " + faces[0].rect.centerY() ); } } }
Dopo aver creato questa classe, impostala nell'oggetto Camera
dell'applicazione, come mostrato nel codice di esempio riportato di seguito:
Kotlin
camera?.setFaceDetectionListener(MyFaceDetectionListener())
Java
camera.setFaceDetectionListener(new MyFaceDetectionListener());
L'applicazione deve avviare la funzione di rilevamento dei volti ogni volta che avvii (o riavvii) l'anteprima della videocamera. Crea un metodo per avviare il rilevamento del volto in modo da poterlo chiamare in base alle necessità, come mostrato nel codice di esempio riportato di seguito.
Kotlin
fun startFaceDetection() { // Try starting Face Detection val params = mCamera?.parameters // start face detection only *after* preview has started params?.apply { if (maxNumDetectedFaces > 0) { // camera supports face detection, so can start it: mCamera?.startFaceDetection() } } }
Java
public void startFaceDetection(){ // Try starting Face Detection Camera.Parameters params = mCamera.getParameters(); // start face detection only *after* preview has started if (params.getMaxNumDetectedFaces() > 0){ // camera supports face detection, so can start it: mCamera.startFaceDetection(); } }
Devi avviare il rilevamento dei volti ogni volta che avvii (o riavvii) l'anteprima della videocamera. Se
utilizzi la classe di anteprima mostrata in Creazione di una classe di anteprima, aggiungi il metodo
startFaceDetection()
ai metodi
surfaceCreated()
e surfaceChanged()
nella classe di anteprima,
come mostrato nel codice di esempio riportato di seguito.
Kotlin
override fun surfaceCreated(holder: SurfaceHolder) { try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // start face detection feature } catch (e: IOException) { Log.d(TAG, "Error setting camera preview: ${e.message}") } } override fun surfaceChanged(holder: SurfaceHolder, format: Int, w: Int, h: Int) { if (holder.surface == null) { // preview surface does not exist Log.d(TAG, "holder.getSurface() == null") return } try { mCamera.stopPreview() } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: ${e.message}") } try { mCamera.setPreviewDisplay(holder) mCamera.startPreview() startFaceDetection() // re-start face detection feature } catch (e: Exception) { // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: ${e.message}") } }
Java
public void surfaceCreated(SurfaceHolder holder) { try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // start face detection feature } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { if (holder.getSurface() == null){ // preview surface does not exist Log.d(TAG, "holder.getSurface() == null"); return; } try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error stopping camera preview: " + e.getMessage()); } try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); startFaceDetection(); // re-start face detection feature } catch (Exception e){ // ignore: tried to stop a non-existent preview Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } }
Nota:ricordati di chiamare questo metodo dopo aver chiamato
startPreview()
. Non tentare di avviare il rilevamento dei volti
nel metodo onCreate()
dell'attività principale dell'app della videocamera,
in quanto l'anteprima non è disponibile a questo punto dell'esecuzione dell'applicazione.
Video in time-lapse
Il video in time-lapse consente agli utenti di creare video clip che combinano immagini scattate a distanza di pochi secondi o
minuti. Questa funzionalità utilizza MediaRecorder
per registrare le immagini per una sequenza
time-lapse.
Per registrare un video in time-lapse con MediaRecorder
, devi configurare l'oggetto
recorder come se stessi registrando un video normale, impostando i fotogrammi acquisiti al secondo su un
numero basso e utilizzando una delle impostazioni di qualità del time-lapse, come mostrato nell'esempio di codice riportato di seguito.
Kotlin
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)) mediaRecorder.setCaptureRate(0.1) // capture a frame every 10 seconds
Java
// Step 3: Set a CamcorderProfile (requires API Level 8 or higher) mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH)); ... // Step 5.5: Set the video capture rate to a low number mediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
Queste impostazioni devono essere eseguite nell'ambito di una procedura di configurazione più ampia per MediaRecorder
. Per un esempio completo di codice di configurazione, consulta Configurazione di MediaRecorder. Una volta completata la configurazione,
avvia la registrazione del video come se stessi registrando un normale video clip. Per ulteriori informazioni
sulla configurazione e l'esecuzione di MediaRecorder
, vedi Acquisizione di video.
Gli esempi Camera2Video e HdrViewfinder mostrano ulteriormente l'utilizzo delle API trattate in questa pagina.
Campi della videocamera che richiedono l'autorizzazione
Le app che eseguono Android 10 (livello API 29) o versioni successive devono disporre dell'autorizzazione
CAMERA
per
accedere ai valori dei seguenti campi restituiti dal metodo
getCameraCharacteristics()
:
LENS_POSE_ROTATION
LENS_POSE_TRANSLATION
LENS_INTRINSIC_CALIBRATION
LENS_RADIAL_DISTORTION
LENS_POSE_REFERENCE
LENS_DISTORTION
LENS_INFO_HYPERFOCAL_DISTANCE
LENS_INFO_MINIMUM_FOCUS_DISTANCE
SENSOR_REFERENCE_ILLUMINANT1
SENSOR_REFERENCE_ILLUMINANT2
SENSOR_CALIBRATION_TRANSFORM1
SENSOR_CALIBRATION_TRANSFORM2
SENSOR_COLOR_TRANSFORM1
SENSOR_COLOR_TRANSFORM2
SENSOR_FORWARD_MATRIX1
SENSOR_FORWARD_MATRIX2
Codice campione aggiuntivo
Per scaricare le app di esempio, consulta l'esempio Camera2Basic e l'app di esempio ufficiale CameraX.