Android: cómo detectar si la cámara parpadea

Estoy usando la API de Camera2 de Android y actualmente quiero que la cámara realice una determinada acción cada vez que se prepara para destellar.

Al crear el CaptureRequest, la línea siguiente:

captureRequest.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); 

Permite que la cámara parpadee en condiciones de poca iluminación. Sin embargo, estoy en una pérdida en cuanto a cómo puedo detectar si la cámara está preparada para flash o no. Parece que la literatura en línea sobre esta acción en particular es bastante escasa.

He intentado comprobar si FLASH_STATE está en FLASH_STATE_READY mientras que procesaba un FLASH_STATE_READY en FLASH_STATE_READY de la cámara, pero parece que la llave no estaba disponible – guardó el volver null . Tal vez no estoy comprobando en el lugar correcto?

El CaptureCallback la cámara, que se muestra a continuación (basado en el Camera2Basic código de Google Camera2Basic ):

 private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() { private void process(CaptureResult result) { switch(mState) { case STATE_PREVIEW: break; case STATE_WAITING_LOCK: // checking if result.get(CaptureResult.FLASH_STATE) == // CaptureResult.FLASH_READY over here didn't work because // null was returned int afState = result.get(CaptureResult.CONTROL_AF_STATE); if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) { Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) { mState = STATE_WAITING_NON_PRECAPTURE; captureStillPicture(); } else { runPrecaptureSequence(); } } break; case STATE_WAITING_PRECAPTURE: Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE || aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) { mState = STATE_WAITING_NON_PRECAPTURE; } break; case STATE_WAITING_NON_PRECAPTURE: Integer aeState1 = result.get(CaptureResult.CONTROL_AE_STATE); if (aeState1 == null || aeState1 != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) { mState = STATE_PICTURE_TAKEN; captureStillPicture(); } break; } } @Override public void onCaptureProgressed(CameraCaptureSession session, CaptureRequest request, CaptureResult partialResult) { super.onCaptureProgressed(session, request, partialResult); process(partialResult); } @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); process(result); } }; 

En la documentación puede leer la siguiente instrucción para la clave FLASH_STATE :

Opcional : este valor puede ser nulo en algunos dispositivos.

Básicamente, incluso si está utilizando un dispositivo Lollipop, no puede estar seguro de que todas las funciones del AP2 de Camera2 son compatibles. Los dispositivos con funciones limitadas se denominan "dispositivos limitados".

Para más información, eche un vistazo a esta página. Esto lo describe bastante bien.

EDIT: Para responder al comentario que está básicamente equivocado: Las documentaciones dicen:

Cuando el dispositivo de la cámara no tiene una unidad de flash (es decir, android.flash.info.available == false), este estado siempre será NO DISPONIBLE. Otros estados indican el estado actual del flash.

Así que si no hay flash en el dispositivo FLASH_STATE también está presente y volverá UNAVAILABLE .

La documentación dice casi todo lo que tienes que saber. El hecho más importante es que depende del modo hardware / hardware.


Vamos a resumirlo

Para los dispositivos LEGACY

Devolverá lo siguiente

  • FUEGO si el modo AE está ajustado a ON_ALWAYS_FLASH
  • FUEGO si el modo de flash está ajustado a TORCH
  • NO DISPONIBLE si la cámara no tiene flash.

Cuando el dispositivo es al menos LEVEL_LIMITED:

Estos valores son posibles, pero no hay garantía de que todos funcionen:

  • INDISPONIBLE
  • Cargando
  • LISTO
  • DESPEDIDO
  • PARCIAL

Problema

Está intentando detectar si la imagen tomada por su aplicación utiliza flash o no.

Solución

Puede utilizar Camera.Parameters para comprobar el estado del flash mientras utiliza la cámara si el flash es AUTO, ON u OFF.

Código

Puede utilizar el siguiente ejemplo de código para comprobar el estado de flash de la cámara.

 Camera.Parameters p = mCamera.getParameters(); if(p.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_ON)) { //DO STUFF } else if(p.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_OFF)) { //DO STUFF } else if(p.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_TORCH)) { //DO STUFF } else if(p.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_AUTO)) { //DO STUFF } else { //DO STUFF } 

La API de la cámara no está obsoleta, El siguiente fragmento de código de la API de la Cámara2 para comprobar que Flash está disponible o no,

 CameraManager mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE); //here to judge if flash is available CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics("0"); boolean flashAvailable = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE); if (flashAvailable) { mCameraManager.openCamera("0", new MyCameraDeviceStateCallback(), null); } else { //todo: throw Exception } 

No hay ninguna manera actual de saber con certeza si el flash se disparará – la decisión es tomada por el dispositivo de la cámara en el último momento antes de la captura de resolución completa. Una vez que el resultado de la captura final para la captura de resolución completa está disponible, su estado de destello debe ser disparado si el flash se disparó, pero obtendrá esto después del hecho. Asegúrese de esperar el resultado de captura total de onCaptureCompleted para comprobar este campo, no un parcial de onCaptureProgressed; Los resultados parciales pueden faltar varios campos.

Dicho esto, si el campo de estado AE antes de iniciar la secuencia de precaptura es FLASH_REQUIRED , es muy probable que el flash se disparará si el modo AE permite flash (AE_MODE_ON_AUTO_FLASH / ALWAYS_FLASH / AUTO_FLASH_REDEYE). No es una garantía del 100%, ya que la escena puede cambiar en los pocos fotogramas entre el inicio de la secuencia de precaptura (que ejecutará un flash de precaptura para estimar la potencia de flash necesaria) y la captura de imagen final real. Pero sospecho que el 95% del tiempo será el resultado final.

  • Programas funcionan bien con LibGDX -desktop pero no LibGDX - Android?
  • el enlace de datos; la etiqueta de la vista no es correcta, Android
  • Proguard eliminando anotaciones en la aplicación de Android
  • Calcular la distancia de gestos en Android
  • Fragmentos y notificaciones: Objetivo diferentes actividades de notificación; Dependiendo de la configuración de la pantalla
  • Mapbox no se procesa en la presentación XML Vista
  • Crash Una aplicación que utiliza excepción en Android
  • Leer y escribir datos con GSON
  • NullPointerException Causado por getActionBar ()
  • El dedo de desplazamiento rápido desaparece mientras se desplaza AlphabetIndexer
  • Timer.scheduleAtFixedRate no se detiene cuando llamo cancelar
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.