Android: 如何检测相机是否闪光
Android: how to detect if camera flashed
我正在使用 Android 的 Camera2 API,目前我希望相机在准备闪光时执行特定操作。
构建 CaptureRequest 时,以下行:
captureRequest.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
允许相机在低光照条件下闪光。但是,我不知道如何检测相机是否准备好闪光。似乎关于此特定操作的在线文献很少。
我在处理相机 CaptureCallback
中的部分结果时尝试检查 FLASH_STATE
是否在 FLASH_STATE_READY
中,但似乎密钥不可用 - 它一直返回 null
。也许我没有检查正确的地方?
相机的 CaptureCallback
,如下所示(基于 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);
}
};
在 documentation 中,您可以阅读以下针对 FLASH_STATE
键的语句:
Optional - This value may be null on some devices.
基本上,即使您使用的是 Lollipop 设备,您也不能确定支持 Camera2 APi 的所有功能。功能有限的设备称为"limited devices"。
有关详细信息,请查看 this 页面。这描述得很好。
编辑:
要回答基本上是错误的评论:
文档说:
When the camera device doesn't have flash unit (i.e. android.flash.info.available == false), this state will always be UNAVAILABLE. Other states indicate the current flash status.
因此,如果设备上没有闪光灯,FLASH_STATE
也会存在,并且会 return UNAVAILABLE
。
文档几乎涵盖了您需要了解的所有内容。最重要的事实是,它取决于 hardware-level/hardware 模式。
总结一下
对于 LEGACY 设备
它将return以下
- 如果 AE 模式设置为 ON_ALWAYS_FLASH
- 如果闪光灯模式设置为 TORCH,则为 FIRED
- 如果相机没有闪光灯则不可用。
当设备至少为LEVEL_LIMITED:
这些值是可能的,但不能保证它们都有效:
- 不可用
- 正在充电
- 准备就绪
- 已解雇
- 部分
问题
您正在尝试检测您的应用拍摄的照片是否使用闪光灯。
解决方案
您可以在使用相机时使用Camera.Parameters
检查闪光灯的状态,无论闪光灯是自动、开启还是关闭。
代码
您可以使用以下代码示例来检查相机的闪光灯状态。
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
}
相机 API 未弃用,按照 Camera2 API 中的代码片段检查闪光灯是否可用,
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
}
目前没有办法确定闪光灯是否会闪光 - 决定是由相机设备在全分辨率捕捉之前的最后一刻做出的。一旦全分辨率捕获的最终捕获结果可用,它 flash state should be FIRED if the flash did fire, but you'll get this after the fact. Make sure you wait for the total capture result from onCaptureCompleted 检查此字段,而不是来自 onCaptureProgressed 的部分;部分结果可能缺少多个字段。
就是说,如果 AE state field before starting the precapture sequence is FLASH_REQUIRED,如果 AE 模式允许闪光,则很可能会触发闪光灯 (AE_MODE_ON_AUTO_FLASH / ALWAYS_FLASH / AUTO_FLASH_REDEYE ).这不是 100% 的保证,因为场景可能会在预捕捉序列开始(将执行预捕捉闪光以估计必要的闪光功率)和实际的最终图片捕捉之间的几帧中发生变化。但我怀疑 95% 的情况下这将是最终结果。
我正在使用 Android 的 Camera2 API,目前我希望相机在准备闪光时执行特定操作。
构建 CaptureRequest 时,以下行:
captureRequest.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
允许相机在低光照条件下闪光。但是,我不知道如何检测相机是否准备好闪光。似乎关于此特定操作的在线文献很少。
我在处理相机 CaptureCallback
中的部分结果时尝试检查 FLASH_STATE
是否在 FLASH_STATE_READY
中,但似乎密钥不可用 - 它一直返回 null
。也许我没有检查正确的地方?
相机的 CaptureCallback
,如下所示(基于 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);
}
};
在 documentation 中,您可以阅读以下针对 FLASH_STATE
键的语句:
Optional - This value may be null on some devices.
基本上,即使您使用的是 Lollipop 设备,您也不能确定支持 Camera2 APi 的所有功能。功能有限的设备称为"limited devices"。
有关详细信息,请查看 this 页面。这描述得很好。
编辑: 要回答基本上是错误的评论: 文档说:
When the camera device doesn't have flash unit (i.e. android.flash.info.available == false), this state will always be UNAVAILABLE. Other states indicate the current flash status.
因此,如果设备上没有闪光灯,FLASH_STATE
也会存在,并且会 return UNAVAILABLE
。
文档几乎涵盖了您需要了解的所有内容。最重要的事实是,它取决于 hardware-level/hardware 模式。
总结一下
对于 LEGACY 设备
它将return以下
- 如果 AE 模式设置为 ON_ALWAYS_FLASH
- 如果闪光灯模式设置为 TORCH,则为 FIRED
- 如果相机没有闪光灯则不可用。
当设备至少为LEVEL_LIMITED:
这些值是可能的,但不能保证它们都有效:
- 不可用
- 正在充电
- 准备就绪
- 已解雇
- 部分
问题
您正在尝试检测您的应用拍摄的照片是否使用闪光灯。
解决方案
您可以在使用相机时使用Camera.Parameters
检查闪光灯的状态,无论闪光灯是自动、开启还是关闭。
代码
您可以使用以下代码示例来检查相机的闪光灯状态。
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
}
相机 API 未弃用,按照 Camera2 API 中的代码片段检查闪光灯是否可用,
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
}
目前没有办法确定闪光灯是否会闪光 - 决定是由相机设备在全分辨率捕捉之前的最后一刻做出的。一旦全分辨率捕获的最终捕获结果可用,它 flash state should be FIRED if the flash did fire, but you'll get this after the fact. Make sure you wait for the total capture result from onCaptureCompleted 检查此字段,而不是来自 onCaptureProgressed 的部分;部分结果可能缺少多个字段。
就是说,如果 AE state field before starting the precapture sequence is FLASH_REQUIRED,如果 AE 模式允许闪光,则很可能会触发闪光灯 (AE_MODE_ON_AUTO_FLASH / ALWAYS_FLASH / AUTO_FLASH_REDEYE ).这不是 100% 的保证,因为场景可能会在预捕捉序列开始(将执行预捕捉闪光以估计必要的闪光功率)和实际的最终图片捕捉之间的几帧中发生变化。但我怀疑 95% 的情况下这将是最终结果。