12

我在 onPause() onResume() 相机实时循环中遇到了一些问题:带有预览功能的相机和拍照完全正常。除了一个例外:

我启动应用程序,单击主页按钮,切换回应用程序并拍摄另一张照片。

结果:shuttercallback 仍然执行(参见代码),但 jpeg 回调不再执行!然后我的星系 S 振动,屏幕保持黑色,因为在 jpegCallback 之后没有重新触发 startPreview()。堆栈跟踪对我来说远没有用。奇怪的是,这只发生在我的 Galaxy S 上,而不是模拟器上。我真的不知道如何继续前进:/有人知道什么有用吗?

10-28 18:59:40.649:错误/SecCamera(4291):SetRotate(角度(0))
10-28 18:59:40.649: 错误/CameraHardwareSec(4291): ====setParameters processingmethod = (null)
10-28 18:59:40.649:错误/SecCamera(4291):setRecordingSize(宽度(800),高度(480))
10-28 18:59:40.673:错误/SecCamera(4291):SetRotate(角度(0))
10-28 18:59:40.673: 错误/CameraHardwareSec(4291): ====setParameters processingmethod = (null)
10-28 18:59:40.673:错误/SecCamera(4291):setRecordingSize(宽度(800),高度(480))
10-28 18:59:40.692:错误/SecCamera(4291):SetRotate(角度(0))
10-28 18:59:40.692: 错误/CameraHardwareSec(4291): ====setParameters processingmethod = (null)
10-28 18:59:40.692:错误/SecCamera(4291):setRecordingSize(宽度(800),高度(480))
10-28 18:59:40.712:错误/SecCamera(4291):SetRotate(角度(0))
10-28 18:59:40.712: 错误/CameraHardwareSec(4291): ====setParameters processingmethod = (null)
10-28 18:59:40.712:错误/SecCamera(4291):setRecordingSize(宽度(800),高度(480))
10-28 18:59:40.751: 错误/CameraHardwareSec(4291): stopPreview()
10-28 18:59:40.751: 错误/SecCamera(4291): cancelAutofocus()
10-28 18:59:40.751: 错误/SecCamera(4291): cancelAutofocus() end, 0, 4
10-28 18:59:40.768: 错误/SecCamera(4291): stopPreview()
10-28 18:59:40.768: 错误/SecCamera(4291): fimc_v4l2_streamoff()
10-28 18:59:40.797: 错误/CameraHardwareSec(4291): stopPreview() 结束
10-28 18:59:41.622: 错误/SecCamera(4291): fimc_v4l2_streamoff()
10-28 18:59:46.536:错误/dalvikvm(2993):无法将堆栈跟踪写入 /data/anr/traces.txt(2970 中的 2775):未知错误:0
10-28 18:59:46.540: 错误/dalvikvm(2919): 无法将堆栈跟踪写入 /data/anr/traces.txt (-1 of 3414): 数学结果不可表示
10-28 18:59:46.610: 错误/dalvikvm(3044): 无法将堆栈跟踪写入 /data/anr/traces.txt (3354 of 7154): 数学结果不可表示
...

这是我的(缩短的)代码:

公共类 CameraActivity 扩展 Activity 实现 MenuViewCallback、CutoutPathManagerCallback {
    public static final String TAG = "CutoutCamera";
    预览预览;
    OverlayView 覆盖;
    静态MenuView menuView;

    @覆盖
    公共无效 onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 隐藏窗口标题。
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

        ...

        preview = (Preview) this.findViewById(R.id.preview);
        ...
    }

    ...

    @覆盖
    受保护的无效 onResume() {
        超级.onResume();
        this.log("onResume()");
        预览.openCamera();
    }


    @覆盖
    受保护的无效 onPause() {
        超级.onPause();
        this.log("onPause()");
        if (preview.camera != null) {
            preview.camera.release();
            preview.camera = null;
        }
    }

    // 快门打开时调用
    ShutterCallback shutterCallback = new ShutterCallback() { //
        公共无效 onShutter() {
            Log.d(TAG, "onShutter'd");
        }
    };

    // 处理原始图片的数据
    PictureCallback rawCallback = new PictureCallback() { //
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.d(TAG, "onPictureTaken - raw");
        }
    };

    //处理jpeg图片的数据
    PictureCallback jpegCallback = new PictureCallback() { //
        public void onPictureTaken(byte[] data, Camera camera) {
            Log.d(TAG, "onPictureTaken - jpeg");
            ...
        }
    };

    @覆盖
    公共无效 shootButtonClicked() {
        preview.camera.takePicture(shutterCallback, rawCallback, jpegCallback);
    }

    @覆盖
    公共无效focusButtonClicked(){
        preview.camera.autoFocus(new Camera.AutoFocusCallback() {   
            public void onAutoFocus(布尔成功,相机相机){

            }
        });
    }
}
/**
 * 执行顺序:
 * 开放式摄像头()
 * onMeasure()
 * onLayout()
 * onMeasure()
 * onLayout()
 * 表面创建()
 * 表面变化()
 * onMeasure()
 * onLayout()
 * onMeasure()
 * @作者斯蒂芬
 *
 */
类 Preview 扩展 ViewGroup 实现 SurfaceHolder.Callback { //
    私人静态最终字符串标签=“预览”;

    SurfaceHolder mHolder;//
    公共摄像头摄像头;//
    私有列表supportedPreviewSizes;
    私人尺寸 previewSize;
    SurfaceView mSurfaceView;
    相机活动相机活动;
    int l2 = 0, t2 = 0, r2 = 0, b2 = 0;
    int 填充 = 20;
    尺寸最佳预览尺寸、最佳图片尺寸;
    // 这个视图的大小。在 onMeasure() 中设置
    整型全宽,全高;



    公共预览(上下文上下文){
        超级(上下文);
        初始化(上下文);
    }

    公共预览(上下文上下文,AttributeSet attrs){
        超级(上下文,属性);
        初始化(上下文);
    }

    公共预览(上下文上下文,AttributeSet attrs,int defStyle){
        超级(上下文,属性,defStyle);
        初始化(上下文);
    }

    私人无效初始化(上下文上下文){
        setKeepScreenOn(true);
        cameraActivity = (CameraActivity) 上下文;
        mSurfaceView = new SurfaceView(context);
        addView(mSurfaceView);

        mHolder = mSurfaceView.getHolder(); //
        mHolder.addCallback(this); //
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); //
    }
    ...

    公共无效openCamera(){
        cameraActivity.log("openCamera()");
        如果(this.camera == null){
            cameraActivity.log("Camera.open()");
            this.camera = Camera.open();

            //supportedPreviewSizes = camera.getParameters().getSupportedPreviewSizes();
            请求布局();// -> onMeassure() -> onLayout()
        }
    }


    @覆盖
    受保护的无效onMeasure(int widthMeasureSpec,int heightMeasureSpec){
        cameraActivity.log("onMeasure()");

        // 我们故意忽略子测量,因为充当
        // 封装到以相机预览为中心的 SurfaceView
        // 拉伸它。
        fullWidth = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        fullHeight = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
        setMeasuredDimension(fullWidth, fullHeight);

        如果(this.camera != null){
            cameraActivity.log("fullSize:"+fullWidth+"x"+fullHeight);
            this.setCameraPreviewSize();
            this.setCameraPictureSize();
        }
    }

    私人无效 calcScaledPreviewSize(){
        ...
    }

    ...

    私人无效 setCameraPreviewSize() {
        Camera.Parameters 参数 = camera.getParameters();
        if(parameters.getPreviewSize() != this.getOptimalPreviewSize()){
            参数.setPreviewSize(this.getOptimalPreviewSize().width, this.getOptimalPreviewSize().height);
            this.camera.setParameters(参数);
        }
    }

    私人无效 setCameraPictureSize() {
        Camera.Parameters 参数 = this.camera.getParameters();
        如果(参数。getPictureSize()!= this.getOptimalCameraPictureSize()){
            参数.setPictureSize(getOptimalCameraPictureSize().width, getOptimalCameraPictureSize().height);
            this.camera.setParameters(参数);
        }
    }

    @覆盖
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        cameraActivity.log("onLayout()");
        if (更改 && getChildCount() > 0 && this.camera != null) {
            最终视图子 = getChildAt(0);
            cameraActivity.log("r:"+this.getPreviewRight()+" l:"+this.getPreviewLeft()+" b:"+this.getPreviewBottom()+" t:"+this.getPreviewTop());
            child.layout(this.getPreviewLeft(), this.getPreviewTop(), this.getPreviewRight(), this.getPreviewBottom());
            cameraActivity.initOverlay(this.getPreviewLeft(),this.getPreviewTop(),this.getPreviewRight(),this.getPreviewBottom());
        }
    }
    私人尺寸 getOptimalPreviewSize() {

        if(optimalPreviewSize == null){
            //计算最佳预览尺寸
        }
        返回最佳预览尺寸;
    }

    私人尺寸 getOptimalCameraPictureSize() {

        如果(最佳图片大小 == 空){
            //计算最佳图像尺寸
        }
        返回最佳图片大小;
    }


    // 一旦持有者准备好调用
    public void surfaceCreated(SurfaceHolder holder) { //
        // Surface 已创建,获取相机并告诉它在哪里
        // 绘制。
        cameraActivity.log("surfaceCreated()");
        尝试 {
            if (this.camera != null) {
                this.camera.setPreviewDisplay(holder);
            }
        } 捕捉(IOException 异常){
            Log.e(TAG, "由 setPreviewDisplay() 引起的 IOException", 异常);

        }
    }

    公共无效surfaceChanged(SurfaceHolder持有人,int格式,int w,int h){
        cameraActivity.log("surfaceChanged()");
        如果(相机!= null){

            Camera.Parameters 参数 = camera.getParameters();
            参数.setPreviewSize(getOptimalPreviewSize().width, getOptimalPreviewSize().height);
            请求布局();

            camera.setParameters(参数);
            camera.startPreview();
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) { //
        cameraActivity.log("surfaceDestroyed()");
        如果(this.camera != null){
            camera.stopPreview();
        }
    }

    公共无效释放相机(){
        cameraActivity.log("releaseCamera()");
        如果(相机!= null){
            camera.stopPreview();
            camera.setPreviewCallback(null);
            相机.release();
            相机=空;
        }
    }
}

4

3 回答 3

6

这就是我最终 100% 修复它的方式(在我尝试过的每台设备上工作,包括 Galaxy S):

我销毁了 onResume 上的camer预览对象并一起重新实例化(就像在启动时一样)。更多细节在这里:

android:我没有堆栈跟踪,电话只是挂起

于 2012-01-10T14:56:51.680 回答
4

到达这篇文章有点晚了,但我遇到了类似的问题。首先,如果您使用客户 rom,则可能是相机驱动程序的问题(我的一台 X8 运行 4.0.4)。如果您按下电源按钮将手机置于待机模式并在短时间内将其恢复(有或没有主屏幕锁定),也会存在此问题。在尝试和错误之后,我发现在 super.onPause 之前关闭相机后放置一个短暂的延迟是最好的。我的代码如下。

  @Override
  public void onPause() {
      // Log.d(TAG,"ccp_onPause");
      closeCamera();
      try {
          Thread.sleep(500);
      } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
      }
      super.onPause();
  }

和 closeCamera();

   public void closeCamera() {
      if (mCamera != null) {
          mCamera.stopPreview();
          mCamera.setPreviewCallback(null);
          mCamera.lock();
          mCamera.release();
          mCamera=null;
          requestLayout();
        }
    }
于 2012-07-21T04:23:29.423 回答
2

我的猜测是,您所要做的就是在 Preview 中创建一个 setter 方法来重置相机(在 onPause() 后,预览中的本地相机对象因相机被释放而变得无效,但仍保持 Preview 的其余状态) .

于 2012-05-26T21:43:47.523 回答