恢复应用程序时应用程序崩溃

Application Crashes when resuming the app

我正在创建一个简单的手电筒应用程序,但每次我离开应用程序并重新打开它时,它都会崩溃。我是否在我的代码中遗漏了什么,因为我不确定是什么,下面是它崩溃时的错误。请告诉我如何解决此简历问题:

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)

正如日志所说 Camera is being used after Camera.release() was called。因此,查看 activity lifecycle 您需要在 onStart()onRestart()

中打开相机

此异常是因为 camera.release(); 在您的 activity 的 onStop() 方法中被调用。释放相机实例后,您将重新使用已释放的实例。

 camera = Camera.open();

将上面的行从OnCreate()移动到onStart()

您正在释放 onPause() 中的相机实例,根据文档这是正确的:

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.

但是您还需要在 onResume() 中重新打开它,就像您在 onCreate 中所做的那样,因为在您恢复应用程序时并不总是调用 onCreate()。

正如他们所说 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()).

有关 android 应用程序生命周期的详细信息,请参阅 this

祝你好运!

您可能 camera.release();onStop()。当 surfaceDestroyed 调用时,您使用了 camera.stopPreview();

所以 camera 已经 release 而你将要 stopePreview。这就是你得到 Camera is being used after Camera.release() was called 这个错误的方式。

所以你必须改变它。

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

以及 surfaceDestroyed

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

调用 Camera.release() 后正在使用相机。因此,查看 activity 生命周期,您需要在 onStart()onRestart() 中打开相机。所以也许这段代码可以正常工作...

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();
    }
}

我的相机也有同样的问题class。使用这一行 onResume()

mCameraPreview.getHolder().removeCallback(mCameraPreview);

及其现在的工作。

我的应用有同样的问题, 当我在我的 on create 函数中删除“on click listener”时,问题就解决了。

我认为我们不应该在我们的 onCreate 方法中插入任何实现函数或其他东西...

最好只使用onCreate来声明和实例化变量。