How to get single preview frame in Camera2 API Android 5.0?

theb1uro picture theb1uro · Apr 2, 2015 · Viewed 16k times · Source

I'm trying to get a preview frame for QR code scanning functionality using Camera2 API. In old Camera API it's as easy as:

    android.hardware.Camera mCamera;
    ...
    mCamera.setPreviewCallback(new Camera.PreviewCallback() {
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            // will be invoked for every preview frame in addition to displaying them on the screen             
        }
    });

However, I can't find a way to achieve that using new Camera2 API. I'd like to receive multiple frames that I can work on - the best would be to receive byte array as in old API. Any ideas how to do that?

Answer

crysxd picture crysxd · May 11, 2019

A little late but better than never:

Usually a TextureView is used to display the preview of the camera. You can use TextureView.SurfaceTextureListener to get a callback every time the surface changes. TextureView does provide a method getBitmap(Bitmap) which you can use to get the preview frame in the same size as the TextureView.

You can use this Google sample as starting point. Simply update the surfaceTextureListener like shown here:

private val surfaceTextureListener = object : TextureView.SurfaceTextureListener {

    override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) {
        openCamera(width, height)
    }

    override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) {
        configureTransform(width, height)
    }

    override fun onSurfaceTextureDestroyed(texture: SurfaceTexture) = true

    override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {
        // Start changes
        // Get the bitmap
        val frame = Bitmap.createBitmap(textureView.width, textureView.height, Bitmap.Config.ARGB_8888)
        textureView.getBitmap(frame)

        // Do whatever you like with the frame
        frameProcessor?.processFrame(frame)
        // End changes
    }

}