how do I capture a single image with the Android Camera2 API?

android

Solution

since your question I started reading and digging into it, and I believe that's the way it works. As per doc (link) says:

Each request will produce one CaptureResult and produce new frames for one or more target Surfaces

note that it says "frames". In plural.

Said that I believe you should only consider the last frame from inside `onCaptureCompleted` callback.

Problem

I am using the Android Camera2 API to capture and process an image. The image processing happens in reponse to a successful capture. The problem I am having is that the camera captures 2 images, I have been unable to change the code in the Camera2Basic sample to ensure only a single image is captured. The issue can be demonstrated by adding logging code to the `ImageSaver.run()` method in `Camera2BasicFragment.java` ``` public void run() { Log.d("Camera2", "Saving image"); ByteBuffer buffer = mImage.getPlanes()[0].getBuffer(); ... } ``` Edit - after further investigation the issue appears to be in the implementation of the sample, rather than anything fundamental to the API. In the sample, the following code tracks the state changes of the camera, ``` private void process(CaptureResult result) { switch (mState) { case STATE_PREVIEW: { // We have nothing to do when the camera preview is working normally. break; } case STATE_WAITING_LOCK: { int afState = result.get(CaptureResult.CONTROL_AF_STATE); if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) { // CONTROL_AE_STATE can be null on some devices Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); if (aeState == null || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) { mState = STATE_WAITING_NON_PRECAPTURE; /** CAPTURE 1 */ captureStillPicture(); } else { runPrecaptureSequence(); } } break; } case STATE_WAITING_PRECAPTURE: { ... break; } case STATE_WAITING_NON_PRECAPTURE: { // CONTROL_AE_STATE can be null on some devices Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) { mState = STATE_PICTURE_TAKEN; /** CAPTURE 2 **/ captureStillPicture(); } break; } } } ``` I have verified that both invocations of `captureStillPicture` result in an image being generated, and hence processed. I'm not entirely sure what the correct state transitions should be. I am using a Motorola Nexus 6

Original source