android:相机 onPause/onResume 问题 [英] android: camera onPause/onResume issue
问题描述
我在使用 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, 410-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):未知错误:010-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();相机=空;}}}
这就是我最终 100% 修复它的方法(在我尝试过的所有设备上工作,包括 Galaxy S):
我在 onResume 上销毁了camer预览对象并一起重新实例化(就像在启动时一样).更多细节在这里:
I have some troubles with the onPause() onResume() camera live cycle: Camera with preview, and taking photos works totally fine. With one exceptions:
I start the app, click the home button, switch back to the app and take another shot.
Result: shuttercallback is still executed (see code), but jpeg callback isn't anymore! Then my galaxy S vibrates, and the screen stays black, since startPreview() is not re-triggered after jpegCallback. The stack trace is far from usefull for me. Strange thing is that this only happens on my Galaxy S, not on the emulator. I have really no clue how to move on :/ Anyone has an idea what could be usefull?
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 ...
Here is my (shortened) code:
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); // Hide the window title. 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; } } // Called when shutter is opened ShutterCallback shutterCallback = new ShutterCallback() { // public void onShutter() { Log.d(TAG, "onShutter'd"); } }; // Handles data for raw picture PictureCallback rawCallback = new PictureCallback() { // public void onPictureTaken(byte[] data, Camera camera) { Log.d(TAG, "onPictureTaken - raw"); } }; // Handles data for jpeg picture 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) { } }); } }
/** * order of execution: * openCamera() * onMeasure() * onLayout() * onMeasure() * onLayout() * surfaceCreated() * surfaceChanged() * onMeasure() * onLayout() * onMeasure() * @author stephan * */ 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; // the size of this view. gets set in 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()"); // We purposely disregard child measurements because act as a // wrapper to a SurfaceView that centers the camera preview instead // of stretching it. 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 setCameraPreviewSize() { Camera.Parameters parameters = camera.getParameters(); if(parameters.getPreviewSize() != this.getOptimalPreviewSize()){ parameters.setPreviewSize(this.getOptimalPreviewSize().width, this.getOptimalPreviewSize().height); this.camera.setParameters(parameters); } } private void setCameraPictureSize() { Camera.Parameters parameters = this.camera.getParameters(); if(parameters.getPictureSize() != this.getOptimalCameraPictureSize()){ parameters.setPictureSize(getOptimalCameraPictureSize().width, getOptimalCameraPictureSize().height); this.camera.setParameters(parameters); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { cameraActivity.log("onLayout()"); if (changed && getChildCount() > 0 && this.camera != null) { final View child = 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()); } } private Size getOptimalPreviewSize() { if(optimalPreviewSize == null){ //calculate optimal preview size } return optimalPreviewSize; } private Size getOptimalCameraPictureSize() { if(optimalPictureSize == null){ //calculate optimal image size } return optimalPictureSize; } // Called once the holder is ready public void surfaceCreated(SurfaceHolder holder) { // // The Surface has been created, acquire the camera and tell it where // to draw. cameraActivity.log("surfaceCreated()"); try { if (this.camera != null) { this.camera.setPreviewDisplay(holder); } } catch (IOException exception) { Log.e(TAG, "IOException caused by setPreviewDisplay()", exception); } } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { cameraActivity.log("surfaceChanged()"); if (camera != null) { Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewSize(getOptimalPreviewSize().width, getOptimalPreviewSize().height); requestLayout(); camera.setParameters(parameters); camera.startPreview(); } } public void surfaceDestroyed(SurfaceHolder holder) { // cameraActivity.log("surfaceDestroyed()"); if(this.camera != null){ camera.stopPreview(); } } public void releaseCamera(){ cameraActivity.log("releaseCamera()"); if (camera != null) { camera.stopPreview(); camera.setPreviewCallback(null); camera.release(); camera = null; } } }
This is how I fixed it 100%, finally (working on every device I tried it on, including Galaxy S):
I destroyed the camere preview object onResume and reinstantiated all together (like on startup). More details here:
android: I get no stacktrace, phone just hangs
这篇关于android:相机 onPause/onResume 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!