Changing Flash setting of Android Camera 2 at runt

2019-02-22 09:34发布

Basically, what I am trying to do is change the CONTROL_AE_MODE by button click in the app. The user can use AUTO flash(ON_AUTO_FLASH), turn if ON(ON_ALWAYS_FLASH), or OFF(CONTROL_AE_MODE_OFF).

In this example: https://github.com/googlesamples/android-Camera2Basic/blob/master/Application/src/main/java/com/example/android/camera2basic/Camera2BasicFragment.java

Line 818, they set the flash once:

// Use the same AE and AF modes as the preview.
            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            setAutoFlash(captureBuilder);

            // Orientation
            int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));

            CameraCaptureSession.CaptureCallback CaptureCallback
                    = new CameraCaptureSession.CaptureCallback() {

                @Override
                public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                               @NonNull CaptureRequest request,
                                               @NonNull TotalCaptureResult result) {
                    showToast("Saved: " + mFile);
                    Log.d(TAG, mFile.toString());
                    unlockFocus();
                }
            };

            mCaptureSession.stopRepeating();
            mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);

And then builds the CaptureSession at line 840.

Is there a way to change the CONTROL_AE_MODE after the preview is made?

I have tried remaking the session, which kinda worked:

if(flashMode == CameraView.CAMERA_FLASH_ON){
            Log.e("CAMERA 2", "FLASH ON");
            mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
        }else if(flashMode == CameraView.CAMERA_FLASH_OFF){
            Log.e("CAMERA 2", "FLASH OFF");
            mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_OFF);
        }else if(flashMode == CameraView.CAMERA_FLASH_AUTO){
            Log.e("CAMERA 2", "FLASH AUTO");
            mPreviewCaptureRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
        }
        mFlashMode = flashMode;
        if (mCameraCaptureSession != null) {
            mCameraCaptureSession.close();
            mCameraCaptureSession = null;
       }
  createCameraPreviewSession();

For some reason, CONTROL_AE_MODE_OFF would turn the whole preview black. I tried looking in the docs for methods to update but haven't found anything.

Any tutorials or docs is much appreciated.

3条回答
兄弟一词,经得起流年.
2楼-- · 2019-02-22 09:58

What you want is disabling flash, not auto-exposure (AE), thus you want to use CONTROL_AE_MODE_ON rather than CONTROL_AE_MODE_OFF.

As mentioned in the documentation:

CONTROL_AE_MODE_ON

The camera device's autoexposure routine is active, with no flash control.

查看更多
劫难
3楼-- · 2019-02-22 10:04

I don't know why your preview turn black, but you don't need to close capture session manually. From .close() method's docs:

Using createCaptureSession(List , CameraCaptureSession.StateCallback, Handler) directly without closing is the recommended approach for quickly switching to a new session, since unchanged target outputs can be reused more efficiently.

So you can reuse existing CaptureRequest.Builder, set your changed value, build new PreviewRequest and just start new session with this new request, like this:

try {
    // Change some capture settings
    mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
    // Build new request (we can't just edit existing one, as it is immutable)
    mPreviewRequest = mPreviewRequestBuilder.build();
    // Set new repeating request with our changed one
    mCaptureSession.setRepeatingRequest(mPreviewRequest, mCaptureCallback, mBackgroundHandler);
} catch (CameraAccessException e) {
    e.printStackTrace();
}

It will be much faster (almost without any visible freeze of preview).

查看更多
smile是对你的礼貌
4楼-- · 2019-02-22 10:09

As mentioned by @cyborg86pl when switching flash modes you should not switch CONTROL_AE_MODE . Instead you can switch between FLASH_MODE´s. Here is a working example for my case:

  when (currentFlashState) {
        FlashState.AUTO -> {
          previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH)
        }
        FlashState.ON -> {
          previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
          previewRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH)
        }
        FlashState.OFF -> {
          previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON)
          previewRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF)
        }
      }
 previewRequest = previewRequestBuilder.build()
 captureSession.setRepeatingRequest(previewRequest, captureCallback, backgroundHandler)
查看更多
登录 后发表回答