CameraActivity生命周期相机释放投掷错误

时间:2017-09-19 19:33:22

标签: android android-camera android-lifecycle camera-api

我正在使用表面视图和Camera 1 API创建自定义相机应用程序,生命周期中存在某种问题而我无法让它工作,但基本上我正在释放相机然后再次调用它:< / p>

  

调用Camera.release()后正在使用相机

理想情况下,当按下后退按钮时,应该返回上一个活动,按下主页按钮时应该重新打开,没有任何问题。

有人会指导我完成这些调用的实施,例如发布和打开相机:

自定义曲面视图类:

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

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


@Override
public void surfaceCreated(SurfaceHolder holder) {
    try {
        this.camera.setPreviewDisplay(holder);
        this.camera.startPreview();
    } catch (IOException ex){
        Log.e(TAG, "surfaceCreated: "+ex.getMessage() );
    }

}

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

}

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

}

和我的CameraAcitivty LifeCycle CallBacks:

@Override
protected void onRestart() {
    super.onRestart();
    camera = null;
    requestCamera();
}

@Override
protected void onResume() {
    super.onResume();
    try {
        requestCamera();
    } catch (RuntimeException ex){
        Log.e(TAG, "onResume: "+ex.getMessage() );
    }
}

@Override
protected void onPause() {
    super.onPause();
    if (camera != null) {
        camera.setPreviewCallback(null);
        imageSurfaceView.getHolder().removeCallback(imageSurfaceView);
        camera.release();
        camera = null;
    }
}

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

@Override
protected void onDestroy() {
    super.onDestroy();
    releaseCameraAndPreview();
}

private void releaseCameraAndPreview(){

    if (camera != null) {
        camera.stopPreview();
        camera.release();
        camera = null;
    }
    if(imageSurfaceView != null){
        imageSurfaceView.destroyDrawingCache();
    }
}

private void requestCamera(){
    if (camera == null) {
        if (checkPermission()) {
            callCameraThread();
            Toast.makeText(getApplicationContext(), "Permission already granted", Toast.LENGTH_LONG).show();
        } else {
            requestPermission();
        }
    }
}

public Camera checkDeviceCamera(){
    Camera mCamera = null;
    try {
        mCamera = Camera.open(0);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return mCamera;
}

private void callCameraThread(){
    if(mThread == null){
        mThread = new CameraHandlerThread();
    }

    synchronized (mThread){
        mThread.openCamera();
    }
}

public synchronized void loadSurface(){
    while(camera == null){
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    if(!isSurfaceCreated) {
        imageSurfaceView = new ImageSurfaceView(CameraActivity.this, camera);
        cameraPreviewLayout.addView(imageSurfaceView);
        isSurfaceCreated = true;
        imgGhost = new ImageView(this);
        imgGhost.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        imgGhost.setBackground(ContextCompat.getDrawable(this, R.drawable.fantasma_doc_front));
        cameraPreviewLayout.addView(imgGhost);
    }
}

private CameraHandlerThread mThread = null;
private class CameraHandlerThread extends HandlerThread {
    Handler mHandler = null;

    CameraHandlerThread(){
        super("CameraHandlerThread");
        start();
        mHandler = new Handler(getLooper());
    }

    synchronized  void notifyCameraOpened(){
        notifyAll();
    }

    void openCamera(){
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                camera = checkDeviceCamera();
                notifyCameraOpened();
            }
        });
        try{
            wait();
        } catch (InterruptedException ex){
            Log.e(TAG, "openCamera: "+"wait was interrupted" );
        }
    }
}

我不知道如何正确处理相机的发布和表面视图的创建,现在我做了一些更改后,我能够按下主页按钮并回来没有问题,但onBackPressed崩溃,之前是相反的,谢谢事先得到任何帮助

1 个答案:

答案 0 :(得分:0)

所以,我试图尽量减少对相机的重复引用,这是onBackPressed的样子:

@Override
public void onBackPressed() {
    if (isPreviewing) {  //if previewing layout is on screen, then I want to return to the camera, without saving the picture
        rlPicturePreview.setVisibility(View.GONE);
        llCameraControl.setVisibility(View.VISIBLE);
        isPreviewing = false;
        isPictureProcessing = false;
        camera.startPreview();
    } else {
        if(!isPictureProcessing) {   //Otherwise if there is no process happening I want to go back to previous calling activity, therefore closing the camera
            previousDataExists = false;
            isSurfaceCreated = false;
            DriverFragment.docPicturesArray.clear();
            CameraDocActivity.this.finish();
        }
    }
}

这就是onResume()现在的样子,我添加了对在棒棒糖,Marshmallow和Nougat中测试的大多数现代API的支持

@Override
protected void onResume() {
    super.onResume();
    try {
        if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M){
            callCameraThread();
            loadSurface();
        } else {
            requestCamera();
        }
    } catch (RuntimeException ex){
        Log.e(TAG, "onResume: "+ex.getMessage() );
    }
}
onRestart中的

只需删除requestCamera():

@Override
protected void onRestart() {
    super.onRestart();
    camera = null;
}

最后在onSurfaceDestroyed()中进行空验证:

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    if(this.camera != null) {
        this.camera.stopPreview();
        this.camera.release();
        this.camera = null;
    }

现在按下主页按钮时没有任何问题,或者按下后退按钮,我确保每次通过onRestart(),关闭后和onStop i时相机都设置为空确保标志isSurfaceCreated设置为false。