android video app still capture session
The android video app still capture session tutorial describes the setup of the camera capture session for capturing a still image once the autofocus has locked.
Get Code
The code to start this tutorial is on github here
https://github.com/mobapptuts/android_camera2_api_video_app.git Tag camera2-video-still-preview
or you can run this command
git clone https://github.com/mobapptuts/android_camera2_api_video_app.git –branch camera2-video-still-preview
Steps
Add members for the image folder and image filenames
private File mImageFolder; private static String mImageFileName;
Create the image folder and call it from the onCreate method
private void createImageFolder() { File imageFile = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); mImageFolder = new File(imageFile, "camera2VideoImage"); if(!mImageFolder.exists()) { mImageFolder.mkdirs(); } }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera2_video_image); createVideoFolder(); createImageFolder();
Add a method for creating unique file names for images
private File createImageFileName() throws IOException { String timestamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(new Date()); String prepend = "IMAGE_" + timestamp + "_"; File imageFile = File.createTempFile(prepend, ".jpg", mImageFolder); mImageFileName = imageFile.getAbsolutePath(); return imageFile; }
Create a method to do the still capture in the preview session
private void startStillCaptureRequest() { try { mCaptureRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); mCaptureRequestBuilder.addTarget(mImageReader.getSurface()); mCaptureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, mTotalRotation); CameraCaptureSession.CaptureCallback stillCaptureCallback = new CameraCaptureSession.CaptureCallback() { @Override public void onCaptureStarted(CameraCaptureSession session, CaptureRequest request, long timestamp, long frameNumber) { super.onCaptureStarted(session, request, timestamp, frameNumber); try { createImageFileName(); } catch (IOException e) { e.printStackTrace(); } } }; mPreviewCaptureSession.capture(mCaptureRequestBuilder.build(), stillCaptureCallback, null); } catch (CameraAccessException e) { e.printStackTrace(); } }
Call that method inside the preview session callback
private CameraCaptureSession.CaptureCallback mPreviewCaptureCallback = new CameraCaptureSession.CaptureCallback() { private void process(CaptureResult captureResult) { switch (mCaptureState) { case STATE_PREVIEW: // Do nothing break; case STATE_WAIT_LOCK: mCaptureState = STATE_PREVIEW; Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE); if(afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED) { Toast.makeText(getApplicationContext(), "AF Locked!", Toast.LENGTH_SHORT).show(); startStillCaptureRequest(); } break; } } @Override public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, TotalCaptureResult result) { super.onCaptureCompleted(session, request, result); process(result); } };
Create a runnable for saving the image to a file
private static class ImageSaver implements Runnable { private final Image mImage; private ImageSaver(Activity activity, Image image, Handler handler) { mImage = image; } @Override public void run() { ByteBuffer byteBuffer = mImage.getPlanes()[0].getBuffer(); byte[] bytes = new byte[byteBuffer.remaining()]; byteBuffer.get(bytes); FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(mImageFileName); fileOutputStream.write(bytes); } catch (IOException e) { e.printStackTrace(); } finally { mImage.close(); if(fileOutputStream != null) { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
Inside the ImageReader on image available listener to the image to the ImageSaver runnable so it can be saved to a file
private ImageReader.OnImageAvailableListener mImageAvailableListener = new ImageReader.OnImageAvailableListener() { @Override public void onImageAvailable(ImageReader reader) { mBackgroundHandler.post(new ImageSaver(reader.acquireLatestImage())); } };
Now run the code in the application and see if it saves images while in the normal preview mode.
Android video app still capture session summary
In the android video app still capture session tutorial we had to setup the storage for the still images. Which involved creating a folder for the files and unique file names for each image.
We then created a capture request for the still images and used the onCaptureStarted callback to create the image filename.
We then created a runnable so that the image could be saved to storage with the assigned filename in a background thread. And then called the runnable once the capture still image was made available from the ImageReader.