Android 摄影机在摄影机之后使用。在屏幕旋转后调用release()

Android 摄影机在摄影机之后使用。在屏幕旋转后调用release(),android,camera,rotation,sleep,Android,Camera,Rotation,Sleep,我有一个用定时器拍照的应用程序。正常情况下,它可以正常工作,除非在相机睡觉时旋转屏幕。有人能告诉我为什么它在睡眠中旋转后不能拍照吗 通常,当相机进入睡眠状态并醒来时,它会执行 @Override protected void onPause() { super.onPause(); camera.stopPreview(); camera.release(); //camera = null; //this give me a null object messa

我有一个用定时器拍照的应用程序。正常情况下,它可以正常工作,除非在相机睡觉时旋转屏幕。有人能告诉我为什么它在睡眠中旋转后不能拍照吗

通常,当相机进入睡眠状态并醒来时,它会执行

@Override
protected void onPause() {
    super.onPause();
    camera.stopPreview();
    camera.release();
    //camera = null;  //this give me a null object message
}

@Override
protected void onResume() {
    super.onResume();
    camera = Camera.open(cameraId);
    setCameraDisplayOrientation();
    startCameraPreview(surfaceHolder, surfaceView.getWidth(), surfaceView.getHeight());
}
但是,当它在睡眠中旋转相机后醒来时,它首先执行onResume()、surfacechange()、onPause()、onStop(空)、onDestroy(空),然后执行以下操作:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    surfaceView = (SurfaceView) findViewById(R.id.surface);
    surfaceHolder = surfaceView.getHolder();
    surfaceHolder.addCallback(this);  
} 

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

@Override
protected void onResume() {
    super.onResume();
    camera = Camera.open(cameraId);
    setCameraDisplayOrientation();
    startCameraPreview(surfaceHolder, surfaceView.getWidth(), surfaceView.getHeight());
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    camera.stopPreview();
    setCameraDisplayOrientation();
    startCameraPreview(holder, w, h);
}

public void setCameraDisplayOrientation() {
    deviceRotation = getWindowManager().getDefaultDisplay().getRotation();
    int degrees = 0;
    switch(deviceRotation) {
        case Surface.ROTATION_0: degrees=0; break;//vertical
        case Surface.ROTATION_90: degrees=-90; break; //left side
        case Surface.ROTATION_180: degrees=180; break; //upside-down
        case Surface.ROTATION_270: degrees=90; break; //right side
    }
    Camera.CameraInfo info = new Camera.CameraInfo();
    Camera.getCameraInfo(cameraId, info);
    displayRotation = info.orientation + degrees;
    camera.setDisplayOrientation(displayRotation); //changes orientation of camera's display
}

public void startCameraPreview(SurfaceHolder holder, int w, int h) {
    double targetRatio = 0;
    switch(deviceRotation) {
        case Surface.ROTATION_0: targetRatio = (double)w/(double)h; break; //vertical
        case Surface.ROTATION_90: targetRatio = (double)h/(double)w; break; //left side
        case Surface.ROTATION_180: targetRatio = (double)w/(double)h; break; //upside-down
        case Surface.ROTATION_270: targetRatio = (double)h/(double)w; break; //right side
    }
    Camera.Parameters p = camera.getParameters();
    List<Camera.Size> previewSizes = p.getSupportedPreviewSizes();
    int optimal_h = 2; //always refers to short length in PreviewSizes
    int optimal_w = 1; //always refers to long length in PreviewSizes
    for(Camera.Size previewSize : previewSizes) {
        if (Math.abs((double)previewSize.height/(double)previewSize.width - targetRatio) <
                Math.abs((double)optimal_h/(double)optimal_w - targetRatio)) {
            optimal_h = previewSize.height;
            optimal_w = previewSize.width;
        }
    }
    p.setPreviewSize(optimal_w, optimal_h); //defines ratio of image preview - sizes can be larger than actual display
    p.set("rotation", displayRotation); //required to orient final jpeg file correctly
    camera.setParameters(p);
    ViewGroup.LayoutParams surfaceParams = surfaceView.getLayoutParams();
    switch(deviceRotation) { //aligns ratio of surface view to ratio of image preview
        case Surface.ROTATION_0:
            surfaceParams.width=ViewGroup.LayoutParams.MATCH_PARENT;
            surfaceParams.height=(int)(w*(double)optimal_w/(double)optimal_h);
            break; //vertical
        case Surface.ROTATION_90:
            surfaceParams.width=(int)(h*(double)optimal_w/(double)optimal_h);
            surfaceParams.height=ViewGroup.LayoutParams.MATCH_PARENT;
            break; //left side
        case Surface.ROTATION_180:
            surfaceParams.width=ViewGroup.LayoutParams.MATCH_PARENT;
            surfaceParams.height=(int)(w*(double)optimal_w/(double)optimal_h);
            break; //upside-down
        case Surface.ROTATION_270:
            surfaceParams.width=(int)(h*(double)optimal_w/(double)optimal_h);
            surfaceParams.height=ViewGroup.LayoutParams.MATCH_PARENT;
            break; //right side
    }
    surfaceView.setLayoutParams(surfaceParams);
    camera.setPreviewDisplay(holder); //required to startPreview
    camera.startPreview();
}
@覆盖
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surfaceView=(surfaceView)findViewById(R.id.surface);
surfaceHolder=surfaceView.getHolder();
surfaceHolder.addCallback(this);
} 
@凌驾
受保护的void onStart(){
super.onStart();
}
@凌驾
受保护的void onResume(){
super.onResume();
摄像机=摄像机。打开(摄像机阵列);
setCameraRadisPlayOrientation();
startCameraPreview(surfaceHolder、surfaceView.getWidth()、surfaceView.getHeight());
}
@凌驾
公共无效表面更改(表面持有人,整数格式,整数w,整数h){
camera.stopPreview();
setCameraRadisPlayOrientation();
startCameraPreview(支架,w,h);
}
public void setCameraRadisPlayOrientation(){
deviceRotation=getWindowManager().getDefaultDisplay().getRotation();
整数度=0;
开关(设备旋转){
case Surface.ROTATION_0:degrees=0;break;//垂直
case Surface.ROTATION_90:degrees=-90;break;//左侧
case Surface.ROTATION_180:degrees=180;break;//倒置
外壳表面旋转270度=90度;断裂;//右侧
}
Camera.CameraInfo info=新建Camera.CameraInfo();
Camera.getCameraInfo(cameraId,info);
显示旋转=信息方向+角度;
setDisplayOrientation(displayRotation);//更改相机显示的方向
}
公共无效startCameraPreview(表面持有人,内部w,内部h){
双目标率=0;
开关(设备旋转){
case Surface.ROTATION_0:targetRatio=(双)w/(双)h;break;//垂直
外壳表面旋转90:targetRatio=(双)h/(双)w;断裂;//左侧
case Surface.ROTATION_180:targetRatio=(双)w/(双)h;break;//倒置
外壳表面旋转度:targetRatio=(双)h/(双)w;断裂;//右侧
}
Camera.Parameters p=Camera.getParameters();
List previewSizes=p.getSupportedPreviewSizes();
int optimal_h=2;//在PreviewSizes中总是指短长度
int optimal_w=1;//在PreviewSizes中总是指长长度
用于(Camera.Size previewSize:previewSizes){
if(Math.abs((双精度)previewSize.height/(双精度)previewSize.width-targetRatio)<
数学abs((双)最优(双)最优目标){
最佳_h=previewSize.height;
最佳宽度=previewSize.width;
}
}
p、 setPreviewSize(optimal_w,optimal_h);//定义图像预览的比率-大小可以大于实际显示
p、 设置(“旋转”,displayRotation);//正确定向最终jpeg文件所需
摄像机参数设置(p);
ViewGroup.LayoutParams surfaceParams=surfaceView.getLayoutParams();
开关(设备旋转){//将曲面视图的比率与图像预览的比率对齐
外壳表面旋转0:
surfaceParams.width=ViewGroup.LayoutParams.MATCH\u父项;
曲面图高度=(int)(w*(双)最优w/(双)最优h);
break;//垂直
外壳表面旋转90度:
曲面图宽度=(int)(h*(双)最优w/(双)最优h);
surfaceParams.height=ViewGroup.LayoutParams.MATCH\u父项;
break;//左侧
外壳表面旋转180度:
surfaceParams.width=ViewGroup.LayoutParams.MATCH\u父项;
曲面图高度=(int)(w*(双)最优w/(双)最优h);
打破;//倒置
外壳表面。旋转_270:
曲面图宽度=(int)(h*(双)最优w/(双)最优h);
surfaceParams.height=ViewGroup.LayoutParams.MATCH\u父项;
break;//右侧
}
surfaceView.setLayoutParams(surfaceParams);
camera.setPreviewDisplay(支架);//需要启动预览
camera.startPreview();
}

这不是完整的代码。这段代码确实会产生一些小的图像格式错误,但它仍然演示了这个问题。为了简单起见,我删去了一些东西。主要问题是,当它在睡眠中旋转后尝试拍照时,返回一个错误“Camera在调用Camera.release()后正在使用Camera”。这是为什么?

这真的是太晚了,但当我在一分钟前设法解决了我的一个类似问题时,我想我会为你自己和其他可能拼命搜索堆栈的人的利益做出贡献

因此,当您旋转设备时,您正在调用暂停和onDestroy,在那里您正在释放相机。我注意到你的简历中确实有camera.open(),没有看一下你的表面相关代码,我无法评论。这就是对我有用的东西

首先,是检讨

`

接下来是CameraActivity的生命周期代码

 @Override
public void onResume() {
    super.onResume();
   try{
       mCamera = openFrontFacingCameraGingerbread();
      // Add to Framelayout
       this.mCameraPreview = new CameraPreview(this, this.mCamera);
        mImage.removeAllViews();
       this.mImage.addView(this.mCameraPreview);

   }catch (RuntimeException ex){

    }



}


@Override
public void onPause() {
    super.onPause();
    captureButton.setText("Begin Capture");
    if(CameraActivity.this.timer !=null) {
        CameraActivity.this.timer.cancel();
        CameraActivity.this.timer.purge();
        CameraActivity.this.timer = null;
    }
    if (mCamera != null) {
        mCamera.setPreviewCallback(null);
        mCameraPreview.getHolder().removeCallback(mCameraPreview);
        mCamera.release();
        mCamera = null;
    }


}


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

private void releaseCameraAndPreview() {

    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
    if(mCameraPreview != null){
        mCameraPreview.destroyDrawingCache();
        mCameraPreview.mCamera = null;
    }
}

这真的是迟到了,但当我在一分钟前设法解决了我的一个类似问题时,我想我会为你自己和其他可能正在拼命搜索堆栈的人的利益做出贡献

因此,当您旋转设备时,您正在调用暂停和onDestroy,在那里您正在释放相机。我注意到你的简历中确实有camera.open(),没有看一下你的表面相关代码,我无法评论。这就是对我有用的东西

首先,是检讨

`

接下来是CameraActivity的生命周期代码

 @Override
public void onResume() {
    super.onResume();
   try{
       mCamera = openFrontFacingCameraGingerbread();
      // Add to Framelayout
       this.mCameraPreview = new CameraPreview(this, this.mCamera);
        mImage.removeAllViews();
       this.mImage.addView(this.mCameraPreview);

   }catch (RuntimeException ex){

    }



}


@Override
public void onPause() {
    super.onPause();
    captureButton.setText("Begin Capture");
    if(CameraActivity.this.timer !=null) {
        CameraActivity.this.timer.cancel();
        CameraActivity.this.timer.purge();
        CameraActivity.this.timer = null;
    }
    if (mCamera != null) {
        mCamera.setPreviewCallback(null);
        mCameraPreview.getHolder().removeCallback(mCameraPreview);
        mCamera.release();
        mCamera = null;
    }


}


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

private void releaseCameraAndPreview() {

    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
    if(mCameraPreview != null){
        mCameraPreview.destroyDrawingCache();
        mCameraPreview.mCamera = null;
    }
}