重新输入Google Camera API应用程序后崩溃

时间:2018-08-28 20:23:10

标签: java android android-activity android-camera

我正在使用Google的相机API制作一个非常基本的相机应用。 最初启动该应用程序是可以的,但是一旦退出并重新进入,它就会崩溃。我找到了类似的答案,但无法将其应用于我的特定代码/情况。我也尝试过弄乱onPause(),onResume等,但是没有用。为什么会发生这种情况,我该如何解决?

下面是相关的方法和错误日志。

SurfaceView类:

public class ImageSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private Camera camera;
private SurfaceHolder surfaceHolder;
private String TAG = ImageSurfaceView.class.getSimpleName();

public ImageSurfaceView(Context context, Camera camera) {
    super(context);
    this.camera = camera;
    surfaceHolder = getHolder();
    surfaceHolder.addCallback(this);
    surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}

@Override
public void surfaceCreated(SurfaceHolder holder) {

    try {
            this.camera.setPreviewDisplay(holder);
            this.camera.startPreview();
            this.camera.setDisplayOrientation(90);

    } catch (IOException e) {
        Log.d(TAG, "Error setting camera preview: " + e.getMessage());
    }
}

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

    if (holder.getSurface() == null){
        // preview surface does not exist
        return;
    }

    try {
        camera.stopPreview();
    } catch (Exception e){
        // ignore: tried to stop a non-existent preview
    }
    try {
        Camera.Parameters params = camera.getParameters();
        List<Camera.Size> supportedPreviewSizes = params.getSupportedPreviewSizes();
        Camera.Size camPreviewSize = getOptimalPreviewSize(supportedPreviewSizes, width , height);

        params.setPreviewSize(camPreviewSize.width ,camPreviewSize.height);
        camera.setParameters(params);
    } catch (RuntimeException e) {
        Log.d(TAG, "Error getting camera parameters: " + e.getMessage());
    }


    try {
       camera.setPreviewDisplay(surfaceHolder);
       camera.startPreview();

    } catch (Exception e){
        Log.d(TAG, "Error starting camera preview: " + e.getMessage());
    }
}

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

    if (camera != null) {
        // Call stopPreview() to stop updating the preview surface.
       camera.stopPreview();

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

       camera = null;
    }
}
private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
    final double ASPECT_TOLERANCE = 0.1;
    double targetRatio=(double)h / w;

    if (sizes == null) return null;

    Camera.Size optimalSize = null;
    double minDiff = Double.MAX_VALUE;

    int targetHeight = h;

    for (Camera.Size size : sizes) {
        double ratio = (double) size.width / size.height;
        if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
        if (Math.abs(size.height - targetHeight) < minDiff) {
            optimalSize = size;
            minDiff = Math.abs(size.height - targetHeight);
        }
    }

    if (optimalSize == null) {
        minDiff = Double.MAX_VALUE;
        for (Camera.Size size : sizes) {
            if (Math.abs(size.height - targetHeight) < minDiff) {
                optimalSize = size;
                minDiff = Math.abs(size.height - targetHeight);
            }
        }
    }
    return optimalSize;
}

}

onPause / onResume

protected void onPause() {
    Log.d(TAG, " -> onPause");
    if(camera != null){
        releaseCamera();
    }
    super.onPause();
    Log.d(TAG, " <- onPause");

}
private void releaseCamera(){
    if (camera != null){

       camera.release(); 
        camera = null;
    }
}
 @Override
public void onResume() {
     super.onResume();
         Log.d(TAG, " -> OnResume");
       if (camera == null) {
           camera = checkDeviceCamera();
       }

         Log.d(TAG, " <- OnResume");
 }

相机方法:

private Camera checkDeviceCamera(){
    Camera mCamera = null;
    try {
        mCamera = Camera.open();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return mCamera;
}
private void startCamera() {

    camera = checkDeviceCamera();

    mImageSurfaceView = new ImageSurfaceView(MainActivity.this, camera);
    cameraPreviewLayout = (FrameLayout) findViewById(R.id.camera_preview); //the framelayout
    cameraPreviewLayout.addView(mImageSurfaceView); //adding surfaceview to framelayout

    ImageButton captureButton = (ImageButton)findViewById(R.id.imageButton);
    captureButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            camera.takePicture(null, null, pictureCallback);

        }
    });
}

Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {

    @Override
    public void onPictureTaken(byte[] data, Camera cam) {
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                if (camera != null) {
                    camera.startPreview();
                }
            }
        }, 0);
    }
};

错误:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: daniel816.com.danger, PID: 10594
              java.lang.RuntimeException: Camera is being used after Camera.release() was called
                  at android.hardware.Camera.setPreviewSurface(Native Method)
                  at android.hardware.Camera.setPreviewDisplay(Camera.java:738)
                  at danielwei816.com.danger.ImageSurfaceView.surfaceCreated(ImageSurfaceView.java:33)
                  at android.view.SurfaceView.updateWindow(SurfaceView.java:634)
                  at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:256)
                  at android.view.View.dispatchWindowVisibilityChanged(View.java:10293)
                  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1289)
                  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1289)
                  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1289)
                  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1289)
                  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1289)
                  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1289)
                  at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1289)
                  at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1599)
                  at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1299)
                  at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6558)
                  at android.view.Choreographer$CallbackRecord.run(Choreographer.java:871)
                  at android.view.Choreographer.doCallbacks(Choreographer.java:683)
                  at android.view.Choreographer.doFrame(Choreographer.java:619)
                  at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:857)
                  at android.os.Handler.handleCallback(Handler.java:751)
                  at android.os.Handler.dispatchMessage(Handler.java:95)
                  at android.os.Looper.loop(Looper.java:154)
                  at android.app.ActivityThread.main(ActivityThread.java:6316)
                  at java.lang.reflect.Method.invoke(Native Method)
                  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:872)
                  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:762)

1 个答案:

答案 0 :(得分:0)

您具有活动的生命周期(onResume,onPause等)和SurfaceView的生命周期(surfaceChanged,surfaceDestroyed等)。 您在onPause中释放相机,但在surfaceDestroyed中将其停止(稍后称为)。我认为这是问题所在。