Observação: esta página se refere ao pacote Camera2. A menos que seu app exija recursos específicos de baixo nível do Camera2, recomendamos o uso do CameraX. CameraX e Camera2 oferecem suporte ao Android 5.0 (nível 21 da API) e versões mais recentes.
Muitos dispositivos Android modernos têm duas ou mais câmeras na frente, atrás ou em ambos os lados. Cada lente pode ter recursos exclusivos, como captura em sequência, controle manual ou rastreamento de movimento. Um app para depositar cheques pode usar apenas a primeira câmera traseira, enquanto um app de rede social pode usar uma câmera frontal por padrão, mas dar aos usuários a opção de alternar entre todas as lentes disponíveis. Ele também pode lembrar as escolhas deles.
Nesta página, mostramos como listar as lentes da câmera e os recursos delas para que você possa decidir qual lente usar em uma determinada situação no app. O snippet de código a seguir recupera uma lista de todas as câmeras e as itera:
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) } // ... }
A variável cameraLensFacing descreve a direção para onde a câmera está voltada
em relação à tela do dispositivo e tem um dos seguintes valores:
CameraMetadata.LENS_FACING_FRONTCameraMetadata.LENS_FACING_BACKCameraMetadata.LENS_FACING_EXTERNAL
Para mais informações sobre a configuração de direção da lente, consulte
CameraCharacteristics.LENS_FACING.
A variável cameraCapabilities do exemplo de código anterior contém
informações sobre vários recursos, incluindo se a câmera é
capaz de produzir frames padrão como saída (em vez de, por exemplo, apenas
dados do sensor de profundidade). Você pode procurar se
CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE
é um dos recursos listados da câmera, que é armazenado como uma flag em
isBackwardCompatible.
Escolha padrões sensatos
No app, é provável que você queira abrir uma câmera específica por padrão (se estiver disponível). Por exemplo, um app de selfie provavelmente abre a câmera frontal, enquanto um app de realidade aumentada pode começar com a câmera traseira. A função a seguir retorna a primeira câmera que está voltada para uma determinada direção:
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 } }
Ativar a troca de câmeras
Muitos apps de câmera oferecem aos usuários a opção de alternar entre câmeras:
Muitos dispositivos têm várias câmeras voltadas para a mesma direção. Alguns até têm câmeras USB externas. Para fornecer aos usuários uma interface que permita alternar entre câmeras com diferentes direções, escolha a primeira câmera disponível para cada configuração possível de direção da lente.
Embora não haja uma lógica universal para selecionar a próxima câmera, o código abaixo funciona para a maioria dos casos de uso:
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) } }
Esse código funciona para um grande conjunto de dispositivos com muitas configurações
diferentes. Para mais informações sobre como lidar com casos extremos, consulte
CameraMetadata.REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA.
Criar apps compatíveis
Para apps que ainda usam a API Camera descontinuada, o número de câmeras que
Camera.getNumberOfCameras() retorna depende da implementação
do OEM. Se houver uma câmera lógica múltipla no sistema, para manter
a compatibilidade com versões anteriores do app, esse método vai expor apenas uma câmera para cada
câmera lógica e grupo de câmeras físicas subjacentes. Use a API Camera2 para ver
todas as câmeras.
Para mais informações sobre orientações de câmera, consulte
Camera.CameraInfo.orientation.
Em geral, use a API Camera.getCameraInfo() para consultar todos os
orientations de câmera e exponha apenas uma câmera para
cada orientação disponível aos usuários que estão alternando entre câmeras.
Compatibilidade com todos os tipos de dispositivo
Não presuma que o app sempre será executado em um dispositivo portátil com uma ou duas câmeras. Em vez disso, escolha as câmeras mais adequadas para o app. Se você não precisar de uma câmera específica, selecione a primeira câmera que estiver voltada para a direção escolhida. Se a câmera voltada para uma determinada direção não estiver disponível, considere se o usuário pode concluir a jornada com outra câmera. Não restrinja a disponibilidade do app em determinados dispositivos com base no hardware da câmera. Se uma câmera externa estiver conectada, é provável que o usuário prefira que ela seja a padrão.