终于想通了,gpuser 的回答使用了正确的标志,但它不完整 - 仍然需要编写回调代码并在需要时打开手电筒。
我还发现,对于视频录制,我们仍然使用相同的 Camera2 API 初始化和配置步骤,只是有些回调会被触发多次,所以我添加了一个标志来只执行一次闪光检测。
1)相机开始拍摄后,运行这段代码
performAutoTorchDetectionOnce = true; // set this flag first, will be used later
captureRequestBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); // CONTROL_AE_MODE_ON_AUTO_FLASH is important here, to enable flash detection
captureSession.setRepeatingRequest(captureRequestBuilder.build(), captureCallback, null);
2)这是我的 captureCallback 实现,根据您的需要进行更改。它的要点是最终相机捕获将落入两种状态之一,CONTROL_AE_STATE_CONVERGED 或 CONTROL_AE_STATE_FLASH_REQUIRED。这两种状态意味着自动曝光算法已经运行完毕,如果它收敛意味着不需要闪光灯,而flash_required意味着我们必须打开闪光灯。在后者中,我们将需要在下一步中手动打开闪光灯。
private CameraCaptureSession.CaptureCallback captureCallback =
new CameraCaptureSession.CaptureCallback() {
@Override
public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request,
long timestamp, long frameNumber) {
super.onCaptureStarted(session, request, timestamp, frameNumber);
}
@Override
public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) {
super.onCaptureCompleted(session, request, result);
Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
if (aeState != null) {
if (performAutoTorchDetectionOnce) {
if (aeState == CameraMetadata.CONTROL_AE_STATE_CONVERGED // CONTROL_AE_STATE_CONVERGED means Auto-exposure has finished
|| aeState == CameraMetadata.CONTROL_AE_STATE_FLASH_REQUIRED) { // CONTROL_AE_STATE_FLASH_REQUIRED means Auto-exposure has finished, but flash is required
performAutoTorchDetectionOnce = false;
enableTorch(aeState == CameraMetadata.CONTROL_AE_STATE_FLASH_REQUIRED);
}
}
}
}
};
3) 这是 enableTorch 的实现。我尝试将 CONTROL_AE_MODE 保留为 CONTROL_AE_MODE_ON_AUTO_FLASH 但它不起作用,手电筒灯不亮,所以我必须将其更改为 CONTROL_AE_MODE_ON。
public synchronized void enableTorch(boolean enable) {
Timber.d("enableTorch(" + enable + ") called");
try {
if (isCaptureStarted()) {
if (enable) {
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
} else {
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
}
captureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
captureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null);
}
} catch (CameraAccessException e) {
Timber.e(e, "enableTorch(" + enable + ") failed: ");
}
}