Il framework Android include il supporto per varie fotocamere e funzionalità delle fotocamere disponibili sui dispositivi, consentendoti di acquisire immagini e video nelle tue applicazioni. Questo documento illustra un approccio rapido e semplice all'acquisizione di immagini e video e delinea un approccio avanzato per creare esperienze di fotocamera personalizzate per i tuoi utenti.
Nota:
in questa pagina viene descritta la classe Camera
, che è stata deprecata. Ti consigliamo di utilizzare la libreria Jetpack FotocameraX o, per casi d'uso specifici, la classe camera2
. Sia CameraX che Camera2 funzionano su Android 5.0 (livello API 21) e
versioni successive.
Fai riferimento alle seguenti risorse correlate:
considerazioni
Prima di consentire alla tua applicazione di utilizzare le fotocamere dei dispositivi Android, dovresti rispondere ad alcune domande sulla modalità di utilizzo di questa funzionalità hardware da parte dell'app.
- Requisito della fotocamera: l'utilizzo di una videocamera è così importante per la tua applicazione da impedire che l'applicazione venga installata su un dispositivo che non dispone di una videocamera? Se è così, devi dichiarare il requisito di utilizzo della fotocamera nel file manifest.
- Rapida foto o fotocamera personalizzata: in che modo la tua applicazione utilizza la fotocamera? Ti interessa solo scattare una foto o un video clip o la tua applicazione offre un nuovo modo di utilizzare le videocamere? Per ottenere uno scatto o un clip rapido, considera l'articolo Utilizzare le app della fotocamera esistenti. Per sviluppare una funzionalità personalizzata della fotocamera, consulta la sezione Creazione di 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 eseguite in background non possono accedere alla fotocamera. Dovresti quindi usare la videocamera quando l'app è in primo piano o come parte di un servizio in primo piano.
- Spazio di archiviazione: le immagini o i video generati dall'applicazione devono essere visibili solo all'applicazione o condivisi in modo che altre applicazioni come Galleria o altre app social e multimediali possano utilizzarli? Vuoi che le immagini e i video siano disponibili anche se la tua applicazione viene disinstallata? Consulta la sezione Salvataggio dei file multimediali per vedere 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 controllare le videocamere dei dispositivi. Può essere usata per scattare foto o registrare video mentre crei un'applicazione per la fotocamera.
Camera
- Questa classe è l'API deprecata precedente per il controllo delle videocamere dei dispositivi.
SurfaceView
- Questo corso viene utilizzato per presentare all'utente un'anteprima in diretta della videocamera.
MediaRecorder
- Questo corso viene utilizzato per registrare il video proveniente dalla videocamera.
Intent
- È possibile usare un tipo di azione intent di
MediaStore.ACTION_IMAGE_CAPTURE
oMediaStore.ACTION_VIDEO_CAPTURE
per acquisire immagini o video senza usare direttamente l'oggettoCamera
.
Dichiarazioni del file manifest
Prima di iniziare lo sviluppo dell'applicazione con l'API Camera, assicurati che il file manifest contenga le dichiarazioni appropriate per consentire l'utilizzo dell'hardware della fotocamera e di altre funzionalità correlate.
- Autorizzazione Fotocamera. L'applicazione deve richiedere l'autorizzazione per utilizzare la fotocamera del dispositivo.
<uses-permission android:name="android.permission.CAMERA" />
Nota: se utilizzi la fotocamera richiamando un'app per fotocamera esistente, l'applicazione non deve richiedere questa autorizzazione.
- Funzionalità della fotocamera. L'applicazione deve dichiarare anche l'utilizzo delle funzionalità della fotocamera, ad esempio:
<uses-feature android:name="android.hardware.camera" />
Per un elenco delle funzionalità della videocamera, consulta il riferimento sulle funzionalità del file manifest.
Se aggiungi funzionalità della videocamera al file manifest, Google Play impedisce l'installazione dell'applicazione su dispositivi che non includono una videocamera o che non supportano le funzionalità della videocamera da te specificate. Per ulteriori informazioni sull'utilizzo del filtro basato sulle funzionalità con Google Play, consulta la pagina relativa a Google Play e i filtri basati sulle funzionalità.
Se l'applicazione può utilizzare una fotocamera o una funzionalità di fotocamera per il corretto funzionamento, ma non la richiede, devi specificarla nel file manifest includendo l'attributo
android:required
e impostandolo sufalse
:<uses-feature android:name="android.hardware.camera" android:required="false" />
- Autorizzazione per lo spazio 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 nel file manifest è specificato quanto segue.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- Autorizzazione registrazione audio: per registrare audio con acquisizione video, la tua applicazione deve richiedere l'autorizzazione per l'acquisizione dell'audio.
<uses-permission android:name="android.permission.RECORD_AUDIO" />
-
Autorizzazione di accesso alla posizione: se l'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 l'app 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 ulteriori informazioni su come ottenere la posizione dell'utente, consulta le strategie per la località.
Utilizzo di app fotocamera esistenti
Un modo rapido per consentire l'acquisizione di foto o video nella tua applicazione senza molto codice aggiuntivo consiste nell'utilizzare un Intent
per richiamare un'applicazione fotocamera Android esistente.
I dettagli sono descritti nelle lezioni di formazione Scattare foto in modo semplice e Registrare video in modo semplice.
Creazione di un'app fotocamera in corso...
Alcuni sviluppatori potrebbero richiedere un'interfaccia utente della videocamera personalizzata in base all'aspetto della loro applicazione o che fornisca funzionalità speciali. Scrivere il tuo codice per scattare foto può fornire un'esperienza più accattivante agli utenti.
Nota: la seguente guida si riferisce all'API Camera
deprecata e precedente. Per applicazioni di fotocamera nuove o avanzate, ti consigliamo di utilizzare l'API android.hardware.camera2
più recente.
I passaggi generali per la creazione di un'interfaccia della videocamera personalizzata per la tua applicazione sono i seguenti:
- Rileva e accedi alla videocamera: crea un codice per verificare l'esistenza delle videocamere e richiedi l'accesso.
- Crea un corso Anteprima: crea una classe di anteprima della fotocamera che estenda
SurfaceView
e implementi l'interfacciaSurfaceHolder
. Questo corso mostra in anteprima le immagini in diretta della videocamera. - Crea un layout di anteprima: una volta ottenuta la classe di anteprima della fotocamera, crea un layout di vista che incorpori l'anteprima e i controlli dell'interfaccia utente desiderati.
- Configura listener per l'acquisizione: connetti i listener ai controlli dell'interfaccia per avviare l'acquisizione di immagini o video in risposta alle azioni dell'utente, ad esempio la pressione di un pulsante.
- Acquisisci e salva file: configura il codice per acquisire foto 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 videocamera è una risorsa condivisa che deve essere gestita con attenzione per evitare che l'applicazione sia in conflitto con altre applicazioni che potrebbero voler utilizzarla. Le seguenti sezioni descrivono come rilevare l'hardware della fotocamera, come richiedere l'accesso a una fotocamera, come acquisire immagini o video e come rilasciare la fotocamera quando l'applicazione ha finito di utilizzarla.
Attenzione: ricorda di rilasciare l'oggetto Camera
chiamando Camera.release()
quando
l'applicazione ha finito di utilizzarlo. Se l'applicazione non rilascia correttamente la fotocamera, tutti i successivi tentativi di accesso alla fotocamera, inclusi quelli eseguiti dalla tua applicazione, non andranno a buon fine e potrebbero causare l'arresto della tua o di altre applicazioni.
Rilevamento dell'hardware della videocamera
Se la tua applicazione non richiede specificatamente una videocamera che utilizza una dichiarazione del file manifest, devi controllare se una videocamera è disponibile in fase di runtime. Per eseguire questa verifica, usa 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 posteriore per fotografare e una anteriore per le videochiamate. Android 2.3 (livello API 9) e versioni successive ti consentono di controllare il numero di videocamere disponibili su un dispositivo usando il metodo Camera.getNumberOfCameras()
.
Accesso alle videocamere
Se hai stabilito che il dispositivo su cui è in esecuzione la tua applicazione ha una videocamera, devi richiedere l'accesso ricevendo un'istanza di Camera
(a meno che tu non stia utilizzando un intent per accedere alla fotocamera).
Per accedere alla fotocamera principale, usa il metodo Camera.open()
e assicurati di individuare eventuali eccezioni, come mostrato nel codice seguente:
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:verifica sempre la presenza di eccezioni quando utilizzi Camera.open()
. Se la videocamera non è in uso o non è presente, l'applicazione verrà arrestata 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 consente di accedere
alla prima fotocamera posteriore su un dispositivo con più di una fotocamera.
Controllo delle funzionalità della fotocamera in corso...
Dopo aver 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 conoscere le funzionalità supportate. Quando utilizzi
il livello API 9 o superiore, usa il Camera.getCameraInfo()
per determinare se una fotocamera si trova sulla parte anteriore o
retro del dispositivo e l'orientamento dell'immagine.
Creazione di un corso in anteprima
Per scattare foto o registrare video in modo efficace, gli utenti devono essere in grado di vedere ciò che inquadra la fotocamera del dispositivo. Una classe di anteprima della fotocamera è un SurfaceView
che può visualizzare i dati delle immagini in tempo reale provenienti da una fotocamera, in modo che gli utenti possano inquadrare e acquisire un'immagine o un video.
Il codice di esempio che segue mostra come creare una classe di anteprima di base della fotocamera che può essere inclusa in un layout View
. Questa classe implementa SurfaceHolder.Callback
per acquisire gli eventi di callback necessari per creare e eliminare la vista, 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 fotocamera, impostala nel metodo surfaceChanged()
, come indicato nei commenti qui sopra. Quando imposti le dimensioni di anteprima, devi utilizzare i valori di getSupportedPreviewSizes()
.
Non impostare valori arbitrari nel metodo setPreviewSize()
.
Nota: con l'introduzione della funzionalità
Multi-finestra in Android 7.0 (livello API 24) e versioni successive, non puoi più presumere che le proporzioni dell'anteprima corrispondano a quelle dell'attività anche dopo aver chiamato il numero setDisplayOrientation()
.
A seconda delle dimensioni e delle proporzioni della finestra, potrebbe essere necessario adattare l'anteprima grandangolare della fotocamera a un layout con orientamento verticale o viceversa utilizzando un layout letterbox.
Inserire l'anteprima in un layout
Nel layout di un'attività deve essere inserita una classe di anteprima della videocamera, come quella mostrata nella sezione precedente, insieme agli 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 offre una visualizzazione di base che può essere utilizzata per mostrare un'anteprima della videocamera. In questo esempio, l'elemento FrameLayout
deve essere il contenitore per la classe di anteprima della fotocamera. Questo tipo di layout consente di sovrapporre ulteriori informazioni
o controlli sull'immagine alle immagini di anteprima in diretta della fotocamera.
<?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 fotocamera è orizzontale. Questo layout di esempio specifica un layout orizzontale (orizzontale) e il codice riportato di seguito corregge l'orientamento dell'applicazione in orizzontale. Per semplificare il rendering dell'anteprima della fotocamera, devi modificare l'orientamento dell'attività di anteprima dell'applicazione in orizzontale aggiungendo quanto segue al file 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: non è necessario che l'anteprima della fotocamera sia in modalità Orizzontale.
A partire da Android 2.2 (livello API 8), puoi usare il metodo setDisplayOrientation()
per impostare la rotazione dell'immagine di anteprima. Per modificare l'orientamento dell'anteprima quando l'utente cambia l'orientamento del telefono, utilizzando il metodo surfaceChanged()
della classe di anteprima, interrompi l'anteprima con Camera.stopPreview()
modifica l'orientamento, quindi riavvia l'anteprima con Camera.startPreview()
.
Nell'attività relativa alla visualizzazione della videocamera, aggiungi la classe di anteprima all'elemento FrameLayout
mostrato nell'esempio sopra. L'attività della videocamera deve anche
garantire che la videocamera venga rilasciata quando è in pausa o spenta. L'esempio seguente mostra come modificare un'attività della fotocamera 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 foto
Dopo aver creato una classe di anteprima e un layout di visualizzazione in cui mostrarla, puoi iniziare ad acquisire immagini con la tua applicazione. Nel codice dell'applicazione, devi configurare i listener affinché i controlli dell'interfaccia utente rispondano a un'azione dell'utente scattando una foto.
Per recuperare un'immagine, usa il metodo Camera.takePicture()
. Questo metodo richiede tre parametri che ricevono dati dalla fotocamera.
Per ricevere 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 di Camera.PictureCallback
per salvare un'immagine ricevuta dalla fotocamera.
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 codice di esempio seguente 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
nell'esempio seguente fa riferimento al codice di esempio riportato sopra.
Attenzione: ricorda di rilasciare l'oggetto Camera
chiamando Camera.release()
quando
l'applicazione ha finito di utilizzarlo. Per informazioni su come rilasciare la videocamera, vedi Rilascio della videocamera.
Acquisizione di video
L'acquisizione di video tramite il framework Android richiede un'attenta gestione 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
di accedere 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 delle foto con la fotocamera di un dispositivo, l'acquisizione di video richiede un ordine di chiamata molto particolare. Per prepararti e acquisire video con la tua applicazione, devi seguire un ordine di esecuzione specifico, come descritto di seguito.
- Apri la fotocamera: utilizza il
Camera.open()
per visualizzare un'istanza dell'oggetto fotocamera. - Collega anteprima: prepara un'anteprima in diretta dell'immagine della fotocamera collegando
SurfaceView
alla fotocamera utilizzandoCamera.setPreviewDisplay()
. - Avvia anteprima: chiama il numero
Camera.startPreview()
per iniziare a visualizzare le immagini in diretta della videocamera. - Avvia la registrazione del video: i seguenti passaggi devono essere completati nell'ordine per registrare correttamente il video:
- Sblocca la fotocamera. Sblocca la fotocamera da utilizzare entro il giorno
MediaRecorder
chiamando il numeroCamera.unlock()
. - Configura MediaRecorder. Esegui una chiamata nei seguenti
MediaRecorder
metodi 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 attuale diCamera
della tua applicazione.setAudioSource()
- Imposta la sorgente audio, usaMediaRecorder.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 di profilo utilizzandoCamcorderProfile.get()
. Per le versioni di Android precedenti alla 2.2, devi impostare il formato dell'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()
del metodo di esempio nella sezione Salvataggio dei file multimediali.setPreviewDisplay()
: specifica l'elemento layout di anteprimaSurfaceView
per l'applicazione. Utilizza lo stesso oggetto specificato per Connetti anteprima.
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. - Prepara MediaRecorder: prepara
MediaRecorder
con le impostazioni di configurazione fornite chiamando il numeroMediaRecorder.prepare()
. - Avvia MediaRecorder: inizia a registrare video chiamando il numero
MediaRecorder.start()
.
- Sblocca la fotocamera. Sblocca la fotocamera da utilizzare entro il giorno
- Interrompi la registrazione del video: chiama i seguenti metodi nell'ordine per completare correttamente una registrazione video:
- Interrompi MediaRecorder. Interrompi la registrazione del video chiamando il numero
MediaRecorder.stop()
. - Resetta MediaRecorder: se vuoi, rimuovi le impostazioni di configurazione dal registratore chiamando il numero
MediaRecorder.reset()
. - Release MediaRecorder. Rilascia
MediaRecorder
chiamandoMediaRecorder.release()
. - Blocca la videocamera: blocca la videocamera in modo che le future sessioni 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.
- Interrompi MediaRecorder. Interrompi la registrazione del video chiamando il numero
- Interrompi anteprima: quando l'attività di utilizzo della fotocamera ha terminato l'attività, interrompi l'anteprima utilizzando
Camera.stopPreview()
. - Rilascia fotocamera: rilascia la fotocamera in modo che altre applicazioni possano
utilizzarla chiamando il numero
Camera.release()
.
Nota: è possibile utilizzare MediaRecorder
senza prima creare un'anteprima della fotocamera e saltare i primi passaggi della procedura. Tuttavia, poiché gli utenti in genere preferiscono visualizzare un'anteprima prima di avviare una registrazione, questo processo non viene discusso qui.
Suggerimento: se la tua applicazione viene generalmente utilizzata per registrare video, imposta setRecordingHint(boolean)
su true
prima di avviare l'anteprima. Questa impostazione può aiutare a ridurre il tempo necessario per avviare la registrazione.
Configurazione di MediaRecorder
Se utilizzi la classe MediaRecorder
per registrare video, devi eseguire i passaggi di configurazione in un ordine specifico e quindi chiamare il metodo MediaRecorder.prepare()
per verificare e implementare la configurazione. Il codice di esempio seguente 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 è dimostrato 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
ricevono impostazioni predefinite; tuttavia, ti consigliamo di modificare queste impostazioni per la tua applicazione:
setVideoEncodingBitRate()
setVideoSize()
setVideoFrameRate()
setAudioEncodingBitRate()
setAudioChannels()
setAudioSamplingRate()
Avvio e arresto di MediaRecorder
Quando avvii e interrompi la registrazione video con il corso MediaRecorder
,
devi seguire un ordine specifico, come indicato di seguito.
- Sblocca la fotocamera con
Camera.unlock()
- Configura
MediaRecorder
come mostrato nell'esempio di codice riportato sopra - Avvia la registrazione usando
MediaRecorder.start()
- Registra il video
- Interrompi la registrazione con
MediaRecorder.stop()
- Rilascia il registratore multimediale con
MediaRecorder.release()
- Blocca la fotocamera usando
Camera.lock()
Il codice di esempio riportato di seguito 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 fotocamera 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 consente di bloccare la videocamera, configurare e preparare l'istanza MediaRecorder
.
Rilascio della fotocamera
Le videocamere sono una risorsa condivisa dalle applicazioni su un dispositivo. La tua applicazione può utilizzare la fotocamera dopo aver ricevuto un'istanza di Camera
e devi prestare particolare attenzione a rilasciare l'oggetto fotocamera quando l'applicazione smette di utilizzarlo e appena l'applicazione viene messa in pausa (Activity.onPause()
). Se l'applicazione non rilascia correttamente la fotocamera, tutti i successivi tentativi di accesso alla fotocamera, inclusi quelli della tua applicazione, non andranno a buon fine e potrebbero causare la chiusura di te 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 successivi tentativi di accesso alla fotocamera, inclusi quelli della tua applicazione, non andranno a buon fine e potrebbero causare l'arresto della tua o di altre applicazioni.
Salvataggio dei file multimediali
I file multimediali creati dagli utenti, ad esempio foto e video, devono essere salvati nella directory di archiviazione esterna (scheda SD) del dispositivo per risparmiare spazio di sistema e consentire agli utenti di accedere ai file senza il proprio dispositivo. Esistono molte posizioni di directory possibili per salvare i file multimediali su un dispositivo, ma esistono solo due posizioni standard che è consigliabile considerare in qualità di sviluppatore:
Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_PICTURES
): questo metodo restituisce la posizione standard, condivisa e consigliata per il salvataggio di foto e video. Questa directory è condivisa (pubblica), pertanto altre applicazioni possono scoprire, leggere, modificare ed eliminare facilmente 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 dell'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 le chiamate equivalenti nelle versioni precedenti dell'API, consulta Salvataggio dei file condivisi.Context.getExternalFilesDir
(Environment.DIRECTORY_PICTURES
): questo metodo restituisce una posizione standard in cui salvare le immagini e i video associati alla tua applicazione. Se l'applicazione viene disinstallata, tutti i file salvati in questa posizione vengono rimossi. La sicurezza non viene applicata in modo forzato per i file in questa posizione e altre applicazioni potrebbero leggerli, modificarli ed eliminarli.
Il codice di esempio seguente mostra come creare un percorso File
o Uri
per un file multimediale da utilizzare quando si richiama la fotocamera di un dispositivo con
un dispositivo Intent
o nell'ambito di un'app per la 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 su Android 2.2 (livello API 8) o versioni successive. Se hai scelto come target dispositivi con versioni precedenti di Android, utilizza invece Environment.getExternalStorageDirectory()
. Per ulteriori informazioni, consulta la sezione Salvataggio dei file condivisi.
Per rendere i profili di lavoro di supporto dell'URI, 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 ulteriori informazioni su come salvare i file su un dispositivo Android, consulta la sezione Archiviazione dei dati.
Funzionalità della fotocamera
Android supporta un'ampia gamma di funzionalità della fotocamera che puoi controllare con l'applicazione Fotocamera, ad esempio il formato dell'immagine, la modalità flash, le impostazioni della messa a fuoco e molte altre. Questa sezione elenca le funzionalità
comuni della fotocamera e spiega brevemente come usarle. La maggior parte delle funzionalità della fotocamera è accessibile e
impostata utilizzando l'oggetto tramite Camera.Parameters
. Tuttavia, esistono diverse
funzionalità importanti che richiedono impostazioni più semplici 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à di seguito alla documentazione di riferimento dell'API.
Funzionalità | Livello API | Descrizione |
---|---|---|
Rilevamento facciale | 14 | Identifica i volti umani in una foto e usali per la messa a fuoco, la misurazione e l'equilibrio del bianco |
Aree di misurazione | 14 | Specifica una o più aree di un'immagine per il calcolo del bilanciamento del bianco |
Aree di interesse | 14 | Imposta una o più aree dell'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 (aderenza di fotogrammi) |
Video time-lapse | 11 | Registra fotogrammi con ritardi impostati per registrare un video in time-lapse |
Multiple Cameras |
9 | Supporto di più videocamere su un dispositivo, incluse quelle anteriori e posteriori |
Focus Distance |
9 | Segnala le distanze tra la fotocamera e gli oggetti che sembrano essere a fuoco |
Zoom |
8 | Imposta ingrandimento immagine |
Exposure
Compensation |
8 | Aumentare o diminuire il livello di esposizione alla luce |
GPS Data |
5 | Includi o ometti dati sulla posizione geografica con l'immagine |
White Balance |
5 | Consente di impostare la modalità di bilanciamento del bianco, che influisce sui valori di colore nell'immagine acquisita |
Focus Mode |
5 | Consente di impostare il modo in cui la fotocamera mette a fuoco un soggetto, ad esempio automatico, fisso, macro o infinito |
Scene Mode |
5 | Applica una modalità preimpostata per tipi specifici di situazioni fotografiche, ad esempio scene notturne, in spiaggia, 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 la dimensione del file di output |
Flash Mode |
5 | Attiva, disattiva il flash o utilizza l'impostazione automatica |
Color Effects |
5 | Applica un effetto di colore all'immagine acquisita, ad esempio bianco e nero, seppia o negativo. |
Anti-Banding |
5 | Riduce l'effetto delle bande nei gradienti di colore a causa della compressione JPEG |
Picture Format |
1 | Specifica il formato file per l'immagine |
Picture Size |
1 | Specifica le dimensioni in pixel dell'immagine salvata |
Nota: queste funzionalità non sono supportate su tutti i dispositivi a causa delle differenze hardware e dell'implementazione del software. Per informazioni su come verificare la disponibilità delle funzionalità sul dispositivo su cui è in esecuzione l'applicazione, vedi Verificare la disponibilità delle funzionalità.
Verifica della disponibilità della funzionalità in corso...
La prima cosa da capire quando si configura l'utilizzo delle funzionalità della fotocamera sui dispositivi Android è che non tutte le funzionalità della fotocamera sono supportate su tutti i dispositivi. Inoltre, i dispositivi che supportano determinate funzionalità potrebbero supportarle in vari livelli o con opzioni differenti. Di conseguenza, parte del processo decisionale durante lo sviluppo di un'applicazione per fotocamera è decidere quali funzionalità della fotocamera supportare e a quale livello. Dopo aver preso questa decisione, dovresti pianificare l'inclusione di codice nell'applicazione della videocamera che verifica se l'hardware del dispositivo supporta quelle funzionalità e che non funziona correttamente se una funzione non è disponibile.
Puoi verificare 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 verificare 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 descritta sopra per la maggior parte delle funzionalità della fotocamera. 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 file manifest dell'applicazione. Quando dichiari l'uso 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 è possibile dichiarare nel file manifest dell'app, consulta il riferimento sulle funzionalità del file manifest.
Utilizzo delle funzionalità della fotocamera
La maggior parte delle funzionalità della videocamera viene attivata e controllata tramite un oggetto Camera.Parameters
. Puoi ottenere questo oggetto recuperando prima un'istanza dell'oggetto Camera
, chiamando il metodo getParameters()
, modificando l'oggetto parametro restituito e quindi impostandolo di nuovo nell'oggetto fotocamera, come mostrato nel seguente codice di esempio:
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 all'utente immediatamente nell'anteprima della fotocamera dell'applicazione.
Sul lato software, le modifiche ai parametri possono richiedere diversi fotogrammi prima di diventare effettive mentre l'hardware della fotocamera elabora le nuove istruzioni e poi invia dati immagine aggiornati.
Importante: alcune funzionalità della fotocamera non possono essere modificate a tuo piacimento. In particolare, per modificare le dimensioni o l'orientamento dell'anteprima della fotocamera occorre prima interrompere l'anteprima, modificarne le dimensioni e quindi riavviarla. A partire da Android 4.0 (Livello API 14) l'orientamento dell'anteprima può essere modificato senza riavviarlo.
Altre funzionalità della fotocamera richiedono più codice per essere implementate, tra cui:
- Misurazione e aree di messa a fuoco
- Riconoscimento facciale
- Video time-lapse
Nelle sezioni seguenti viene fornito un breve riepilogo 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 del livello di messa a fuoco o di luce e trasferire questi valori all'hardware della fotocamera per l'acquisizione di immagini o video.
Le aree per la misurazione e la messa a fuoco funzionano in modo molto simile alle altre funzionalità della fotocamera, poiché puoi controllarle tramite 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 fotocamera e un valore di peso, che indica alla fotocamera il livello di importanza che l'area dovrebbe assegnare alla misurazione della luce o ai calcoli di messa a fuoco.
Il campo Rect
in un oggetto Camera.Area
descrive una forma rettangolare mappata su una griglia di unità di 2000 x 2000. Le coordinate -1000, -1000
rappresentano l'angolo in alto a sinistra dell'immagine della fotocamera, mentre le coordinate 1000, 1000 rappresentano
l'angolo in basso a destra dell'immagine della fotocamera, come mostrato nell'illustrazione seguente.
I limiti di questo sistema di coordinate corrispondono sempre al bordo esterno dell'immagine visibile nell'anteprima della fotocamera e non si riducono o si 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
Nel caso di foto che includono persone, i volti sono in genere la parte più importante dell'immagine e dovrebbero essere utilizzati per determinare la messa a fuoco e il bilanciamento del bianco quando si scatta un'immagine. Il framework Android 4.0 (livello API 14) fornisce API per l'identificazione dei volti e il calcolo delle impostazioni delle immagini utilizzando la tecnologia di riconoscimento facciale.
Nota: mentre la funzionalità di rilevamento dei volti è in esecuzione,
setWhiteBalance(String)
,
setFocusAreas(List<Camera.Area>)
e
setMeteringAreas(List<Camera.Area>)
non hanno effetto.
L'uso della funzionalità di rilevamento dei volti nell'applicazione della fotocamera richiede alcuni passaggi generali:
- Verificare che il rilevamento dei volti sia supportato sul dispositivo
- Crea un listener per il rilevamento dei volti
- Aggiungere il listener di rilevamento dei volti all'oggetto della videocamera
- Avvia il rilevamento dei volti dopo l'anteprima (e dopo ogni riavvio dell'anteprima)
La funzionalità di rilevamento dei volti non è supportata su tutti i dispositivi. Puoi verificare se questa funzionalità è supportata chiamando il numero getMaxNumDetectedFaces()
. Un esempio di questo controllo è mostrato nel metodo di esempio startFaceDetection()
riportato di seguito.
Per ricevere notifiche e rispondere al rilevamento di un volto, l'applicazione della videocamera deve impostare un listener per gli eventi di rilevamento dei volti. A questo scopo, 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, puoi impostarla 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 dei volti in modo da poterlo chiamare in base alle esigenze, 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()
a entrambi i 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: ricorda di chiamare questo metodo dopo aver chiamato
startPreview()
. Non tentare di avviare il rilevamento dei volti
nel metodo onCreate()
dell'attività principale dell'app Fotocamera,
poiché a questo punto l'anteprima non è disponibile nell'esecuzione dell'applicazione.
Video time-lapse
I video in time-lapse consentono agli utenti di creare video clip che combinano immagini scattate a intervalli di qualche secondo o
minuti. Questa funzionalità utilizza MediaRecorder
per registrare le immagini in una sequenza time-lapse.
Per registrare un video in time-lapse con MediaRecorder
, devi configurare l'oggetto registratore come se stessi registrando un video normale, impostare un numero basso di fotogrammi al secondo acquisiti e utilizzare 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 effettuate nell'ambito di una procedura di configurazione più ampia per MediaRecorder
. Per un esempio di codice di configurazione completo, consulta Configurazione di MediaRecorder. Completata la configurazione,
avvii la registrazione video come se stessi registrando un normale video clip. Per ulteriori informazioni
sulla configurazione e sull'esecuzione di MediaRecorder
, consulta la sezione Acquisizione dei video.
Gli esempi di Fotocamera2Video e HdrViewfinder dimostrano ulteriormente l'utilizzo delle API trattate in questa pagina.
Campi della fotocamera che richiedono l'autorizzazione
Le app con Android 10 (livello API 29) o versioni successive devono avere l'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 app di esempio, vedi l'esempio di Camera2Basic e l'esempio dell'app ufficiale CameraX.