安卓:如何检测相机是否闪光

6

我正在使用Android的Camera2 API,目前我希望在相机准备闪光灯时执行某个特定操作。

在构建CaptureRequest时,下面这行代码:

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

允许相机在低光条件下闪光的功能。然而,我不知道如何检测相机是否准备好闪光。在线上关于这个特定操作的文献似乎非常稀少。
我尝试在相机的CaptureCallback中处理partialresult时检查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);
    }
};

请查看以下关于Camera2 API中Flash的类: https://dev59.com/UV4c5IYBdhLWcg3w59qQ#31289731 - Umang Kothari
要读取闪存状态,请等待完整的捕获结果,然后在那里检查闪存状态;部分结果可能尚未具备所有字段(通常它们具有完成AF等必要字段以提高速度的字段)。 - Eddy Talvala
4个回答

4
文档中,您可以阅读关于FLASH_STATE键的以下声明:

可选 - 在某些设备上此值可能为null。

基本上,即使您使用的是Lollipop设备,也不能确定相机2 API的所有功能都受支持。具有有限功能的设备称为“有限设备”。
要了解更多信息,请查看页面。这描述得非常清楚。 编辑: 回答错误的评论: 文档说:

当相机设备没有闪光灯单元(即android.flash.info.available == false)时,此状态将始终为UNAVAILABLE。其他状态指示当前闪光灯状态。

因此,如果设备上没有闪光灯,则FLASH_STATE也存在,并将返回UNAVAILABLE
文档已经说得很清楚了。最重要的事实是它取决于硬件级别/硬件模式。
让我们总结一下 对于传统设备
它将返回以下内容
  • 如果AE模式设置为ON_ALWAYS_FLASH,则返回FIRED
  • 如果闪光灯模式设置为TORCH,则返回FIRED
  • 如果相机没有闪光灯,则返回UNAVAILABLE。

当设备至少达到LEVEL_LIMITED时:
这些值是可能的,但不保证它们都能正常工作:
  • UNAVAILABLE
  • CHARGING
  • READY
  • FIRED
  • PARTIAL

感谢您的快速回复和提供资源。因此,我想一个解决方案是实现检查“FLASH_STATE”键并将其用于支持它的设备,但如果设备不支持它,是否仍然有其他方式可以检查? - rfblue2
1
你说得对,通常的方法是检查你请求的值。我不确定是否还有其他方法,但我猜想没有。因为智能手机制造商本身必须实现一个硬件抽象层来支持camera2 api的功能。所以我猜如果你不能以这种方式请求STATE,那么硬件和程序之间的通信接口就缺少了这个功能。 - daemmie
如果设备有闪光灯单元,FLASH_STATE将存在。 - Eddy Talvala

1

目前没有确切的方法可以知道闪光灯是否会触发 - 决定是由相机设备在全分辨率捕获前的最后一刻做出的。一旦完整分辨率捕获的最终捕获结果可用,如果闪光灯触发,则其闪光灯状态应为已触发,但您将在事后得到此结果。确保等待onCaptureCompleted的总捕获结果以检查此字段,而不是来自onCaptureProgressed的部分结果;部分结果可能会缺少各种字段。

话虽如此,如果在开始预捕获序列之前AE状态字段FLASH_REQUIRED,如果AE模式允许闪光灯(AE_MODE_ON_AUTO_FLASH / ALWAYS_FLASH / AUTO_FLASH_REDEYE),则很可能会触发闪光灯。这并不能100%保证,因为在开始预捕获序列(将执行预捕获闪光以估计必要的闪光功率)和实际最终图片捕获之间的几帧中场景可能会发生变化。但我认为95%的时间它会成为最终结果。


看起来很有前途,但即使CONTROL_AE_STATE也是可选的!(即,如果您查看文档,它会说“可选-某些设备上此值可能为null。”)。这在我的特定设备上是正确的,它总是输出“null”。我猜唯一保证检查闪光灯是否已经发生了? - rfblue2
1
你的设备是否为LEGACY级别的设备?如果是,那么就没有太多信息可以透露了。由于缺乏直接硬件支持,LEGACY设备在旧API之上有效地运行camera2 API,因此它们在产生的信息方面相当有限。请注意,“可选”并不意味着字段是否存在完全是任意的。这意味着存在某些配置,在这些配置中该字段可能不存在,因此应该小心处理,但大多数条目都具有明确定义的存在要求。AE_STATE必须在LIMITED或以上设备上存在。 - Eddy Talvala

0

问题

您正在尝试检测应用程序拍摄的照片是否使用了闪光灯。

解决方案

您可以使用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
}

1
Camera.Parameters自API 21起已被弃用。在使用Camera API2时,将其与之结合使用是否是一个好主意? - daemmie
谢谢您的快速回复 - 不过我有一个问题 - 如果相机设置为自动模式,我如何检查相机是否确实要闪光?因为有时在自动模式下它会闪光,而有时则不会。 - rfblue2
@rfblue2 在自动模式下,你应该检查捕获图像后触发的FLASH_STATE。希望这可以帮到你。在开始编写代码之前,你可能需要参考官方文档:https://developer.android.com/reference/android/hardware/camera2/CaptureResult.html#FLASH_STATE - Karan Sharma

0

相机 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
}

感谢您的快速回复。我不是在寻找相机是否具有闪光灯(这已在其他问题中得到回答),而是想知道当设置为自动闪光时,闪光灯是否即将触发,因为在自动模式下,闪光灯有时会触发,有时则不会。 - rfblue2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接