Remarque : Cette page fait référence au package Camera2. À moins que votre application ne nécessite des fonctionnalités spécifiques de bas niveau de Camera2, nous vous recommandons d'utiliser CameraX. CameraX et Camera2 sont compatibles avec Android 5.0 (niveau d'API 21) ou version ultérieure.
De nombreux appareils Android modernes sont équipés de deux caméras ou plus à l'avant, à l'arrière ou des deux côtés de l'appareil. Chaque objectif peut avoir des capacités uniques, telles que la capture en rafale, le contrôle manuel ou le suivi du mouvement. Une application permettant de déposer des chèques peut n'utiliser que la première caméra arrière, tandis qu'une application de réseau social peut utiliser par défaut une caméra avant, mais permettre aux utilisateurs de basculer entre tous les objectifs disponibles. Il peut également mémoriser leurs choix.
Cette page explique comment lister les objectifs d'appareil photo et leurs fonctionnalités afin de pouvoir décider, dans votre application, quel objectif utiliser dans une situation donnée. L'extrait de code suivant récupère la liste de toutes les caméras et les parcourt :
try { val cameraIdList = cameraManager.cameraIdList // may be empty // iterate over available camera devices. for (cameraId in cameraIdList) { val characteristics = cameraManager.getCameraCharacteristics(cameraId) val cameraLensFacing = characteristics.get(CameraCharacteristics.LENS_FACING) val cameraCapabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) // check if the selected camera device supports basic features // ensures backward compatibility with the original Camera API. val isBackwardCompatible = cameraCapabilities?.contains( CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE ) ?: false // ... } } catch (e: CameraAccessException) { e.message?.let { Log.e(TAG, it) } // ... }
La variable cameraLensFacing décrit la direction vers laquelle l'appareil photo est orienté par rapport à l'écran de l'appareil. Elle peut prendre l'une des valeurs suivantes :
CameraMetadata.LENS_FACING_FRONTCameraMetadata.LENS_FACING_BACKCameraMetadata.LENS_FACING_EXTERNAL
Pour en savoir plus sur la configuration de l'orientation de l'objectif, consultez CameraCharacteristics.LENS_FACING.
La variable cameraCapabilities de l'exemple de code précédent contient des informations sur diverses fonctionnalités, y compris si la caméra est capable de produire des images standards en sortie (par opposition, par exemple, aux données de capteur de profondeur uniquement). Vous pouvez vérifier si CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE fait partie des fonctionnalités listées de la caméra, qui sont stockées sous forme d'indicateur dans isBackwardCompatible.
Choisir des valeurs par défaut judicieuses
Dans votre application, vous souhaiterez probablement ouvrir un appareil photo spécifique par défaut (s'il est disponible). Par exemple, une application de selfie ouvre probablement la caméra avant, tandis qu'une application de réalité augmentée peut démarrer avec la caméra arrière. La fonction suivante renvoie la première caméra orientée dans une direction donnée :
fun getFirstCameraIdFacing( cameraManager: CameraManager, facing: Int = CameraMetadata.LENS_FACING_BACK ): String? { try { // Get list of all compatible cameras. val cameraIds = cameraManager.cameraIdList.filter { val characteristics = cameraManager.getCameraCharacteristics(it) val capabilities = characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES) capabilities?.contains( CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE ) ?: false } // Iterate over the list of cameras and return the first one matching desired // lens-facing configuration. cameraIds.forEach { val characteristics = cameraManager.getCameraCharacteristics(it) if (characteristics.get(CameraCharacteristics.LENS_FACING) == facing) { return it } } // If no camera matched desired orientation, return the first one from the list. return cameraIds.firstOrNull() } catch (e: CameraAccessException) { e.message?.let { Log.e(TAG, it) } return null } }
Activer le changement de caméra
De nombreuses applications d'appareil photo permettent aux utilisateurs de basculer entre les caméras :
De nombreux appareils sont équipés de plusieurs caméras orientées dans la même direction. Certains sont même équipés de caméras USB externes. Pour fournir aux utilisateurs une UI leur permettant de basculer entre différentes caméras, choisissez la première caméra disponible pour chaque configuration d'orientation de l'objectif possible.
Bien qu'il n'existe pas de logique universelle pour sélectionner la caméra suivante, le code suivant fonctionne dans la plupart des cas d'utilisation :
fun filterCompatibleCameras( cameraIds: Array<String>, cameraManager: CameraManager ): List<String> { return cameraIds.filter { val characteristics = cameraManager.getCameraCharacteristics(it) characteristics.get(CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES)?.contains( CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE ) ?: false } } fun filterCameraIdsFacing( cameraIds: List<String>, cameraManager: CameraManager, facing: Int ): List<String> { return cameraIds.filter { val characteristics = cameraManager.getCameraCharacteristics(it) characteristics.get(CameraCharacteristics.LENS_FACING) == facing } } fun getNextCameraId(cameraManager: CameraManager, currCameraId: String? = null): String? { // Get all front, back and external cameras in 3 separate lists. val cameraIds = filterCompatibleCameras(cameraManager.cameraIdList, cameraManager) val backCameras = filterCameraIdsFacing( cameraIds, cameraManager, CameraMetadata.LENS_FACING_BACK ) val frontCameras = filterCameraIdsFacing( cameraIds, cameraManager, CameraMetadata.LENS_FACING_FRONT ) val externalCameras = filterCameraIdsFacing( cameraIds, cameraManager, CameraMetadata.LENS_FACING_EXTERNAL ) // The recommended order of iteration is: all external, first back, first front. val allCameras = ( externalCameras + listOf( backCameras.firstOrNull(), frontCameras.firstOrNull() ) ).filterNotNull() // Get the index of the currently selected camera in the list. val cameraIndex = allCameras.indexOf(currCameraId) // The selected camera may not be in the list, for example it could be an // external camera that has been removed by the user. return if (cameraIndex == -1) { // Return the first camera from the list. allCameras.getOrNull(0) } else { // Return the next camera from the list, wrap around if necessary. allCameras.getOrNull((cameraIndex + 1) % allCameras.size) } }
Ce code fonctionne pour un grand nombre d'appareils avec de nombreuses configurations différentes. Pour en savoir plus sur la prise en compte des cas particuliers, consultez CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA.
Créer des applications compatibles
Pour les applications qui utilisent encore l'API Camera obsolète, le nombre de caméras renvoyé par Camera.getNumberOfCameras() dépend de l'implémentation de l'OEM. S'il existe un multicaméra logique dans le système, pour maintenir la rétrocompatibilité de l'application, cette méthode n'expose qu'une seule caméra pour chaque caméra logique et groupe de caméras physiques sous-jacent. Utilisez l'API Camera2 pour voir toutes les caméras.
Pour en savoir plus sur les orientations de la caméra, consultez Camera.CameraInfo.orientation.
En général, utilisez l'API Camera.getCameraInfo() pour interroger tous les orientation de la caméra et n'exposez qu'une seule caméra pour chaque orientation disponible aux utilisateurs qui passent d'une caméra à l'autre.
S'adapter à tous les types d'appareils
Ne partez pas du principe que votre application s'exécute toujours sur un appareil portable équipé d'une ou deux caméras. Choisissez plutôt les caméras les plus appropriées pour l'application. Si vous n'avez pas besoin d'une caméra spécifique, sélectionnez la première caméra orientée dans la direction choisie. Si la caméra orientée dans une certaine direction n'est pas disponible, déterminez si l'utilisateur peut effectuer son parcours avec une autre caméra. Ne limitez pas la disponibilité de votre application sur certains appareils en fonction du matériel de l'appareil photo. Si une caméra externe est connectée, l'utilisateur préfère probablement l'utiliser par défaut.