Method called after release Exception Camera preview

前端 未结 7 1318

I have one activity class(CameraActivity) which is using my CameraPreview class. In \"OnResume\" the camera and preview are initiated. In \"OnPause\", i am releasing camera

相关标签:
7条回答
  • 2020-12-13 11:44

    Try the code below, instead of overriding onPause() and onResume(), override the onStop() and onRestart(). In the activity lifecycle, onStop() is called when the activity is not Visible and the next lifecycle method call would be to the onRestart(). Have a look at the code below.

    @Override
        protected void onStop() {
            super.onStop();
            try {
                m_camera.stopPreview();
                m_camera.release();
                preview.removeView(m_CameraPreview);
    /*
    m_CameraPreview is the object of the class that looks like this :                                public class CameraSurfaceView extends SurfaceView implements Callback
    */
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
        @Override
        protected void onRestart() {
            super.onRestart();
            m_camera=getCameraInstance();//Initialize the camera in your own way
            m_CameraPreview = new CameraSurfaceView(this, m_camera);
           preview = (FrameLayout)findViewById(R.id.camera_preview);   
            preview.addView(this.m_CameraPreview);
    /* 
    *camera_preview is the id of the framelayout defined in xml file and preview is *the instance of FrameLayout. 
    */
        }
    

    As Dan said, the frame layout will have a hold to the previous camera instance and its' surfaceview callbacks will be created in addition to the new objects creating a race condition. Hence you would need to release it in onStop() and reinitialize in onRestart(). Hope this helps.

    0 讨论(0)
  • 2020-12-13 11:50

    My working solution: First: In CameraActivity class declare mCamera as array:

    Camera mCamera[] = new Camera[1];
    

    Second: declaration of the constructor CameraPreview must look like this:

    public CameraPreview(Context context, Camera[] camera,
                         PreviewCallback previewCb,
                         AutoFocusCallback autoFocusCb) {
          mCamera = camera;
          ...
    }
    

    But mCamera in CameraPreview class must be declared as follows:

    Camera[] mCamera; // without instantiating of the array!
    

    And finally: in both classes inside all the methods you should replace all references mCamera by mCamera[0]

    P.S: Sorry for my English

    0 讨论(0)
  • 2020-12-13 11:51

    As you have added the camera to the FrameLayout, like this:

    FrameLayout preview = (FrameLayout)findViewById(R.id.cameraPreview);
    preview.addView(mPreview);
    

    The surfaceCreated method will be called and so mCamera.setPreviewDisplay(holder); will be called.

    When you create/open a new camera, the FrameLayout still has your previous camera and so its surfaceCreated will be called in addition to your new camera.

    What you should do, is remove your previous camera from FrameLayout when you release your camera (on onPause() method) like this:

    preview.removeView(mPreview);
    

    Hope it helps.

    0 讨论(0)
  • 2020-12-13 11:59

    EDIT

    This is a tough one to answer, I can't be 100% sure what's causing your exceptions right now. I have included my Camera code below, hopefully that will help, I use startCamera() and stopCamera() methods that I call in onPause and onResume. I also, only create a new instance of the CameraPreview class in my onCreate, I don't re-instantiate in onResume unless my cameraView == null. There are a couple things we do differently. Hopefully the code below will help, maybe you can play with it to get yours working:

    P.S.: Everything works for me. i.e. Going into other Activities, etc. The only part of the Lifecycle I haven't tested is onDestroy, but that is because my application is designed to start at the beginning in this cycle.

    MainActivity:

    boolean cameraReleased = false;
    
    @Override
    protected void onPause() {
        Log.i("onPause", "CALLED:: cameraReleased = " + cameraReleased);
        Log.i("onResume", "CALLED:: cameraView = " + cameraView.toString());
        if (cameraReleased == false) {
            image = null;
            imageResult.setImageBitmap(null);
            imageResult.setImageResource(0);
            cameraView.stopCamera();
            cameraReleased = true;
        }
    
        if (cameraView == null) {
            Log.i("onPause", "cameraView == null");
            cameraView = new JJCameraSurfaceView(getApplicationContext());
            imageResult = new ImageView(getApplicationContext());
        }
        super.onPause();
    }
    
    @Override
    protected void onDestroy() {
        Log.e("onDestroy", "INITIATED");
        super.onDestroy();
    }
    
    @Override
    protected void onResume() {
        Log.i("onResume", "CALLED:: cameraReleased = " + cameraReleased);
        Log.i("onResume", "CALLED:: cameraView = " + cameraView.toString());
        if (cameraReleased == true) {
            image = null;
            imageResult.setImageBitmap(null);
            imageResult.setImageResource(0);
            cameraView.startCamera();
        }
    
        if (cameraView == null) {
            Log.i("onResume", "cameraView == null");
            cameraView = new JJCameraPreview(getApplicationContext());
            imageResult = new ImageView(getApplicationContext());
        }
    
        super.onResume();
    }
    
    @Override
    public void onBackPressed() {
        // If Statement used to get out of my camera view and back to my MainActivity - Same Class
        if (“Camera Preview or Image Result is displayed”) {
            cameraView.stopCamera();
            image = null;
            imageResult.setImageBitmap(null);
            imageResult.setImageResource(0);
            cameraView.startCamera();
            return;
        }
    
        Log.i("onBackPressed", "WAS PRESSED");
        super.onBackPressed();
    }
    

    CameraPreview:

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        Log.w("surfaceChanged", "STARTED");
        if (camera != null) {
            Log.w("surfaceChanged", "camera = NOT NULL");
            Camera.Parameters cParams = camera.getParameters();
            cParams.setPreviewSize(width, height);
            cParams.setSceneMode(Parameters.SCENE_MODE_NIGHT);
            camera.setParameters(cParams);
            camera.startPreview();
        }
    }
    
    public void surfaceCreated(SurfaceHolder holder) {
        Log.w("surfaceCreated", "STARTED");
        if (camera == null) {
            camera = Camera.open(); 
        }
        try {
            camera.setPreviewDisplay(mHolder);
        } catch (Exception e) {
            Log.e("setPreviewDisplay", "FAILED: " + e.getMessage());
        }
    }
    
    public void surfaceDestroyed(SurfaceHolder holder) {
        Log.w("CameraSurfaceDestroyed", "INITIATED");
        camera.stopPreview();
        camera.release();
        camera = null;
    }
    
    public void startCamera() {
        Log.w("startCamera", "CALLED");
        mHolder = getHolder();
        surfaceCreated(mHolder);
        camera.startPreview();
        mHolder.addCallback(this);
    }
    
    public void stopCamera() {
        mHolder = getHolder();
        mHolder.removeCallback(this);
        camera.stopPreview();
    }
    
    0 讨论(0)
  • 2020-12-13 12:00

    I had a similar problem with my code which was force closing with the Method called after release() error.

    I was calling a SetupCamera() method in OnResume()which checked for a null camera object and then called camera.Open().

    What fixed my problem was to get rid of the null-check and just call camera.Open() whether it was null or not (I had already set camera = null on onPause) after reading the Camera Docs.

    I know this is not definitive in tracking down my problem, but it absolutely worked for me!

    0 讨论(0)
  • 2020-12-13 12:06

    I was getting same error. Below sequence solves my problem.

    Call getHolder().removeCallback(this); in surfaceDestroyed()

    Call

     private void releaseCameraAndPreview() {
    
            if (mCamera != null) {
                mCamera.stopPreview();
                mCamera.setPreviewCallback(null);
                mCamera.release();
                mCamera = null;
            }
    
            if(mPreview != null){
                mPreview.destroyDrawingCache();
                mPreview.mCamera = null;
            }
    
        }
    

    in onPause

    Call

      private boolean safeCameraOpenInView(View view) {
            boolean qOpened = false;
            releaseCameraAndPreview();
            mCamera = getCameraInstance();
            mCameraView = view;
            qOpened = (mCamera != null);
    
            if(qOpened == true){
                mPreview = new CameraPreview(getActivity().getBaseContext(), mCamera,view);
                preview = (FrameLayout) view.findViewById(R.id.camera_preview);
                preview.addView(mPreview);
                mPreview.startCameraPreview();
            }
            return qOpened;
        }
    

    in onCreateView().

    0 讨论(0)
提交回复
热议问题