0

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

调用 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 回调:

@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 崩溃,之前是相反的,提前谢谢在这件事上有任何帮助

4

1 回答 1

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() 现在的样子,我添加了对在棒棒糖、棉花糖和牛轧糖中测试的大多数现代 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() 时设置为 null,在关闭后,在 onStop 中我确保标志 isSurfaceCreated设置为假。

于 2017-09-29T14:33:00.100 回答