Search code examples
androidcamerapreview

Camera preview stops on activity restart


I made a camera preview app for android and everything works fine even when I press the power button to make device asleep, and waking it up again. But when my activity goes to background (like pressing home button) and then it comes to foreground again the program stops.

This is my activity code:

package com.example.campreview;

import com.example.campreview.CameraPreview;
import com.example.campreview.R;

import android.graphics.ImageFormat;
import android.hardware.Camera;
import android.hardware.Camera.AutoFocusCallback;
import android.hardware.Camera.PreviewCallback;
import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.view.Menu;
import android.view.View;

public class ScanActivity extends Activity  {

    private CameraPreview CamPrev = null;
    private FrameLayout PreviewFrm; 

    private Camera cam = null;    
    private Handler atfcs;
    private ImageScanner scnr;

    private boolean hascam = false;
    private boolean prvng = true;
    private boolean paused = false; 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scan);     
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        PreviewFrm = (FrameLayout)findViewById(R.id.PreviewFrm); 

        StartCamera();
        if (cam != null) {
            hascam = true;
            atfcs = new Handler();
            CamPrev = new CameraPreview(this, cam, PreviewCB, AutoFocusCB);
            PreviewFrm.addView(CamPrev);
        }    
    }

    @Override
    public void onPause() { 
        ReleaseCamera();
        paused = true;
        super.onPause();  
    }

    @Override
    public void onResume() {
        super.onResume();
        if (paused) StartPreview();
    }

    private boolean StartCamera() {
        boolean r = true;
        if (cam == null) {
            try {
                cam = Camera.open();
            } catch (Exception e) {
                cam = null;
                r = false;
            }
            if (cam != null) {
                try {
                    Camera.Parameters p = cam.getParameters();          
                    if (p.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO))
                        p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                    if (p.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_OFF))
                        p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                    if (p.getSupportedPreviewFormats().contains(ImageFormat.NV21))
                        p.setPreviewFormat(ImageFormat.NV21);
                    Camera.Size s = null;
                    int a = 0, b;       
                    for (Camera.Size z : p.getSupportedPreviewSizes()) {
                        b = z.width * z.height;
                        if (Math.abs(b - 307200) < Math.abs(a - 307200)) { //640x480 is the best
                            s = z;
                            a = b;
                        }   
                    }
                    if (a != 0) p.setPreviewSize(s.width, s.height);    
                    cam.setParameters(p);
                    cam.setDisplayOrientation(90);          
                    if (CamPrev != null) cam.setPreviewDisplay(CamPrev.getHolder());    
                } catch (Exception e) {
                    r = false;
                    cam.release();
                    cam = null;
                }
            }
        }
        return r;
    }

    private void ReleaseCamera() {
        if (cam != null) {
            StopPreview();
            cam.release();
            cam = null;
        }
    }

    public void StartPreview() {
        if ((!prvng) & hascam) {
            if (StartCamera()) {
                cam.setPreviewCallback(PreviewCB);
                cam.startPreview();
                cam.autoFocus(AutoFocusCB);
                prvng = true;               
            }
        }
    }

    public void StopPreview() {
        if (prvng) {
            cam.stopPreview();
            cam.setPreviewCallback(null);
            prvng = false;   
        }
    }

    private Runnable DoAutoFocus = new Runnable() {
        public void run() {
            if (prvng) cam.autoFocus(AutoFocusCB);
        }
    };

    AutoFocusCallback AutoFocusCB = new AutoFocusCallback() {
        public void onAutoFocus(boolean success, Camera camera) {
            atfcs.postDelayed(DoAutoFocus, 1000);
        }
    };

    PreviewCallback PreviewCB = new PreviewCallback() {
        public void onPreviewFrame(byte[] data, Camera camera) {             
             //
         }
     };

}

And this is the preview code:

package com.example.campreview;

import java.io.IOException;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.content.Context;
import android.hardware.Camera;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.AutoFocusCallback;

public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
    private SurfaceHolder hldr;
    private Camera cam;
    private PreviewCallback pcb;
    private AutoFocusCallback afcb;

    public CameraPreview(Context context, Camera camera, PreviewCallback previewCb, AutoFocusCallback autoFocusCb) {
        super(context);
        cam = camera;
        pcb = previewCb;
        afcb = autoFocusCb;
        hldr = getHolder();
        hldr.addCallback(this);
        //hldr.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        try {
            cam.setPreviewDisplay(holder);            
        } catch (IOException e) {
            // No Code
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {}

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (hldr.getSurface() == null) return;
        try {
            cam.stopPreview();
        } catch (Exception e){
            // No Code
        }
        try {
            cam.setPreviewDisplay(hldr);
            cam.setPreviewCallback(pcb);
            cam.startPreview();
            cam.autoFocus(afcb);
        } catch (Exception e) {
            // No Code
        }
    }
}

Is there any idea how can I solve this problem?


Solution

  • I found the problem. It seems the SurfaceView that is made in program destroys on activity stop. So I replaced it with a SurfaceView in my layout.

    package com.example.campreview;
    
    import com.example.campreview.R;
    
    import java.io.IOException;
    
    import android.graphics.ImageFormat;
    import android.hardware.Camera;
    import android.hardware.Camera.AutoFocusCallback;
    import android.hardware.Camera.PreviewCallback;
    import android.os.Bundle;
    import android.os.Handler;
    import android.app.Activity;
    import android.content.pm.ActivityInfo;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    
    public class ScanActivity extends Activity implements OnClickListener  {
    
        private SurfaceView PreviewSfc;
    
        private Camera cam = null;    
        private Handler atfcs;
    
        private boolean hascam = false;
        private boolean validdisplay = false; 
        private boolean prvng = false;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_scan);     
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    
            PreviewSfc = (SurfaceView)findViewById(R.id.PreviewSfc);
            PreviewSfc.getHolder().addCallback(SurfaceCB);
            //PreviewSfc.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    
            StartCamera();      
            if (cam != null) {
                hascam = true;
                atfcs = new Handler();
            }    
        }
    
        @Override
        public void onPause() { 
            ReleaseCamera();
            super.onPause();  
        }
    
        @Override
        public void onResume() {
            super.onResume();
            StartPreview();
        }
    
        private boolean StartCamera() {
            boolean r = true;
            if (cam == null) {
                try {
                    cam = Camera.open();
                } catch (Exception e) {
                    cam = null;
                    r = false;
                }
                if (cam != null) {
                    try {
                        Camera.Parameters p = cam.getParameters();          
                        if (p.getSupportedFocusModes().contains(Camera.Parameters.FOCUS_MODE_AUTO))
                            p.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
                        if (p.getSupportedFlashModes().contains(Camera.Parameters.FLASH_MODE_OFF))
                            p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
                        if (p.getSupportedPreviewFormats().contains(ImageFormat.NV21))
                            p.setPreviewFormat(ImageFormat.NV21);
                        Camera.Size s = null;
                        int a = 0, b;       
                        for (Camera.Size z : p.getSupportedPreviewSizes()) {
                            b = z.width * z.height;
                            if (Math.abs(b - 307200) < Math.abs(a - 307200)) { //640x480 is the best
                                s = z;
                                a = b;
                            }   
                        }
                        if (a != 0) p.setPreviewSize(s.width, s.height);    
                        cam.setParameters(p);
                        cam.setDisplayOrientation(90);          
                        if (validdisplay) cam.setPreviewDisplay(PreviewSfc.getHolder());
                    } catch (Exception e) {
                        r = false;
                        cam.release();
                        cam = null;
                    }
                }
            }
            //if (!r) Error message that failed to start camera
            return r;
        }
    
        private void ReleaseCamera() {
            if (cam != null) {
                StopPreview();
                cam.release();
                cam = null;
            }
        }
    
        public void StartPreview() {
            if ((!prvng) & (hascam) & (validdisplay)) {
                if (StartCamera()) {
                    cam.setPreviewCallback(PreviewCB);
                    cam.startPreview();
                    cam.autoFocus(AutoFocusCB);
                    prvng = true;   
                }
            }
        }
    
        public void StopPreview() {
            if (prvng) {
                cam.stopPreview();
                cam.setPreviewCallback(null);
                prvng = false;  
            }   
        }
    
        private Runnable DoAutoFocus = new Runnable() {
            public void run() {
                if (prvng) cam.autoFocus(AutoFocusCB);
            }
        };
    
        AutoFocusCallback AutoFocusCB = new AutoFocusCallback() {
            public void onAutoFocus(boolean success, Camera camera) {
                atfcs.postDelayed(DoAutoFocus, 1000);
            }
        };
    
        PreviewCallback PreviewCB = new PreviewCallback() {
            public void onPreviewFrame(byte[] data, Camera camera) {             
                 //
             }
         };
    
         SurfaceHolder.Callback SurfaceCB = new SurfaceHolder.Callback() {
             public void surfaceCreated(SurfaceHolder holder) {
                 if (cam != null) {
                     try {
                         cam.setPreviewDisplay(holder);              
                     } catch (IOException e) {
                         // No Code
                     }
                 }
             }
    
             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
                 validdisplay = true;
                 StartPreview();         
             }
    
             public void surfaceDestroyed(SurfaceHolder holder) {
                 validdisplay = false;
             }
         };
    
    }