API Camera

Il framework Android include il supporto di varie fotocamere e funzionalità disponibili su per acquisire immagini e video nelle tue applicazioni. Questo documento illustra un approccio rapido e semplice per l'acquisizione di immagini e video e delinea un approccio avanzato per creare esperienze con la fotocamera personalizzate per i tuoi utenti.

Nota: In questa pagina vengono descritti i Camera che è stata ritirata. Ti consigliamo di utilizzare la libreria Jetpack CameraX o, per casi d'uso specifici, la classe camera2. Sia CameraX che Camera2 funzionano su Android 5.0 (livello API 21) e in alto.

Considerazioni

Prima di consentire alla tua applicazione di utilizzare le fotocamere sui dispositivi Android, considera alcune domande sulla modalità di utilizzo di questa funzionalità hardware da parte dell'app.

  • Requisito della 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 istantanea o fotocamera personalizzata: in che modo la tua applicazione utilizzerà la fotocamera? Ti interessa solo scattare una foto o un video clip o la tua applicazione offrono un nuovo modo di utilizzare le videocamere? Per ottenere uno scatto o una clip veloci, Utilizzare le app Fotocamera esistenti. Per sviluppare una funzionalità della fotocamera personalizzata, consulta la sezione Creare un'app per la fotocamera.
  • Requisito per i servizi in primo piano: quando interagisce la tua app con la fotocamera? Su Android 9 (livello API 28) e versioni successive, le app in esecuzione nel lo sfondo non può 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 app devono essere visibili solo alla tua app o condivisi in modo che altre app come Galleria o altre app di social e contenuti multimediali possano utilizzarli? Vuoi che le foto e i video siano disponibili anche se l'applicazione viene disinstallata? Consulta la sezione Salvataggio di file multimediali per scopri come implementare queste opzioni.

Nozioni di base

Il framework Android supporta l'acquisizione di immagini e video tramite l'android.hardware.camera2 API o la fotocamera Intent. Ecco le informazioni pertinenti classi:

android.hardware.camera2
Questo pacchetto è l'API principale per il controllo delle fotocamere dei dispositivi. Può essere utilizzato per scattare foto o registrare video quando crei un'applicazione per fotocamere.
Camera
Questa classe è l'API precedente deprecata per il controllo delle fotocamere del dispositivo.
SurfaceView
Questo corso viene utilizzato per presentare all'utente un'anteprima in diretta della fotocamera.
MediaRecorder
Questo corso viene utilizzato per registrare video dalla videocamera.
Intent
Un tipo di azione di intent MediaStore.ACTION_IMAGE_CAPTURE o MediaStore.ACTION_VIDEO_CAPTURE può essere utilizzato per acquisire immagini o video senza utilizzare direttamente l'oggetto Camera.

Dichiarazioni manifest

Prima di iniziare a sviluppare la tua 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. L'applicazione deve richiedere l'autorizzazione a utilizzare un dispositivo. fotocamera.
    <uses-permission android:name="android.permission.CAMERA" />

    Nota: se utilizzi la videocamera chiamando un'app di fotocamera esistente, la tua applicazione non deve richiedere questa autorizzazione.

  • Funzionalità della fotocamera. L'applicazione deve inoltre dichiarare l'utilizzo delle funzionalità della fotocamera. Ad esempio:
    <uses-feature android:name="android.hardware.camera" />

    Per un elenco delle funzionalità della fotocamera, consulta il file manifest Funzionalità Riferimento.

    Se aggiungi funzionalità della videocamera al file manifest, Google Play impedisce alla tua applicazione di l'installazione su dispositivi che non includono una videocamera o che non supportano le relative funzionalità specificare. Per saperne di più sull'utilizzo dei filtri basati sulle funzionalità con Google Play, consulta Google Play e i filtri basati sulle funzionalità.

    Se la tua applicazione può utilizzare una fotocamera o una funzionalità della fotocamera per il corretto funzionamento, ma non è obbligatorio, devi specificarlo nel file manifest includendo l'attributo android:required e impostandolo su false:

    <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 file 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 le informazioni sulla posizione GPS, devi richiedere ACCESS_FINE_LOCATION autorizzazione. Tieni presente che, se la tua app ha come target Android 5.0 (livello API 21) oppure superiore, 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 Strategie di geolocalizzazione.

Usare app della fotocamera esistenti

Un modo rapido per scattare foto o registrare video nella tua applicazione senza molto codice aggiuntivo consiste nell'utilizzare un Intent per richiamare un'applicazione della fotocamera Android esistente. I dettagli sono descritti nei tutorial Fotografare 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 offra funzionalità speciali. Scrivere codice personalizzato per scattare foto può offrire un'esperienza più accattivante agli utenti.

Nota: la guida riportata di seguito è relativa all'API Camera precedente, deprecata. Per le applicazioni per fotocamere nuove o avanzate, è consigliata la nuova API android.hardware.camera2.

Di seguito sono riportati i passaggi generali per la creazione di un'interfaccia della videocamera personalizzata per la tua applicazione:

  • Rileva e accedi alla videocamera: crea codice per verificare l'esistenza di videocamere e richiedere l'accesso.
  • Crea un corso in anteprima: crea una classe di anteprima della fotocamera che estende SurfaceView e implementa l'interfaccia SurfaceHolder. Questo di classe mostra l'anteprima delle immagini in diretta della fotocamera.
  • Crea un layout di anteprima: dopo aver creato la classe di anteprima della videocamera, crea un layout di visualizzazione che includa l'anteprima e i controlli dell'interfaccia utente che preferisci.
  • Configura listener per l'acquisizione: connetti i listener per la tua interfaccia. per avviare l'acquisizione di immagini o video in risposta alle azioni dell'utente, ad esempio la pressione di un .
  • 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: correttamente rilasciarlo per l'uso da parte di altre applicazioni.

L'hardware della videocamera è 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 fotocamera, come richiedere l'accesso a una fotocamera, come acquisire foto o video e come rilasciare la fotocamera quando l'applicazione ha finito di utilizzarla.

Attenzione: ricorda di rilasciare Camera richiamando Camera.release() quando l'applicazione usarla. Se l'applicazione non rilascia correttamente la fotocamera, i tentativi successivi di accesso alla fotocamera, inclusi quelli effettuati dalla tua applicazione, non andranno a buon fine e potrebbero l'arresto della tua applicazione o di altre applicazioni.

Rilevamento dell'hardware della videocamera in corso...

Se la tua applicazione non richiede specificamente una videocamera con una dichiarazione del file manifest, devi controllare se una videocamera è 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 (API Livello 9) e versioni successive ti consente di controllare numero di videocamere disponibili su un dispositivo con il metodo Camera.getNumberOfCameras().

Accesso alle videocamere

Se hai stabilito che il dispositivo su cui è in esecuzione la tua applicazione è dotato di una fotocamera, devi richiedere l'accesso ottenendo un'istanza di Camera (a meno che tu stai utilizzando un intent per accedere alla fotocamera).

Per accedere alla fotocamera principale, utilizza il metodo Camera.open() e assicurati di intercettare 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: controlla sempre la presenza di eccezioni quando utilizzi Camera.open(). Se non controlli la presenza di 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 fotocamere specifiche utilizzando Camera.open(int). Il codice di esempio riportato sopra consente di accedere la prima fotocamera posteriore di 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 le funzionalità supportate nell'oggetto Camera.Parameters restituito. Quando utilizzi il livello API 9 o versioni successive, utilizza Camera.getCameraInfo() per determinare se una fotocamera si trova sulla parte anteriore o posteriore del dispositivo e l'orientamento dell'immagine.

Creazione di un corso di anteprima

Per poter scattare foto o registrare video in modo efficace, gli utenti devono essere in grado di vedere la fotocamera del dispositivo vede. Un'anteprima della fotocamera è un SurfaceView che può visualizzare i dati delle immagini in tempo reale provenienti da una videocamera, in modo che gli utenti possano inquadrare e acquisire una foto o un video.

Il seguente codice di esempio illustra come creare una classe di anteprima di base della fotocamera che può essere incluso in un layout View. Questa classe implementa SurfaceHolder.Callback per acquisire gli eventi di callback per creare ed eliminare la vista, necessarie 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 di anteprima, deve utilizzare 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ù assumere che le proporzioni dell'anteprima corrispondano a quelle della tua attività anche dopo aver chiamato setDisplayOrientation(). A seconda delle dimensioni e delle proporzioni della finestra, potresti dover adattare l'anteprima della videocamera in un layout orizzontale o viceversa, utilizzando un layout letterbox.

Inserire l'anteprima in un layout

Una classe di anteprima della fotocamera, come l'esempio mostrato nella sezione precedente, deve essere inserita nella layout di un'attività insieme ad altri controlli dell'interfaccia utente per scattare foto o registrare video. Questo mostra come creare un layout di base e un'attività per l'anteprima.

Il seguente codice di layout fornisce una visualizzazione di base che può essere utilizzata per visualizzare un'anteprima della fotocamera. In questo esempio, l'elemento FrameLayout deve essere il contenitore della classe di anteprima della fotocamera. Questo tipo di layout viene utilizzato per mostrare informazioni o controlli possono essere sovrapposti alle immagini di anteprima della fotocamera 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 fotocamera è orizzontale. Questo layout di esempio specifica un layout orizzontale e il codice seguente fissa l'orientamento del dall'applicazione all'orientamento 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 fotocamera non deve essere necessariamente 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 cambiare l'orientamento dell'anteprima quando l'utente orienta nuovamente la telefono, nel metodo surfaceChanged() della lezione in anteprima, interrompi prima l'anteprima con Camera.stopPreview() modifica l'orientamento, quindi riavvia l'anteprima con Camera.startPreview().

Nell'attività per la visualizzazione della videocamera, aggiungi la classe di anteprima all'elemento FrameLayout mostrato nell'esempio sopra. L'attività della videocamera deve inoltre assicurati di rilasciare la videocamera quando è in pausa o si spegne. L'esempio seguente mostra come per modificare un'attività della videocamera per allegare la lezione di anteprima mostrata in Creazione di un corso in 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 Accedere alle videocamere.

Acquisizione di foto

Dopo aver creato un corso di anteprima e un layout di visualizzazione in cui mostrarlo, sei pronto a 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 fotocamera. Per ricevere dati in formato JPEG, devi implementare un'interfaccia Camera.PictureCallback per ricevere i dati dell'immagine e e scriverlo 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 codice di esempio 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 Camera richiamando Camera.release() quando l'applicazione usarla. Per informazioni su come sbloccare la fotocamera, consulta Sbloccare la fotocamera.

Registrazione di video

L'acquisizione di video con il framework Android richiede una gestione accurata dell'oggetto Camera e la coordinazione con 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 di quanto accade quando si scattano foto con la fotocamera di un dispositivo, l'acquisizione di video richiede un ordine di chiamate molto particolare. Per preparare e acquisire correttamente i video con la tua applicazione, devi seguire un ordine di esecuzione specifico, come descritto di seguito.

  1. Apri Fotocamera. Usa l'Camera.open() per ottenere un'istanza dell'oggetto camera.
  2. Anteprima connessione: prepara un'anteprima delle immagini della videocamera in diretta collegando un SurfaceView alla videocamera utilizzando Camera.setPreviewDisplay().
  3. Avvia anteprima: chiama Camera.startPreview() per iniziare a visualizzare le immagini in diretta della videocamera.
  4. Avvia registrazione video: per registrare correttamente il video, devi completare i seguenti passaggi in ordine:
    1. Sblocca la fotocamera: sblocca la fotocamera per l'utilizzo da parte di MediaRecorder chiamando Camera.unlock().
    2. Configura MediaRecorder: chiama i seguenti metodi MediaRecorder in questo ordine. Per ulteriori informazioni, consulta la documentazione di riferimento MediaRecorder.
      1. setCamera(): imposta la fotocamera da utilizzare per l'acquisizione video, utilizza l'istanza corrente di Camera dell'applicazione.
      2. setAudioSource() - Imposta il parametro usa MediaRecorder.AudioSource.CAMCORDER.
      3. setVideoSource() - Per impostare la sorgente video, utilizza MediaRecorder.VideoSource.CAMERA.
      4. Imposta il formato di output video e la codifica. Per Android 2.2 (livello API 8) e versioni successive, utilizza il metodo MediaRecorder.setProfile e ottieni un'istanza del profilo utilizzando CamcorderProfile.get(). Per le versioni di Android precedenti 2.2, devi impostare il formato di output del video e i parametri di codifica:
        1. setOutputFormat() - Imposta il formato di output, specifica l'impostazione predefinita o MediaRecorder.OutputFormat.MPEG_4.
        2. setAudioEncoder() - Imposta il tipo di codifica audio, specifica l'impostazione predefinita o MediaRecorder.AudioEncoder.AMR_NB.
        3. setVideoEncoder() - Imposta il tipo di codifica video, specifica l'impostazione predefinita o MediaRecorder.VideoEncoder.MPEG_4_SP.
      5. setOutputFile() - Imposta il file di output, utilizza getOutputMediaFile(MEDIA_TYPE_VIDEO).toString() dal metodo di esempio nella sezione Salvataggio dei file multimediali.
      6. setPreviewDisplay(): specifica l'elemento di layout dell'anteprima setPreviewDisplay() per la tua applicazione. Utilizza lo stesso oggetto specificato per Connect Preview.

      Attenzione:devi chiamare questi metodi di configurazione MediaRecorder in questo ordine, altrimenti i tuoi l'applicazione riscontrerà errori e la registrazione non andrà a buon fine.

    3. Prepara MediaRecorder: prepara MediaRecorder con le impostazioni di configurazione fornite chiamando MediaRecorder.prepare().
    4. Avvia MediaRecorder: avvia la registrazione di video chiamando il numero MediaRecorder.start().
  5. Interrompi registrazione video: chiama i seguenti metodi nell'ordine per completare correttamente una registrazione video:
    1. Interrompi MediaRecorder: interrompi la registrazione video chiamando MediaRecorder.stop().
    2. Ripristina MediaRecorder: se vuoi, rimuovi le impostazioni di configurazione dal registratore chiamando MediaRecorder.reset().
    3. Rilascia MediaRecorder: rilascia MediaRecorder chiamando MediaRecorder.release().
    4. Blocca la videocamera: blocca la videocamera in modo che le sessioni MediaRecorder future possano utilizzarla chiamando il numero Camera.lock(). A partire da Android 4.0 (livello API 14), questa chiamata non è necessaria, a meno che non venga Chiamata MediaRecorder.prepare() non riuscita.
  6. Interrompi l'anteprima: al termine dell'attività di utilizzo della fotocamera, interrompi utilizzando Camera.stopPreview().
  7. Rilascia fotocamera: rilascia la fotocamera per consentire ad altre applicazioni di utilizzarla. chiamando Camera.release().

Nota: è possibile utilizzare MediaRecorder senza creare prima un'anteprima della videocamera e salta i primi passaggi di questa procedura. Tuttavia, poiché gli utenti preferiscono vedere un'anteprima prima di avviare la registrazione, questo processo non di cui parleremo qui.

Suggerimento: se la tua applicazione viene solitamente utilizzata per la registrazione di video, imposta dal giorno setRecordingHint(boolean) al giorno true prima di iniziare 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 passaggi di configurazione in un ordine specifico, quindi chiama il metodo MediaRecorder.prepare() per verificare e implementare il 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 di formato di output e di 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 sono le impostazioni predefinite, ma ti consigliamo di modificarle in base alle tue esigenze:

Avvio e arresto di MediaRecorder

Quando avvii e interrompi la registrazione video utilizzando la classe MediaRecorder, devi seguire un ordine specifico, come indicato di seguito.

  1. Sbloccare la videocamera con Camera.unlock()
  2. Configura MediaRecorder come mostrato nel codice di esempio in alto
  3. Avvia la registrazione usando MediaRecorder.start()
  4. Registra il video
  5. Interrompi la registrazione utilizzando MediaRecorder.stop()
  6. Rilascia il registratore multimediale con MediaRecorder.release()
  7. Bloccare la fotocamera 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 campo prepareVideoRecorder() fa riferimento al codice di esempio mostrato in Configurazione di MediaRecorder. Questo metodo consente di bloccare la videocamera, configurando e preparando l'istanza MediaRecorder.

Rilascio della fotocamera

Le videocamere sono una risorsa condivisa dalle applicazioni su un dispositivo. La tua applicazione può l'utilizzo della videocamera dopo aver ricevuto un'istanza di Camera e devi avere particolarmente attento a rilasciare l'oggetto fotocamera quando l'applicazione smette di utilizzarlo e non appena l'applicazione viene messa in pausa (Activity.onPause()). Se l'applicazione non rilascia correttamente la fotocamera, in tutti i tentativi successivi di accesso alla fotocamera incluse quelle della tua applicazione, non riusciranno e potrebbero causare il è stato arrestato.

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 il videocamera, tutti i tentativi successivi di accesso alla videocamera, inclusi quelli effettuati dalla tua applicazione, potrebbero non funzionare e causare l'arresto dell'applicazione o di altre applicazioni.

Salvataggio dei file multimediali

I file multimediali creati dagli utenti, come immagini e video, devono essere salvati sull'esterno del dispositivo directory di archiviazione (scheda SD) per risparmiare spazio di sistema e consentire agli utenti di accedere a questi file senza il loro dispositivo. Esistono molte posizioni di directory possibili per salvare i file multimediali su un dispositivo, tuttavia, come 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 foto e video. Questa directory è condivisa (pubblica), pertanto altre applicazioni possono facilmente trovare, leggere, modificare ed eliminare i file salvati in questa posizione. Se la tua applicazione è disinstallati dall'utente, i file multimediali salvati in questa posizione non verranno rimossi. Per evitare di interferire con le foto 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 di seguito. Questo metodo è disponibile in Android 2.2 (livello API 8). Per le chiamate equivalenti nelle versioni API precedenti, consulta la sezione Salvataggio di file condivisi.
  • Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES): questo metodo restituisce una posizione standard per 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 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 da utilizzare quando si chiama la fotocamera di un dispositivo con un Intent o nell'ambito di una creazione di una videocamera App.

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() . Per ulteriori informazioni, vedi Salvataggio di file condivisi.

Affinché l'URI supporti i profili di lavoro, per prima cosa l'URI del file in un URI dei contenuti. Quindi, aggiungi l'URI dei contenuti a EXTRA_OUTPUT di Intent.

Per ulteriori informazioni sul salvataggio di file su un dispositivo Android, consulta Spazio di archiviazione dei dati.

Funzionalità della fotocamera

Android supporta un'ampia gamma di funzionalità della fotocamera che puoi controllare con l'applicazione della fotocamera, come il formato delle immagini, la modalità flash, le impostazioni di messa a fuoco e molte altre. Questa sezione elenca le funzionalità comuni della fotocamera e illustra brevemente come utilizzarle. È possibile accedere alla maggior parte delle funzionalità della fotocamera e impostarle utilizzando l'oggetto through Camera.Parameters. Tuttavia, ci sono diversi 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 le sezioni relative all'uso della fotocamera funzionalità. 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.

Tabella 1. Funzionalità comuni della fotocamera ordinate in base al livello API Android in cui vengono sono stati introdotti.

Funzionalità Livello API Descrizione
Rilevamento facciale 14 Identificare i volti umani all'interno di un'immagine e utilizzarli per messa a fuoco, misurazione e bilanciamento del bianco
Misurazione delle aree 14 Specifica una o più aree all'interno di un'immagine per calcolare il bilanciamento del bianco
Aree di interesse 14 Imposta una o più aree 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 (acquisizione frame)
Video time-lapse 11 Registra fotogrammi con ritardi impostati per registrare un video in time-lapse
Multiple Cameras 9 Supporto di più fotocamere su un dispositivo, incluse quelle anteriore e posteriore videocamere
Focus Distance 9 Indica le distanze tra la fotocamera e gli oggetti che sembrano essere a fuoco
Zoom 8 Imposta l'ingrandimento dell'immagine
Exposure Compensation 8 Aumentare o diminuire il livello di esposizione alla luce
GPS Data 5 Includi o ometti 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 Impostare la modalità di 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 notti, spiagge, neve o scene 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, disattivare o utilizzare l'impostazione automatica del flash
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 banding nelle sfumature di colore dovuto alla 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 di implementazione del software. Per informazioni sulla verifica della disponibilità di funzionalità sul dispositivo su cui è in esecuzione l'applicazione, consulta la sezione Verificare la disponibilità delle funzionalità.

Verifica della disponibilità della funzionalità in corso...

La prima cosa da capire quando decidi di usare 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 un particolare funzionalità può supportarli con livelli diversi o con opzioni differenti. Pertanto, parte del tuo durante lo sviluppo di un'applicazione di fotocamera è decidere quali funzionalità della videocamera assistenza e a quale livello. Dopo aver preso questa decisione, ti consigliamo di includere nell'applicazione della videocamera un codice che controlli se l'hardware del dispositivo supporta queste funzionalità e che interrompa il funzionamento in modo corretto se una funzionalità non è disponibile.

Puoi verificare la disponibilità delle funzionalità della videocamera ricevendo un'istanza dei parametri di una videocamera e controllando i metodi pertinenti. Il seguente esempio di codice mostra come ottenere un Camera.Parameters oggetto e controlla se la fotocamera supporta la messa a fuoco automatica funzionalità:

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. La L'oggetto Camera.Parameters fornisce un metodo getSupported...(), is...Supported() o getMax...() per determinare se (e in quale misura) una caratteristica è supportati.

Se la tua applicazione richiede determinate funzionalità della fotocamera per funzionare correttamente, puoi richiederle aggiungendole al file manifest dell'applicazione. Quando dichiari l'utilizzo di specifiche funzionalità della fotocamera, come il flash e la messa a fuoco automatica, Google Play impedisce alla tua applicazione su dispositivi che non supportano queste funzionalità. Per un elenco di funzionalità della fotocamera che puoi dichiarare nel file manifest dell'app, consulta il file manifest Funzionalità Riferimento.

Utilizzare le funzionalità della fotocamera

La maggior parte delle funzionalità della fotocamera viene attivata e controllata utilizzando un oggetto Camera.Parameters. Puoi ottenere questo oggetto ottenendo prima un'istanza l'oggetto Camera, chiamando il metodo getParameters(), modificando il parametro restituito per poi riposizionarlo nell'oggetto videocamera, come mostrato nell'esempio seguente 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 di tempo 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 frame prima di diventare effettive, poiché l'hardware della videocamera elabora le nuove istruzioni, quindi invia i dati immagine aggiornati.

Importante: alcune funzionalità della fotocamera non possono essere modificate a piacere. Nella particolare, la modifica delle dimensioni o dell'orientamento dell'anteprima della fotocamera richiede prima l'interruzione visualizzare l'anteprima, modificare le dimensioni e riavviare l'anteprima. A partire da Android 4.0 (API livello 14) può essere modificato senza riavviare l'anteprima.

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 previsti. A partire da Android 4.0 (Livello API 14), l'applicazione Fotocamera può fornire controlli aggiuntivi per consentire alla tua app o ai tuoi utenti di specificare le aree di un'immagine da utilizzare per determinare le impostazioni di messa a fuoco o del livello di luce e passa questi valori all'hardware della fotocamera per l'acquisizione immagini o video.

Le aree di misurazione e messa a fuoco funzionano in modo molto simile ad altre funzionalità della fotocamera, in quanto controllano mediante metodi nell'oggetto Camera.Parameters. Il seguente codice mostra l'impostazione di due aree di misurazione della luce per un 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 peso che indica alla videocamera il livello di importanza che attribuisci a quest'area per la misurazione della luce. o i calcoli del focus.

Il campo Rect in un oggetto Camera.Area descrive una forma rettangolare mappata su una griglia di 2000 x 2000 unità. Le coordinate -1000, -1000 rappresenta l'angolo superiore sinistro dell'immagine della fotocamera, mentre le coordinate 1000, 1000 rappresentano nell'angolo inferiore destro dell'immagine della fotocamera, come mostrato nell'illustrazione seguente.

Figura 1. Le linee rosse illustrano il sistema di coordinate per specificare un Camera.Area in un'anteprima della fotocamera. La casella blu mostra la posizione e la forma di un'area della fotocamera con i valori Rect 333.333.667.667.

I limiti di questo sistema di coordinate corrispondono sempre al bordo esterno dell'immagine visibile l'anteprima della fotocamera e non ridurre o espandere il livello di zoom. Analogamente, la rotazione dell'immagine anteprima con 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 sia il bilanciamento del bianco durante l'acquisizione di un'immagine. Android 4.0 (livello API 14) fornisce API per identificare i volti e calcolare le impostazioni delle immagini utilizzando di riconoscimento facciale.

Nota:mentre è attiva la funzione di rilevamento dei volti, setWhiteBalance(String), setFocusAreas(List<Camera.Area>) e setMeteringAreas(List<Camera.Area>) non hanno alcun effetto.

Per utilizzare la funzionalità di rilevamento dei volti nell'applicazione della fotocamera sono necessari alcuni passaggi generali:

  • Verificare che il rilevamento dei volti sia supportato sul dispositivo
  • Crea un listener di 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 che questa funzionalità supportato chiamando getMaxNumDetectedFaces(). Un un esempio di questo controllo è mostrato nel metodo campione startFaceDetection() riportato di seguito.

Per ricevere una notifica e rispondere al rilevamento di un volto, l'applicazione della videocamera deve impostare un ascoltatore per gli eventi di rilevamento dei volti. Per farlo, devi creare una classe di listener che implementi l'interfaccia Camera.FaceDetectionListener come mostrato nel codice di esempio 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 nel Camera, 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) la l'anteprima della fotocamera. 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 che utilizzi il corso di anteprima mostrato in Creazione di un corso in anteprima, aggiungi startFaceDetection() in entrambi i casi surfaceCreated() e surfaceChanged() nel corso in anteprima, come mostrato nel codice campione 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, poiché l'anteprima non è disponibile in questo punto dell'esecuzione dell'applicazione.

Video in time-lapse

I video in time-lapse consentono agli utenti di creare video clip che combinano immagini scattate qualche secondo oppure minuti l'uno dall'altro. Questa funzionalità utilizza MediaRecorder per registrare le immagini per una sequenza in time-lapse.

Per registrare un video in time-lapse con MediaRecorder, devi configurare la registratore come se stessi registrando un video normale, impostando i fotogrammi al secondo acquisiti su un numero basso 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 eseguite nell'ambito di una procedura di configurazione più ampia per MediaRecorder. Per un esempio di codice di configurazione completo, consulta Configurazione di MediaRecorder. Una volta 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 Acquisire video.

Gli esempi Camera2Video e HdrViewfinder dimostrano ulteriormente l'utilizzo delle API trattate in questa pagina.

Campi relativi alla fotocamera 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 app di esempio, consulta Camera2Basic sample e Official CameraX sample app.