简体   繁体   中英

App crashes when Resumed

I am creating a simple Flashlight App, but every time I leave the app and reopen it, it crashes. Am I missing something in my code, because I am not sure what, below is an error when it crashes. Please let me know what I need to do in order to fix this resume issue:

 package com.example.gkvxm.materiallight; import android.animation.ValueAnimator; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.Camera; import android.os.Bundle; import android.util.Log; import android.view.KeyEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.Toast; import com.dd.CircularProgressButton; import java.io.IOException; public class FlashLightActivity extends Activity implements SurfaceHolder.Callback { private boolean isLigtOn = false; private Camera camera; @Override protected void onStart(){ super.onStart(); SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW); SurfaceHolder mHolder = preview.getHolder(); mHolder.addCallback(this); } @Override protected void onStop(){ super.onStop(); if(camera!=null){ camera.release(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_flash_light); Context context = this; PackageManager pm = context.getPackageManager(); if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) { Toast.makeText(FlashLightActivity.this, "Your Device is not supported", Toast.LENGTH_SHORT).show(); Log.e("err", "Device is not supported"); return; } camera = Camera.open(); final Camera.Parameters p = camera.getParameters(); final CircularProgressButton circularButton1 = (CircularProgressButton) findViewById(R.id.btnWithText); circularButton1.setIndeterminateProgressMode(true); circularButton1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isLigtOn) { turnOffFlash(p); Toast.makeText(FlashLightActivity.this, "Lights Off!", Toast.LENGTH_SHORT).show(); } else { turnOnFlash(p); Toast.makeText(FlashLightActivity.this, "Lights On!", Toast.LENGTH_SHORT).show(); } if (circularButton1.getProgress() == 0) { simulateSuccessProgress(circularButton1); } else { circularButton1.setProgress(0); } } }); } private void turnOnFlash(Camera.Parameters p){ p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH); camera.setParameters(p); camera.startPreview(); isLigtOn = true; } private void turnOffFlash(Camera.Parameters p){ p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF); camera.setParameters(p); camera.stopPreview(); isLigtOn = false; } @Override public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){ } @Override public void surfaceCreated(SurfaceHolder holder){ try{ Log.i("SurfaceHolder","Setting preview"); camera.setPreviewDisplay(holder); } catch (IOException e){ e.printStackTrace(); } } @Override public void surfaceDestroyed(SurfaceHolder holder){ Log.i("SurfaceHOlder", "stopping preview"); camera.stopPreview(); holder = null; } private void simulateSuccessProgress(final CircularProgressButton button) { ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 100); widthAnimation.setDuration(1500); widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Integer value = (Integer) animation.getAnimatedValue(); button.setProgress(value); } }); widthAnimation.start(); } private void simulateErrorProgress(final CircularProgressButton button) { ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 99); widthAnimation.setDuration(1500); widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator()); widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { Integer value = (Integer) animation.getAnimatedValue(); button.setProgress(value); if (value == 99) { button.setProgress(-1); } } }); widthAnimation.start(); } } 

05-22 03:08:35.646  13909-13909/com.example.gkvxm.materiallight E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.gkvxm.materiallight, PID: 13909
java.lang.RuntimeException: Camera is being used after Camera.release() was called
        at android.hardware.Camera._stopPreview(Native Method)
        at android.hardware.Camera.stopPreview(Camera.java:732)
        at com.example.gkvxm.materiallight.FlashLightActivity.surfaceDestroyed(FlashLightActivity.java:129)
        at android.view.SurfaceView.updateWindow(SurfaceView.java:564)
        at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:238)
        at android.view.View.dispatchWindowVisibilityChanged(View.java:8785)
        at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1164)
        at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1164)
        at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1164)
        at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1164)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1318)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1061)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5885)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767)
        at android.view.Choreographer.doCallbacks(Choreographer.java:580)
        at android.view.Choreographer.doFrame(Choreographer.java:550)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5254)
        at java.lang.reflect.Method.invoke(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:372)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

As the Log says Camera is being used after Camera.release() was called . So, looking at the activity lifecycle you need to open camera in onStart() or in onRestart()

This exception is because of camera.release(); is called in the onStop() method of your activity. After releasing the camera instance you are reusing the released instance.

 camera = Camera.open();

move the above line from OnCreate() to onStart()

You are releasing the camera instance in onPause() which is correct due to documentation:

public final void release ()

Added in API level 1 Disconnects and releases the Camera object resources.

You must call this as soon as you're done with the Camera object.

But you also need to re-open it in onResume(), like you do in onCreate, since onCreate() not always is called when you resume the app.

As they state here :

Important: Call release() to release the camera for use by other applications. Applications should release the camera immediately in onPause() (and re-open() it in onResume()).

See this for more information about the android app lifecycle.

Good luck!

It may be you are camera.release(); on onStop() . And when surfaceDestroyed call you have used camera.stopPreview();

so camera is alredy release and you are going to stopePreview . thats way you are geting Camera is being used after Camera.release() was called this error.

so you have to cange that.

@Override
protected void onStop(){
    super.onStop();
}

and on surfaceDestroyed

@Override
public void surfaceDestroyed(SurfaceHolder holder){
    Log.i("SurfaceHOlder", "stopping preview");
    camera.stopPreview();
    camera.release();
    holder = null;
}

Camera is being used after Camera.release() was called. So, looking at the activity lifecycle you need to open camera in onStart() or in onRestart(). So May be this code will work fine ...

    package com.example.gkvxm.materiallight;

    import android.animation.ValueAnimator;
    import android.app.Activity;
    import android.content.Context;
    import android.content.pm.PackageManager;
    import android.hardware.Camera;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.KeyEvent;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    import android.view.View;
    import android.view.animation.AccelerateDecelerateInterpolator;
    import android.widget.Toast;

    import com.dd.CircularProgressButton;

    import java.io.IOException;


    public class FlashLightActivity extends Activity implements SurfaceHolder.Callback {

        private boolean isLigtOn = false;

        private Camera camera;

        @Override
        protected void onStart(){
            super.onStart();
             camera = Camera.open();
        final Camera.Parameters p = camera.getParameters();
            SurfaceView preview = (SurfaceView)findViewById(R.id.PREVIEW);
                SurfaceHolder mHolder = preview.getHolder();
            mHolder.addCallback(this);
        }

        @Override
        protected void onStop(){
            super.onStop();

            if(camera!=null){
                camera.release();
            }
        }
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_flash_light);

            Context context = this;
            PackageManager pm = context.getPackageManager();

            if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
                Toast.makeText(FlashLightActivity.this, "Your Device is not supported", Toast.LENGTH_SHORT).show();
                Log.e("err", "Device is not supported");
                return;
            }

            camera = Camera.open();
            final Camera.Parameters p = camera.getParameters();


            final CircularProgressButton circularButton1 = (CircularProgressButton) findViewById(R.id.btnWithText);
           circularButton1.setIndeterminateProgressMode(true);
            circularButton1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (isLigtOn) {
                        turnOffFlash(p);
                        Toast.makeText(FlashLightActivity.this, "Lights Off!", Toast.LENGTH_SHORT).show();

                    } else {
                        turnOnFlash(p);
                        Toast.makeText(FlashLightActivity.this, "Lights On!", Toast.LENGTH_SHORT).show();

                    }

                    if (circularButton1.getProgress() == 0) {
                        simulateSuccessProgress(circularButton1);
                    } else {
                        circularButton1.setProgress(0);
                    }
                }
            });
        }

        private void turnOnFlash(Camera.Parameters p){
            p.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);

            camera.setParameters(p);
            camera.startPreview();
            isLigtOn = true;
        }
        private void turnOffFlash(Camera.Parameters p){
            p.setFlashMode(Camera.Parameters.FLASH_MODE_OFF);
            camera.setParameters(p);
            camera.stopPreview();
            isLigtOn = false;
        }
        @Override
        public void surfaceChanged(SurfaceHolder holder,int format,int width,int height){

        }
        @Override
        public void surfaceCreated(SurfaceHolder holder){
            try{
                Log.i("SurfaceHolder","Setting preview");
                camera.setPreviewDisplay(holder);
            } catch (IOException e){
                e.printStackTrace();
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder){
            Log.i("SurfaceHOlder", "stopping preview");
            camera.stopPreview();
            holder = null;
        }

        private void simulateSuccessProgress(final CircularProgressButton button) {
            ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 100);
            widthAnimation.setDuration(1500);
            widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
            widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    Integer value = (Integer) animation.getAnimatedValue();
                    button.setProgress(value);
                }
            });
            widthAnimation.start();
        }

        private void simulateErrorProgress(final CircularProgressButton button) {
            ValueAnimator widthAnimation = ValueAnimator.ofInt(1, 99);
            widthAnimation.setDuration(1500);
            widthAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
            widthAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    Integer value = (Integer) animation.getAnimatedValue();
                    button.setProgress(value);
                    if (value == 99) {
                        button.setProgress(-1);
                    }
                }
            });
            widthAnimation.start();
        }


    }

I have same problem with camera class. Use this line onResume()

mCameraPreview.getHolder().removeCallback(mCameraPreview);

and its work now.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM