我在onPause()和onResume()相机生命周期的处理上遇到了一些问题:
使用预览的相机以及拍照功能都可以正常工作。但有一个例外:
当我启动应用程序,点击主屏幕键,切换回应用程序并再次拍摄时,会发生某些问题。
结果:快门回调仍然被执行(请参见代码),但JPEG回调不再执行! 然后我的Galaxy S手机会振动,而屏幕会一直保持黑色,因为在jpegCallback之后并未重新启动startPreview()。对我来说,堆栈跟踪远非有用。奇怪的是,这只发生在我的Galaxy S手机上,而不是模拟器上。我真的不知道该怎么办了:/有人有什么好的想法吗?10-28 18:59:40.649: ERROR/SecCamera(4291): SetRotate(angle(0)) 10-28 18:59:40.649: ERROR/CameraHardwareSec(4291): ====setParameters processingmethod = (null) 10-28 18:59:40.649: ERROR/SecCamera(4291): setRecordingSize(width(800), height(480)) 10-28 18:59:40.673: ERROR/SecCamera(4291): SetRotate(angle(0)) 10-28 18:59:40.673: ERROR/CameraHardwareSec(4291): ====setParameters processingmethod = (null) 10-28 18:59:40.673: ERROR/SecCamera(4291): setRecordingSize(width(800), height(480)) 10-28 18:59:40.692: ERROR/SecCamera(4291): SetRotate(angle(0)) 10-28 18:59:40.692: ERROR/CameraHardwareSec(4291): ====setParameters processingmethod = (null) 10-28 18:59:40.692: ERROR/SecCamera(4291): setRecordingSize(width(800), height(480)) 10-28 18:59:40.712: ERROR/SecCamera(4291): SetRotate(angle(0)) 10-28 18:59:40.712: ERROR/CameraHardwareSec(4291): ====setParameters processingmethod = (null) 10-28 18:59:40.712: ERROR/SecCamera(4291): setRecordingSize(width(800), height(480)) 10-28 18:59:40.751: ERROR/CameraHardwareSec(4291): stopPreview() 10-28 18:59:40.751: ERROR/SecCamera(4291): cancelAutofocus() 10-28 18:59:40.751: ERROR/SecCamera(4291): cancelAutofocus() end, 0, 4 10-28 18:59:40.768: ERROR/SecCamera(4291): stopPreview() 10-28 18:59:40.768: ERROR/SecCamera(4291): fimc_v4l2_streamoff() 10-28 18:59:40.797: ERROR/CameraHardwareSec(4291): stopPreview() end 10-28 18:59:41.622: ERROR/SecCamera(4291): fimc_v4l2_streamoff() 10-28 18:59:46.536: ERROR/dalvikvm(2993): Failed to write stack traces to /data/anr/traces.txt (2775 of 2970): Unknown error: 0 10-28 18:59:46.540: ERROR/dalvikvm(2919): Failed to write stack traces to /data/anr/traces.txt (-1 of 3414): Math result not representable 10-28 18:59:46.610: ERROR/dalvikvm(3044): Failed to write stack traces to /data/anr/traces.txt (3354 of 7154): Math result not representable ...
以下是我(精简后的)代码:
public class CameraActivity extends Activity implements MenuViewCallback, CutoutPathManagerCallback { public static final String TAG = "CutoutCamera"; Preview preview; OverlayView overlay; static MenuView menuView;
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
// 隐藏窗口标题。 requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
...
preview = (Preview) this.findViewById(R.id.preview); ... }
...
@Override protected void onResume() { super.onResume(); this.log("onResume()"); preview.openCamera(); }
@Override protected void onPause() { super.onPause(); this.log("onPause()"); if (preview.camera != null) { preview.camera.release(); preview.camera = null; } }
// 当快门打开时调用 ShutterCallback shutterCallback = new ShutterCallback() { // public void 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"); ... } };
@Override public void shootButtonClicked() { preview.camera.takePicture(shutterCallback, rawCallback, jpegCallback); }
@Override public void focusButtonClicked() { preview.camera.autoFocus(new Camera.AutoFocusCallback() { public void onAutoFocus(boolean success, Camera camera) {
} }); } }
/** * 执行顺序: * openCamera() * onMeasure() * onLayout() * onMeasure() * onLayout() * surfaceCreated() * surfaceChanged() * onMeasure() * onLayout() * onMeasure() * */ class Preview extends ViewGroup implements SurfaceHolder.Callback { // private static final String TAG = "Preview";
SurfaceHolder mHolder; // public Camera camera; // private List supportedPreviewSizes; private Size previewSize; SurfaceView mSurfaceView; CameraActivity cameraActivity; int l2 = 0, t2 = 0, r2 = 0, b2 = 0; int padding = 20; Size optimalPreviewSize, optimalPictureSize; // 此视图的大小。在 onMeasure() 中设置。 int fullWidth, fullHeight;
public Preview(Context context) { super(context); init(context); }
public Preview(Context context, AttributeSet attrs) { super(context, attrs); init(context); }
public Preview(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context); }
private void init(Context context) { setKeepScreenOn(true); cameraActivity = (CameraActivity) context; mSurfaceView = new SurfaceView(context); addView(mSurfaceView);
mHolder = mSurfaceView.getHolder(); // mHolder.addCallback(this); // mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // } ...
public void openCamera() { cameraActivity.log("openCamera()"); if (this.camera == null) { cameraActivity.log("Camera.open()"); this.camera = Camera.open();
//supportedPreviewSizes = camera.getParameters().getSupportedPreviewSizes(); requestLayout(); // -> onMeassure() -> onLayout() } }
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { cameraActivity.log("onMeasure()");
// 我们故意忽略子视图的测量,因为它作为一个包装器, // 将相机预览居中而不是拉伸它。 fullWidth = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec); fullHeight = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec); setMeasuredDimension(fullWidth, fullHeight);
if(this.camera != null){ cameraActivity.log("fullSize:"+fullWidth+"x"+fullHeight); this.setCameraPreviewSize(); this.setCameraPictureSize(); } }
private void calcScaledPreviewSize(){ ... }
...
private void setCameraPreview