在屏幕旋转后调用Camera.release()后正在使用相机

时间:2016-12-02 18:17:51

标签: android camera rotation sleep

我有一个应用程序,可以在计时器上拍照。通常它工作正常,除非在相机睡眠时旋转屏幕。任何人都可以告诉我为什么它在睡眠中旋转后无法拍照?

通常情况下,当相机进入睡眠状态并唤醒时,它会执行......

@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();
}

然而,当相机在睡眠状态下旋转后唤醒时,它首先执行onResume(),surfaceChanged(),onPause(),onStop(空),onDestroy(空),然后执行以下操作:

 import UIKit

 class CustomImagePageControl: UIPageControl {

   let activeImage:UIImage = UIImage(named: "SelectedPage")!
   let inactiveImage:UIImage = UIImage(named: "UnselectedPage")!

   override func awakeFromNib() {
         super.awakeFromNib()

         self.pageIndicatorTintColor = UIColor.clear
         self.currentPageIndicatorTintColor = UIColor.clear
         self.clipsToBounds = false
    }

    func updateDots() {
         var i = 0
         for view in self.subviews {
             if let imageView = self.imageForSubview(view) {
                 if i == self.currentPage {
                     imageView.image = self.activeImage
                 } else {
                     imageView.image = self.inactiveImage
                 }
                 i = i + 1
             } else {
                 var dotImage = self.inactiveImage
                 if i == self.currentPage {
                     dotImage = self.activeImage
                 }
                 view.clipsToBounds = false
                 view.addSubview(UIImageView(image:dotImage))
                 i = i + 1
             }
         }
     }

     fileprivate func imageForSubview(_ view:UIView) -> UIImageView? {
         var dot:UIImageView?

         if let dotImageView = view as? UIImageView {
             dot = dotImageView
         } else {
             for foundView in view.subviews {
                 if let imageView = foundView as? UIImageView {
                     dot = imageView
                     break
                 }
             }
         }

         return dot
     }
 }

这不是完整的代码。此代码确实产生一些次要的图像格式错误,但它仍然证明了这个问题。为简单起见,我已经删除了一些东西。主要问题是,当它在睡眠状态下旋转后尝试拍照时会返回错误&#34; Camera.release()被调用后会使用相机&#34;。这是为什么?

1 个答案:

答案 0 :(得分:0)

这真的是过期的,但是当我在一分钟前设法解决了我的类似问题时,我想我会为自己和其他任何可能拼命搜索Stack的人做出贡献。

因此,当您旋转设备时,您正在调用onPause和onDestroy,即释放相机。我注意到你的onResume中有camera.open(),没有看你的表面相关代码,我无法评论。这对我有用。

首先是cameraPreview

`

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;
    }
}