Le framework Android est compatible avec les différentes caméras et fonctionnalités de caméra disponibles sur les appareils, ce qui vous permet de prendre des photos et des vidéos dans vos applications. Ce document présente une approche rapide et simple de la capture d'images et de vidéos, et décrit une approche avancée pour créer des expériences d'appareil photo personnalisées pour vos utilisateurs.
Remarque:Cette page décrit la classe Camera
, qui est obsolète. Nous vous recommandons d'utiliser la bibliothèque Jetpack CameraX ou, dans des cas d'utilisation spécifiques, la classe camera2
. CameraX et Camera2 fonctionnent sous Android 5.0 (niveau d'API 21) ou version ultérieure.
Consultez les ressources associées suivantes :
Points à prendre en compte
Avant d'autoriser votre application à utiliser des caméras sur des appareils Android, vous devez vous poser quelques questions sur la façon dont votre application prévoit d'utiliser cette fonctionnalité matérielle.
- Exigence concernant l'appareil photo : l'utilisation d'un appareil photo est-elle si importante pour votre application que vous ne souhaitez pas qu'elle soit installée sur un appareil qui n'en est pas équipé ? Si c'est le cas, vous devez déclarer l'exigence concernant la caméra dans votre fichier manifeste.
- Image rapide ou appareil photo personnalisé : comment votre application utilisera-t-elle l'appareil photo ? Vous souhaitez simplement prendre une photo ou un extrait vidéo rapide, ou votre application propose-t-elle une nouvelle façon d'utiliser les caméras ? Pour prendre une photo ou un extrait vidéo rapidement, envisagez d'utiliser les applications d'appareil photo existantes. Pour développer une fonctionnalité d'appareil photo personnalisée, consultez la section Créer une application d'appareil photo.
- Exigences concernant les services de premier plan : à quel moment votre application interagit-elle avec l'appareil photo ? Sur Android 9 (niveau d'API 28) ou version ultérieure, les applications exécutées en arrière-plan ne peuvent pas accéder à l'appareil photo. Par conséquent, vous devez utiliser la caméra lorsque votre application est au premier plan ou dans le cadre d'un service de premier plan.
- Stockage : les images ou vidéos générées par votre application sont-elles destinées à être visibles uniquement par votre application ou partagées afin que d'autres applications telles que la galerie ou d'autres applications multimédias et de réseaux sociaux puissent les utiliser ? Voulez-vous que les photos et vidéos soient disponibles même si votre application est désinstallée ? Consultez la section Enregistrer des fichiers multimédias pour découvrir comment implémenter ces options.
Principes de base
Le framework Android permet de capturer des images et des vidéos via l'API android.hardware.camera2
ou l'appareil photo Intent
. Voici les classes concernées:
android.hardware.camera2
- Ce package est l'API principale pour contrôler les caméras de l'appareil. Vous pouvez l'utiliser pour prendre des photos ou des vidéos lorsque vous créez une application d'appareil photo.
Camera
- Cette classe est l'ancienne API obsolète permettant de contrôler les caméras de l'appareil.
SurfaceView
- Cette classe permet de présenter à l'utilisateur un aperçu en direct de la caméra.
MediaRecorder
- Cette classe permet d'enregistrer des vidéos à partir de la caméra.
Intent
- Vous pouvez utiliser un type d'action d'intent
MediaStore.ACTION_IMAGE_CAPTURE
ouMediaStore.ACTION_VIDEO_CAPTURE
pour prendre des images ou des vidéos sans utiliser directement l'objetCamera
.
Déclarations de fichier manifeste
Avant de commencer à développer votre application avec l'API Camera, vous devez vous assurer que votre fichier manifeste contient les déclarations appropriées pour autoriser l'utilisation du matériel de la caméra et d'autres fonctionnalités associées.
- Autorisation d'accès à l'appareil photo : votre application doit demander l'autorisation d'utiliser l'appareil photo de l'appareil.
<uses-permission android:name="android.permission.CAMERA" />
Remarque:Si vous utilisez l'appareil photo en appelant une application d'appareil photo existante, votre application n'a pas besoin de demander cette autorisation.
- Fonctionnalités de l'appareil photo : votre application doit également déclarer l'utilisation des fonctionnalités de l'appareil photo, par exemple :
<uses-feature android:name="android.hardware.camera" />
Pour obtenir la liste des fonctionnalités de la caméra, consultez la documentation de référence sur les fonctionnalités du fichier manifeste.
Si vous ajoutez des fonctionnalités d'appareil photo à votre fichier manifeste, Google Play empêche l'installation de votre application sur les appareils qui n'en sont pas équipés ou qui ne prennent pas en charge les fonctionnalités d'appareil photo que vous spécifiez. Pour en savoir plus sur l'utilisation du filtrage basé sur les fonctionnalités avec Google Play, consultez Google Play et filtrage basé sur les fonctionnalités.
Si votre application peut utiliser une caméra ou une fonctionnalité d'appareil photo pour fonctionner correctement, mais qu'elle n'en a pas besoin, vous devez le spécifier dans le fichier manifeste en incluant l'attribut
android:required
et en le définissant surfalse
:<uses-feature android:name="android.hardware.camera" android:required="false" />
- Autorisation de stockage : votre application peut enregistrer des images ou des vidéos sur le stockage externe (carte SD) de l'appareil si elle cible Android 10 (niveau d'API 29) ou une version antérieure et spécifie les éléments suivants dans le fichier manifeste.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- Autorisation d'enregistrement audio : pour enregistrer de l'audio avec la capture vidéo, votre application doit demander l'autorisation de capture audio.
<uses-permission android:name="android.permission.RECORD_AUDIO" />
-
Autorisation d'accéder à la position : si votre application tague des images avec des informations de position GPS, vous devez demander l'autorisation
ACCESS_FINE_LOCATION
. Notez que si votre application cible Android 5.0 (niveau d'API 21) ou une version ultérieure, vous devez également déclarer que votre application utilise le GPS de l'appareil:<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" />
Pour en savoir plus sur l'obtention de la position de l'utilisateur, consultez la section Stratégies de localisation.
Utiliser des applications d'appareil photo existantes
Pour activer rapidement la prise de photos ou de vidéos dans votre application sans beaucoup de code supplémentaire, utilisez un Intent
pour appeler une application d'appareil photo Android existante.
Pour en savoir plus, consultez les leçons de formation Prendre des photos simplement et Enregistrer des vidéos simplement.
Créer une application d'appareil photo
Certains développeurs peuvent avoir besoin d'une interface utilisateur d'appareil photo personnalisée en fonction de l'apparence de leur application ou qui propose des fonctionnalités spéciales. Écrire votre propre code de prise de photo peut offrir une expérience plus attrayante à vos utilisateurs.
Remarque: Le guide suivant concerne l'ancienne API Camera
obsolète. Pour les nouvelles applications d'appareil photo ou les applications avancées, nous vous recommandons d'utiliser la nouvelle API android.hardware.camera2
.
Pour créer une interface d'appareil photo personnalisée pour votre application, procédez comme suit:
- Détecter et accéder à la caméra : créez du code pour vérifier l'existence de caméras et demander l'accès.
- Créer une classe d'aperçu : créez une classe d'aperçu de l'appareil photo qui étend
SurfaceView
et implémente l'interfaceSurfaceHolder
. Cette classe affiche un aperçu des images en direct de la caméra. - Créer une mise en page d'aperçu : une fois que vous disposez de la classe d'aperçu de l'appareil photo, créez une mise en page de vue qui intègre l'aperçu et les commandes d'interface utilisateur souhaitées.
- Configurer des écouteurs pour la capture : connectez des écouteurs aux commandes de votre interface pour lancer la capture d'image ou de vidéo en réponse aux actions de l'utilisateur, comme appuyer sur un bouton.
- Capturer et enregistrer des fichiers : configurez le code pour capturer des photos ou des vidéos et enregistrer la sortie.
- Libérer l'appareil photo : après avoir utilisé l'appareil photo, votre application doit le libérer correctement pour qu'il puisse être utilisé par d'autres applications.
Le matériel de la caméra est une ressource partagée qui doit être gérée avec soin pour que votre application ne se heurte pas à d'autres applications qui pourraient également vouloir l'utiliser. Les sections suivantes expliquent comment détecter le matériel de l'appareil photo, demander l'accès à un appareil photo, prendre des photos ou des vidéos et libérer l'appareil photo lorsque votre application a fini de l'utiliser.
Attention:N'oubliez pas de libérer l'objet Camera
en appelant Camera.release()
lorsque votre application a fini de l'utiliser. Si votre application ne libère pas correctement l'appareil photo, toutes les tentatives ultérieures d'accès à l'appareil photo, y compris celles de votre propre application, échoueront et peuvent entraîner l'arrêt de votre application ou d'autres applications.
Détecter le matériel de la caméra
Si votre application n'a pas besoin d'une caméra spécifique à l'aide d'une déclaration de fichier manifeste, vous devez vérifier si une caméra est disponible au moment de l'exécution. Pour effectuer cette vérification, utilisez la méthode PackageManager.hasSystemFeature()
, comme indiqué dans l'exemple de code ci-dessous:
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; } }
Les appareils Android peuvent être équipés de plusieurs caméras, par exemple d'une caméra arrière pour la photographie et d'une caméra avant pour les appels vidéo. Android 2.3 (niveau d'API 9) et versions ultérieures vous permettent de vérifier le nombre d'appareils photo disponibles sur un appareil à l'aide de la méthode Camera.getNumberOfCameras()
.
Accéder aux caméras
Si vous avez déterminé que l'appareil sur lequel votre application s'exécute est équipé d'une caméra, vous devez demander à y accéder en obtenant une instance de Camera
(sauf si vous utilisez un intent pour accéder à la caméra).
Pour accéder à la caméra principale, utilisez la méthode Camera.open()
et veillez à intercepter toutes les exceptions, comme indiqué dans le code ci-dessous:
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 }
Attention:Vérifiez toujours les exceptions lorsque vous utilisez Camera.open()
. Si vous ne vérifiez pas les exceptions si la caméra est utilisée ou n'existe pas, votre application sera arrêtée par le système.
Sur les appareils équipés d'Android 2.3 (niveau d'API 9) ou version ultérieure, vous pouvez accéder à des caméras spécifiques à l'aide de Camera.open(int)
. L'exemple de code ci-dessus accède à la première caméra arrière d'un appareil doté de plusieurs caméras.
Vérifier les fonctionnalités de la caméra
Une fois que vous avez obtenu l'accès à une caméra, vous pouvez obtenir plus d'informations sur ses fonctionnalités à l'aide de la méthode Camera.getParameters()
et en vérifiant les fonctionnalités compatibles dans l'objet Camera.Parameters
renvoyé. Lorsque vous utilisez le niveau d'API 9 ou version ultérieure, utilisez Camera.getCameraInfo()
pour déterminer si une caméra se trouve à l'avant ou à l'arrière de l'appareil, ainsi que l'orientation de l'image.
Créer une classe d'aperçu
Pour que les utilisateurs puissent prendre des photos ou enregistrer des vidéos de manière efficace, ils doivent pouvoir voir ce que voit la caméra de l'appareil. Une classe d'aperçu de l'appareil photo est un SurfaceView
qui peut afficher les données d'image en direct provenant d'une caméra afin que les utilisateurs puissent cadrer et prendre une photo ou une vidéo.
L'exemple de code suivant montre comment créer une classe d'aperçu de l'appareil photo de base pouvant être incluse dans une mise en page View
. Cette classe implémente SurfaceHolder.Callback
afin de capturer les événements de rappel pour créer et détruire la vue, qui sont nécessaires pour attribuer l'entrée d'aperçu de l'appareil photo.
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()); } } }
Si vous souhaitez définir une taille spécifique pour l'aperçu de l'appareil photo, définissez-la dans la méthode surfaceChanged()
, comme indiqué dans les commentaires ci-dessus. Lorsque vous définissez la taille d'aperçu, vous devez utiliser les valeurs de getSupportedPreviewSizes()
.
Ne définissez pas de valeurs arbitraires dans la méthode setPreviewSize()
.
Remarque:Avec l'introduction de la fonctionnalité
Multifenêtre dans Android 7.0 (niveau d'API 24) ou version ultérieure, vous ne pouvez plus supposer que le format de l'aperçu est le même que celui de votre activité, même après avoir appelé setDisplayOrientation()
.
En fonction de la taille et du format de la fenêtre, vous devrez peut-être adapter un aperçu d'appareil photo large à une mise en page en mode portrait, ou inversement, à l'aide d'une mise en page letterbox.
Placer un aperçu dans une mise en page
Une classe d'aperçu de l'appareil photo, comme l'exemple présenté dans la section précédente, doit être placée dans la mise en page d'une activité avec d'autres commandes d'interface utilisateur permettant de prendre une photo ou une vidéo. Cette section explique comment créer une mise en page et une activité de base pour l'aperçu.
Le code de mise en page suivant fournit une vue très basique qui peut être utilisée pour afficher un aperçu de l'appareil photo. Dans cet exemple, l'élément FrameLayout
doit être le conteneur de la classe d'aperçu de l'appareil photo. Ce type de mise en page permet de superposer des informations ou des commandes supplémentaires sur les images de l'aperçu en direct de la caméra.
<?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>
Sur la plupart des appareils, l'orientation par défaut de l'aperçu de l'appareil photo est le mode Paysage. Cet exemple de mise en page spécifie une mise en page horizontale (paysage), et le code ci-dessous fixe l'orientation de l'application en mode paysage. Pour simplifier l'affichage d'un aperçu de l'appareil photo, vous devez définir l'orientation de l'activité d'aperçu de votre application sur "paysage" en ajoutant ce qui suit à votre fichier manifeste.
<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>
Remarque:L'aperçu de l'appareil photo n'a pas besoin d'être en mode Paysage.
À partir d'Android 2.2 (niveau d'API 8), vous pouvez utiliser la méthode setDisplayOrientation()
pour définir la rotation de l'image d'aperçu. Pour modifier l'orientation de l'aperçu lorsque l'utilisateur réoriente le téléphone, dans la méthode surfaceChanged()
de votre classe d'aperçu, arrêtez d'abord l'aperçu avec Camera.stopPreview()
, modifiez l'orientation, puis redémarrez l'aperçu avec Camera.startPreview()
.
Dans l'activité de la vue de votre caméra, ajoutez votre classe d'aperçu à l'élément FrameLayout
illustré dans l'exemple ci-dessus. L'activité de la caméra doit également s'assurer qu'elle libère la caméra lorsqu'elle est mise en veille ou arrêtée. L'exemple suivant montre comment modifier une activité d'appareil photo pour associer la classe d'aperçu présentée dans la section Créer une classe d'aperçu.
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); } }
Remarque:La méthode getCameraInstance()
de l'exemple ci-dessus fait référence à l'exemple de méthode présenté dans Accéder aux caméras.
Prendre des photos
Une fois que vous avez créé une classe d'aperçu et une mise en page de vue pour l'afficher, vous pouvez commencer à capturer des images avec votre application. Dans le code de votre application, vous devez configurer des écouteurs pour que les commandes de votre interface utilisateur répondent à une action de l'utilisateur en prenant une photo.
Pour récupérer une image, utilisez la méthode Camera.takePicture()
. Cette méthode utilise trois paramètres qui reçoivent des données de la caméra.
Pour recevoir des données au format JPEG, vous devez implémenter une interface Camera.PictureCallback
pour recevoir les données d'image et les écrire dans un fichier. Le code suivant illustre une implémentation de base de l'interface Camera.PictureCallback
pour enregistrer une image reçue de la caméra.
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()); } } };
Déclenchez la capture d'une image en appelant la méthode Camera.takePicture()
. L'exemple de code suivant montre comment appeler cette méthode à partir d'un bouton 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); } } );
Remarque:Le membre mPicture
de l'exemple suivant fait référence à l'exemple de code ci-dessus.
Attention:N'oubliez pas de libérer l'objet Camera
en appelant Camera.release()
lorsque votre application a fini de l'utiliser. Pour savoir comment libérer la caméra, consultez Libérer la caméra.
Enregistrer des vidéos
La capture vidéo à l'aide du framework Android nécessite une gestion minutieuse de l'objet Camera
et une coordination avec la classe MediaRecorder
. Lorsque vous enregistrez une vidéo avec Camera
, vous devez gérer les appels Camera.lock()
et Camera.unlock()
pour autoriser MediaRecorder
à accéder au matériel de la caméra, en plus des appels Camera.open()
et Camera.release()
.
Remarque:À partir d'Android 4.0 (niveau d'API 14), les appels Camera.lock()
et Camera.unlock()
sont gérés automatiquement.
Contrairement à la prise de photos avec l'appareil photo d'un appareil, la capture vidéo nécessite un ordre d'appel très particulier. Vous devez suivre un ordre d'exécution spécifique pour préparer et enregistrer une vidéo avec votre application, comme indiqué ci-dessous.
- Ouvrir l'appareil photo : utilisez
Camera.open()
pour obtenir une instance de l'objet appareil photo. - Connect Preview (Aperçu de la connexion) : préparez un aperçu de l'image de l'appareil photo en direct en connectant un
SurfaceView
à l'appareil photo à l'aide deCamera.setPreviewDisplay()
. - Démarrer l'aperçu : appelez
Camera.startPreview()
pour commencer à afficher les images en direct de la caméra. - Démarrer l'enregistrement d'une vidéo : pour enregistrer une vidéo, vous devez suivre les étapes suivantes dans l'ordre :
- Déverrouiller l'appareil photo : déverrouillez l'appareil photo pour que
MediaRecorder
puisse l'utiliser en appelantCamera.unlock()
. - Configurer MediaRecorder : appelez les méthodes
MediaRecorder
suivantes dans cet ordre. Pour en savoir plus, consultez la documentation de référence deMediaRecorder
.setCamera()
: définissez l'appareil photo à utiliser pour la capture vidéo. Utilisez l'instance actuelle deCamera
de votre application.setAudioSource()
: définissez la source audio, utilisezMediaRecorder.AudioSource.CAMCORDER
.setVideoSource()
: définissez la source vidéo, utilisezMediaRecorder.VideoSource.CAMERA
.- Définissez le format et l'encodage de sortie vidéo. Pour Android 2.2 (niveau d'API 8) ou version ultérieure, utilisez la méthode
MediaRecorder.setProfile
et obtenez une instance de profil à l'aide deCamcorderProfile.get()
. Pour les versions d'Android antérieures à la version 2.2, vous devez définir le format de sortie vidéo et les paramètres d'encodage :setOutputFormat()
: définissez le format de sortie, spécifiez le paramètre par défaut ouMediaRecorder.OutputFormat.MPEG_4
.setAudioEncoder()
: définissez le type d'encodage du son, spécifiez le paramètre par défaut ouMediaRecorder.AudioEncoder.AMR_NB
.setVideoEncoder()
: définissez le type d'encodage vidéo, spécifiez le paramètre par défaut ouMediaRecorder.VideoEncoder.MPEG_4_SP
.
setOutputFile()
: définissez le fichier de sortie, utilisezgetOutputMediaFile(MEDIA_TYPE_VIDEO).toString()
à partir de l'exemple de méthode dans la section Enregistrer des fichiers multimédias.setPreviewDisplay()
: spécifiez l'élément de mise en page d'aperçuSurfaceView
pour votre application. Utilisez le même objet que celui que vous avez spécifié pour Connect Preview.
Attention:Vous devez appeler ces méthodes de configuration
MediaRecorder
dans cet ordre, sinon votre application rencontrera des erreurs et l'enregistrement échouera. - Préparer MediaRecorder : préparez
MediaRecorder
avec les paramètres de configuration fournis en appelantMediaRecorder.prepare()
. - Démarrer MediaRecorder : démarrez l'enregistrement vidéo en appelant
MediaRecorder.start()
.
- Déverrouiller l'appareil photo : déverrouillez l'appareil photo pour que
- Arrêter l'enregistrement vidéo : appelez les méthodes suivantes dans l'ordre pour effectuer un enregistrement vidéo :
- Arrêter MediaRecorder : arrêtez l'enregistrement vidéo en appelant
MediaRecorder.stop()
. - Réinitialiser MediaRecorder : vous pouvez également supprimer les paramètres de configuration de l'enregistreur en appelant
MediaRecorder.reset()
. - Libérer MediaRecorder : libérez l'
MediaRecorder
en appelantMediaRecorder.release()
. - Verrouiller la caméra : verrouillez la caméra pour que les futures sessions
MediaRecorder
puissent l'utiliser en appelantCamera.lock()
. À partir d'Android 4.0 (niveau d'API 14), cet appel n'est pas obligatoire, sauf si l'appelMediaRecorder.prepare()
échoue.
- Arrêter MediaRecorder : arrêtez l'enregistrement vidéo en appelant
- Arrêter l'aperçu : lorsque votre activité a fini d'utiliser l'appareil photo, arrêtez l'aperçu à l'aide de
Camera.stopPreview()
. - Libérer l'appareil photo : libérez l'appareil photo afin que d'autres applications puissent l'utiliser en appelant
Camera.release()
.
Remarque:Vous pouvez utiliser MediaRecorder
sans créer d'abord un aperçu de l'appareil photo et ignorer les premières étapes de ce processus. Toutefois, comme les utilisateurs préfèrent généralement voir un aperçu avant de commencer un enregistrement, ce processus n'est pas abordé ici.
Remarque:Si votre application est généralement utilisée pour enregistrer des vidéos, définissez setRecordingHint(boolean)
sur true
avant de démarrer l'aperçu. Ce paramètre peut vous aider à réduire le temps nécessaire pour démarrer l'enregistrement.
Configurer MediaRecorder
Lorsque vous utilisez la classe MediaRecorder
pour enregistrer une vidéo, vous devez effectuer les étapes de configuration dans un ordre spécifique, puis appeler la méthode MediaRecorder.prepare()
pour vérifier et implémenter la configuration. L'exemple de code suivant montre comment configurer et préparer correctement la classe MediaRecorder
pour l'enregistrement vidéo.
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; }
Avant Android 2.2 (niveau d'API 8), vous devez définir directement les paramètres de format de sortie et de format d'encodage, au lieu d'utiliser CamcorderProfile
. Cette approche est illustrée dans le code suivant:
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);
Les paramètres d'enregistrement vidéo suivants pour MediaRecorder
sont définis par défaut. Toutefois, vous pouvez les ajuster pour votre application:
setVideoEncodingBitRate()
setVideoSize()
setVideoFrameRate()
setAudioEncodingBitRate()
setAudioChannels()
setAudioSamplingRate()
Démarrer et arrêter MediaRecorder
Lorsque vous démarrez et arrêtez l'enregistrement vidéo à l'aide de la classe MediaRecorder
, vous devez suivre un ordre spécifique, comme indiqué ci-dessous.
- Déverrouiller l'appareil photo avec
Camera.unlock()
- Configurez
MediaRecorder
comme indiqué dans l'exemple de code ci-dessus. - Démarrer l'enregistrement à l'aide de
MediaRecorder.start()
- Enregistrer la vidéo
- Arrêter l'enregistrement à l'aide de
MediaRecorder.stop()
- Libérer l'enregistreur multimédia avec
MediaRecorder.release()
- Verrouiller la caméra à l'aide de
Camera.lock()
L'exemple de code suivant montre comment connecter un bouton pour démarrer et arrêter correctement l'enregistrement vidéo à l'aide de l'appareil photo et de la classe MediaRecorder
.
Remarque:Lorsque vous arrêtez l'enregistrement vidéo, ne relâchez pas la caméra, sinon l'aperçu sera arrêté.
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 } } } } );
Remarque:Dans l'exemple ci-dessus, la méthode prepareVideoRecorder()
fait référence à l'exemple de code présenté dans la section Configuration de MediaRecorder. Cette méthode s'occupe de verrouiller la caméra, de configurer et de préparer l'instance MediaRecorder
.
Déplier la caméra
Les appareils photo sont une ressource partagée par les applications d'un appareil. Votre application peut utiliser la caméra après avoir obtenu une instance de Camera
. Vous devez être particulièrement attentif à libérer l'objet de la caméra lorsque votre application cesse de l'utiliser et dès que votre application est mise en pause (Activity.onPause()
). Si votre application ne libère pas correctement la caméra, toutes les tentatives ultérieures d'accès à la caméra, y compris celles de votre propre application, échoueront et peuvent entraîner l'arrêt de votre application ou d'autres applications.
Pour libérer une instance de l'objet Camera
, utilisez la méthode Camera.release()
, comme illustré dans l'exemple de code ci-dessous.
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; } } }
Attention:Si votre application ne libère pas correctement l'appareil photo, toutes les tentatives ultérieures d'accès à l'appareil photo, y compris celles de votre propre application, échoueront et peuvent entraîner l'arrêt de votre application ou d'autres applications.
Enregistrer des fichiers multimédias
Les fichiers multimédias créés par les utilisateurs, tels que les images et les vidéos, doivent être enregistrés dans le répertoire de stockage externe (carte SD) d'un appareil afin de préserver l'espace système et de permettre aux utilisateurs d'accéder à ces fichiers sans leur appareil. Il existe de nombreux emplacements de répertoires possibles pour enregistrer des fichiers multimédias sur un appareil. Toutefois, en tant que développeur, vous ne devez en considérer que deux:
Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_PICTURES
) : cette méthode renvoie l'emplacement standard, partagé et recommandé pour enregistrer des images et des vidéos. Ce répertoire est partagé (public), ce qui permet aux autres applications de découvrir, lire, modifier et supprimer facilement les fichiers enregistrés à cet emplacement. Si l'utilisateur désinstalle votre application, les fichiers multimédias enregistrés à cet emplacement ne seront pas supprimés. Pour éviter d'interférer avec les photos et vidéos existantes des utilisateurs, vous devez créer un sous-répertoire pour les fichiers multimédias de votre application dans ce répertoire, comme illustré dans l'exemple de code ci-dessous. Cette méthode est disponible dans Android 2.2 (niveau d'API 8). Pour les appels équivalents dans les versions d'API antérieures, consultez la section Enregistrer des fichiers partagés.Context.getExternalFilesDir
(Environment.DIRECTORY_PICTURES
) : cette méthode renvoie un emplacement standard pour enregistrer les images et les vidéos associées à votre application. Si votre application est désinstallée, tous les fichiers enregistrés à cet emplacement sont supprimés. La sécurité n'est pas appliquée aux fichiers situés dans cet emplacement, et d'autres applications peuvent les lire, les modifier et les supprimer.
L'exemple de code suivant montre comment créer un emplacement File
ou Uri
pour un fichier multimédia pouvant être utilisé lors de l'appel de la caméra d'un appareil avec un Intent
ou dans le cadre de la création d'une application d'appareil photo.
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; }
Remarque:Environment.getExternalStoragePublicDirectory()
est disponible dans Android 2.2 (niveau d'API 8) ou version ultérieure. Si vous ciblez des appareils équipés de versions antérieures d'Android, utilisez plutôt Environment.getExternalStorageDirectory()
. Pour en savoir plus, consultez Enregistrer des fichiers partagés.
Pour que l'URI prenne en charge les profils professionnels,
convertissez d'abord l'URI du fichier en URI de contenu. Ajoutez ensuite l'URI du contenu à EXTRA_OUTPUT
d'un Intent
.
Pour en savoir plus sur l'enregistrement de fichiers sur un appareil Android, consultez Stockage de données.
Fonctionnalités de l'appareil photo
Android est compatible avec un large éventail de fonctionnalités d'appareil photo que vous pouvez contrôler avec votre application d'appareil photo, comme le format d'image, le mode flash, les paramètres de mise au point et bien plus encore. Cette section liste les fonctionnalités courantes de l'appareil photo et explique brièvement comment les utiliser. La plupart des fonctionnalités de l'appareil photo peuvent être consultées et définies à l'aide de l'objet Camera.Parameters
. Toutefois, plusieurs fonctionnalités importantes nécessitent plus que de simples paramètres dans Camera.Parameters
. Ces fonctionnalités sont décrites dans les sections suivantes:
Pour obtenir des informations générales sur l'utilisation des fonctionnalités contrôlées via Camera.Parameters
, consultez la section Utiliser les fonctionnalités de l'appareil photo. Pour en savoir plus sur l'utilisation des fonctionnalités contrôlées via l'objet des paramètres de l'appareil photo, suivez les liens de la liste des fonctionnalités ci-dessous vers la documentation de référence de l'API.
Fonctionnalité | Niveau d'API | Description |
---|---|---|
Détection de visages | 14 | Identifiez les visages humains dans une photo et utilisez-les pour la mise au point, la mesure et la balance des blancs. |
Zones de mesure | 14 | Spécifiez une ou plusieurs zones d'une image pour calculer la balance des blancs. |
Domaines d'action | 14 | Définir une ou plusieurs zones d'une image à utiliser pour la mise au point |
White Balance Lock |
14 | Arrêter ou démarrer les ajustements automatiques de la balance des blancs |
Exposure Lock |
14 | Arrêter ou démarrer les ajustements automatiques de l'exposition |
Video Snapshot |
14 | Prendre une photo pendant l'enregistrement d'une vidéo (capture d'image) |
Vidéo en accéléré | 11 | Enregistrer des images avec des délais définis pour enregistrer une vidéo en accéléré |
Multiple Cameras |
9 | Prise en charge de plusieurs caméras sur un appareil, y compris de caméras avant et arrière |
Focus Distance |
9 | Indique les distances entre la caméra et les objets qui semblent être mis au point |
Zoom |
8 | Définir l'agrandissement de l'image |
Exposure
Compensation |
8 | Augmenter ou diminuer le niveau d'exposition à la lumière |
GPS Data |
5 | Inclure ou omettre des données de localisation géographique avec l'image |
White Balance |
5 | Définir le mode de balance des blancs, qui affecte les valeurs de couleur de l'image capturée |
Focus Mode |
5 | Définissez la mise au point de l'appareil photo sur un sujet (automatique, fixe, macro ou infini, par exemple). |
Scene Mode |
5 | Appliquer un mode prédéfini pour des types de situations photographiques spécifiques, comme la nuit, la plage, la neige ou les scènes éclairées par des bougies |
JPEG Quality |
5 | Définissez le niveau de compression d'une image JPEG, ce qui augmente ou diminue la qualité et la taille du fichier de sortie de l'image. |
Flash Mode |
5 | Activer ou désactiver le flash, ou utiliser le paramètre automatique |
Color Effects |
5 | Appliquez un effet de couleur à l'image capturée, comme le noir et blanc, le sépia ou le négatif. |
Anti-Banding |
5 | Réduit l'effet de bandes dans les dégradés de couleur dus à la compression JPEG |
Picture Format |
1 | Spécifier le format de fichier de l'image |
Picture Size |
1 | Spécifier les dimensions en pixels de l'image enregistrée |
Remarque:Ces fonctionnalités ne sont pas compatibles avec tous les appareils en raison de différences matérielles et d'implémentations logicielles. Pour savoir comment vérifier la disponibilité des fonctionnalités sur l'appareil sur lequel votre application s'exécute, consultez Vérifier la disponibilité des fonctionnalités.
Vérifier la disponibilité des fonctionnalités
La première chose à comprendre lorsque vous souhaitez utiliser les fonctionnalités de l'appareil photo sur des appareils Android est que toutes les fonctionnalités ne sont pas compatibles avec tous les appareils. De plus, les appareils compatibles avec une fonctionnalité particulière peuvent l'être à différents niveaux ou avec différentes options. Par conséquent, une partie de votre processus de décision lors du développement d'une application d'appareil photo consiste à déterminer les fonctionnalités d'appareil photo que vous souhaitez prendre en charge et à quel niveau. Après avoir pris cette décision, vous devez planifier d'inclure du code dans votre application d'appareil photo qui vérifie si le matériel de l'appareil est compatible avec ces fonctionnalités et échoue de manière élégante si une fonctionnalité n'est pas disponible.
Vous pouvez vérifier la disponibilité des fonctionnalités de l'appareil photo en obtenant une instance de l'objet de paramètres d'une caméra et en vérifiant les méthodes appropriées. L'exemple de code suivant montre comment obtenir un objet Camera.Parameters
et vérifier si la caméra est compatible avec la fonctionnalité de mise au point automatique:
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 }
Vous pouvez utiliser la technique indiquée ci-dessus pour la plupart des fonctionnalités de l'appareil photo. L'objet Camera.Parameters
fournit une méthode getSupported...()
, is...Supported()
ou getMax...()
pour déterminer si (et dans quelle mesure) une fonctionnalité est prise en charge.
Si votre application nécessite certaines fonctionnalités de l'appareil photo pour fonctionner correctement, vous pouvez les exiger en ajoutant des éléments à votre fichier manifeste d'application. Lorsque vous déclarez l'utilisation de fonctionnalités d'appareil photo spécifiques, telles que le flash et la mise au point automatique, Google Play empêche l'installation de votre application sur les appareils qui ne sont pas compatibles avec ces fonctionnalités. Pour obtenir la liste des fonctionnalités de l'appareil photo pouvant être déclarées dans le fichier manifeste de votre application, consultez la documentation de référence sur les fonctionnalités du fichier manifeste.
Utiliser les fonctionnalités de l'appareil photo
La plupart des fonctionnalités de l'appareil photo sont activées et contrôlées à l'aide d'un objet Camera.Parameters
. Pour obtenir cet objet, vous devez d'abord obtenir une instance de l'objet Camera
, appeler la méthode getParameters()
, modifier l'objet de paramètre renvoyé, puis le rétablir dans l'objet de la caméra, comme illustré dans l'exemple de code suivant:
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);
Cette technique fonctionne pour presque toutes les fonctionnalités de l'appareil photo, et la plupart des paramètres peuvent être modifiés à tout moment après avoir obtenu une instance de l'objet Camera
. Les modifications apportées aux paramètres sont généralement visibles immédiatement par l'utilisateur dans l'aperçu de l'appareil photo de l'application.
Côté logiciel, les modifications de paramètres peuvent prendre plusieurs images pour prendre effet, car le matériel de la caméra traite les nouvelles instructions, puis envoie les données d'image mises à jour.
Important:Certaines fonctionnalités de l'appareil photo ne peuvent pas être modifiées à volonté. Plus précisément, pour modifier la taille ou l'orientation de l'aperçu de l'appareil photo, vous devez d'abord arrêter l'aperçu, modifier sa taille, puis le relancer. À partir d'Android 4.0 (niveau d'API 14), l'orientation de l'aperçu peut être modifiée sans avoir à redémarrer l'aperçu.
D'autres fonctionnalités de l'appareil photo nécessitent plus de code pour être implémentées, par exemple:
- Zones de mesure et de mise au point
- Détection de visages
- Vidéo en accéléré
Les sections suivantes présentent brièvement comment implémenter ces fonctionnalités.
Zones de mesure et de mise au point
Dans certains scénarios photographiques, la mise au point et la mesure de la lumière automatiques peuvent ne pas produire les résultats souhaités. À partir d'Android 4.0 (niveau d'API 14), votre application d'appareil photo peut fournir des commandes supplémentaires pour permettre à votre application ou aux utilisateurs de spécifier des zones d'une image à utiliser pour déterminer les paramètres de mise au point ou de luminosité, et de transmettre ces valeurs au matériel de l'appareil photo pour les utiliser lors de la capture d'images ou de vidéos.
Les zones de mesure et de mise au point fonctionnent de manière très similaire aux autres fonctionnalités de l'appareil photo, car vous les contrôlez via des méthodes de l'objet Camera.Parameters
. Le code suivant montre comment définir deux zones de mesure de la lumière pour une instance de 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'objet Camera.Area
contient deux paramètres de données: un objet Rect
permettant de spécifier une zone dans le champ de vision de la caméra et une valeur de pondération, qui indique à la caméra le niveau d'importance à accorder à cette zone dans le calcul de la mesure de la lumière ou de la mise au point.
Le champ Rect
d'un objet Camera.Area
décrit une forme rectangulaire mappée sur une grille de 2 000 x 2 000 unités. Les coordonnées -1 000, -1 000 représentent l'angle supérieur gauche de l'image de la caméra, et les coordonnées 1 000, 1 000 représentent l'angle inférieur droit de l'image de la caméra, comme illustré dans l'illustration ci-dessous.
Les limites de ce système de coordonnées correspondent toujours au bord extérieur de l'image visible dans l'aperçu de l'appareil photo et ne se rétrécissent ni ne se dilatent avec le niveau de zoom. De même, la rotation de l'aperçu de l'image à l'aide de Camera.setDisplayOrientation()
ne remappe pas le système de coordonnées.
Détection de visages
Pour les photos qui incluent des personnes, les visages sont généralement la partie la plus importante de l'image et doivent être utilisés pour déterminer à la fois la mise au point et la balance des blancs lors de la capture d'une image. Le framework Android 4.0 (niveau d'API 14) fournit des API permettant d'identifier les visages et de calculer les paramètres d'image à l'aide de la technologie de reconnaissance faciale.
Remarque:Lorsque la fonctionnalité de détection des visages est en cours d'exécution, setWhiteBalance(String)
, setFocusAreas(List<Camera.Area>)
et setMeteringAreas(List<Camera.Area>)
n'ont aucun effet.
Pour utiliser la fonctionnalité de détection des visages dans votre application d'appareil photo, vous devez suivre quelques étapes générales:
- Vérifier que la détection des visages est prise en charge sur l'appareil
- Créer un écouteur de détection des visages
- Ajouter l'écouteur de détection de visage à votre objet appareil photo
- Démarrer la détection de visage après l'aperçu (et après chaque redémarrage de l'aperçu)
La fonctionnalité de détection du visage n'est pas disponible sur tous les appareils. Pour vérifier que cette fonctionnalité est prise en charge, appelez getMaxNumDetectedFaces()
. Un exemple de cette vérification est illustré dans l'exemple de méthode startFaceDetection()
ci-dessous.
Pour être avertie et répondre à la détection d'un visage, votre application d'appareil photo doit définir un écouteur pour les événements de détection de visage. Pour ce faire, vous devez créer une classe d'écouteur qui implémente l'interface Camera.FaceDetectionListener
, comme illustré dans l'exemple de code ci-dessous.
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() ); } } }
Après avoir créé cette classe, vous la définissez dans l'objet Camera
de votre application, comme illustré dans l'exemple de code ci-dessous:
Kotlin
camera?.setFaceDetectionListener(MyFaceDetectionListener())
Java
camera.setFaceDetectionListener(new MyFaceDetectionListener());
Votre application doit démarrer la fonction de détection des visages chaque fois que vous démarrez (ou redémarrez) l'aperçu de l'appareil photo. Créez une méthode pour démarrer la détection de visage afin de pouvoir l'appeler si nécessaire, comme indiqué dans l'exemple de code ci-dessous.
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(); } }
Vous devez démarrer la détection des visages à chaque fois que vous démarrez (ou redémarrez) l'aperçu de l'appareil photo. Si vous utilisez la classe Preview illustrée dans Créer une classe Preview, ajoutez votre méthode startFaceDetection()
aux méthodes surfaceCreated()
et surfaceChanged()
de votre classe Preview, comme illustré dans l'exemple de code ci-dessous.
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()); } }
Remarque:N'oubliez pas d'appeler cette méthode après avoir appelé startPreview()
. N'essayez pas de démarrer la détection de visage dans la méthode onCreate()
de l'activité principale de votre application d'appareil photo, car l'aperçu n'est pas disponible à ce stade de l'exécution de votre application.
Vidéo en accéléré
Les vidéos accélérées permettent aux utilisateurs de créer des extraits vidéo qui combinent des images prises à quelques secondes ou minutes d'intervalle. Cette fonctionnalité utilise MediaRecorder
pour enregistrer les images d'une séquence accélérée.
Pour enregistrer une vidéo en accéléré avec MediaRecorder
, vous devez configurer l'objet enregistreur comme si vous enregistriez une vidéo normale, en définissant le nombre de frames capturés par seconde sur un nombre faible et en utilisant l'un des paramètres de qualité de l'accéléré, comme illustré dans l'exemple de code ci-dessous.
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
Ces paramètres doivent être définis dans le cadre d'une procédure de configuration plus vaste pour MediaRecorder
. Pour obtenir un exemple de code de configuration complet, consultez la section Configurer MediaRecorder. Une fois la configuration terminée, démarrez l'enregistrement vidéo comme si vous enregistriez un extrait vidéo normal. Pour en savoir plus sur la configuration et l'exécution de MediaRecorder
, consultez Enregistrer des vidéos.
Les exemples Camera2Video et HdrViewfinder illustrent davantage l'utilisation des API abordées sur cette page.
Champs de l'appareil photo nécessitant une autorisation
Les applications exécutées sur Android 10 (niveau d'API 29) ou version ultérieure doivent disposer de l'autorisation CAMERA
pour accéder aux valeurs des champs suivants renvoyés par la méthode 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
Exemples de code supplémentaires
Pour télécharger des applications exemple, consultez l'exemple Camera2Basic et l'application exemple officielle de CameraX.