在屏幕旋转后调用Camera.Release()后,正在使用摄像头 [英] Camera is being used after Camera.release() was called after screen rotation
本文介绍了在屏幕旋转后调用Camera.Release()后,正在使用摄像头的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一款可以在计时器上拍照的应用程序。通常情况下,它工作得很好,除了在相机休眠时旋转屏幕的情况。谁能告诉我为什么它在睡眠状态下旋转后无法拍照?
正常情况下,当摄像机进入睡眠状态并被唤醒时,它会执行...
@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()、Surface eChanged()、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();
}
这不是完整的代码。这段代码确实会产生一些次要的图像格式错误,但它仍然说明了这个问题。为了简单起见,我去掉了一些东西。主要问题是,当它试图在休眠状态下旋转后拍摄一张照片时,它会返回一个错误"Camera is be Used After Camera.Release()Is Call Call Camera.Release()is Used After Camera.Release()"。为什么会这样?
推荐答案
这真的是早该来了,但由于我一分钟前设法解决了我的一个类似问题,我想我应该为您和其他可能正在拼命搜索Stack的人贡献自己的力量。
因此,当您旋转设备时,您调用的是onPause和onDestroy,在那里您正在释放相机。我注意到您的onResume中确实有camera.open(),没有查看与曲面相关的代码,我无法进行评论。以下是对我有效的方法。
首先,CameraPview
`
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
try {
this.mCamera.setPreviewDisplay(surfaceHolder);
this.mCamera.startPreview();
} catch (Exception e) {
}
}
public void surfaceCreated(SurfaceHolder surfaceHolder) {
try {
//TODO we need this here too because on SurfaceCreated we always need to open the camera, in case its released
this.mCamera.setPreviewDisplay(surfaceHolder);
this.mCamera.setDisplayOrientation(90);
//this.mCamera.startPreview();
} catch (IOException e) {
}
}
接下来,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;
}
}
这篇关于在屏幕旋转后调用Camera.Release()后,正在使用摄像头的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文