Search code examples
androidcameraandroid-cameraframepreview

Preview camera frame not capturing Android


I have the code setup (obviously not correctly but it seems ok)

My test code for capturing frame is like this:

frameCallback = new Camera.PreviewCallback() {
        public void onPreviewFrame(byte[] data, Camera camera) {
            System.out.println("preview frame captured");

But this onPreviewFrame is never ran, as the print statement tests.

The weird thing is, the preview is showing up perfectly on my surface. i.e- I can see it on my screen and there is no errors. Why isn't onPreviewFrame being called then?

Here is all my code for reference:

public class HuntActivity extends AppCompatActivity implements SurfaceHolder.Callback{

    Camera camera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    Camera.PreviewCallback frameCallback;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hunt);
        surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
        surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        frameCallback = new Camera.PreviewCallback() {
            public void onPreviewFrame(byte[] data, Camera camera) {

                System.out.println("preview frame captured");
            }
        };
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {

        try {camera = Camera.open();
        } catch (RuntimeException e) {
            System.err.println(e);
            return;
        }
        camera.setPreviewCallback(frameCallback);

        Camera.Parameters param;
        param = camera.getParameters();
        param.setPreviewSize(800, 480);
        camera.setDisplayOrientation(90);
        camera.setParameters(param);
        try {
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
        } catch (Exception e) {
            System.err.println(e);
            return;
        }

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        refreshCamera();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        camera.stopPreview();
        camera.release();
        camera = null;
    }

    public void refreshCamera() {
        if (surfaceHolder.getSurface() == null) {return;}
        try {camera.stopPreview();
        } catch (Exception e){}
        try {
            camera.setPreviewDisplay(surfaceHolder);
            camera.startPreview();
        } catch (Exception e) {}
    }

Solution

  • refreshCamera();
    

    Do not call that function there. It will stop the preview functionality before you can use it.

    Move following code to onSurfaceChanged() and use the width and heigth parameters

        Camera.Parameters param;
        param = camera.getParameters();
        //param.setPreviewSize(800, 480);        
        param.setPreviewSize(width, height);
        ... and the rest of those lines...
    

    Never hardcode resolutions like 800x480