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:
- Clases internas: Android vs Java
- Error de aplicación debido a NullPointerException
- ¿Cómo enviar una respuesta de PHP a una aplicación móvil de Android / Java?
- Cómo obtener los elementos seleccionados de un elemento de opción múltiple en un Alert.Builder?
- Excepción Java del puntero nulo
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); } };
- Privilegios elevados en la aplicación para Android
- Ningún dispositivo de destino encontrado android studio 2.1.1
- . \ key.p12: abierto fallido: ENOENT (No hay tal archivo o directorio)
- Comportamiento extraño con selectAllOnFocus cuando EditText está en ListView
- Error: Error de ejecución de la tarea ': app: dexDebug'. Com.android.ide.common.process.ProcessException
- Características del lenguaje Java 7 con Android
- Cómo ordenar una vista de lista en orden alfabético
- Encadenar dos observables de adaptación con RxJava
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.
- ¿Qué método se llama cuando cierro una aplicación?
- Firebase JobDispatcher vs Evernote Android Trabajo – ¿cómo comparar estos dos?