方法调用release()exception后无法使用android相机继续
在开发相机应用程序时,我遇到了一个exception,只有当我切换到其他应用程序( onPause()
为我的应用程序)时发生的exception。
01-15 17:22:15.017: E/AndroidRuntime(14336): FATAL EXCEPTION: main 01-15 17:22:15.017: E/AndroidRuntime(14336): java.lang.RuntimeException: Method called after release() 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.hardware.Camera.setPreviewDisplay(Native Method) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.hardware.Camera.setPreviewDisplay(Camera.java:357) 01-15 17:22:15.017: E/AndroidRuntime(14336): at com.sora.cbir.yuki.image.leaf.CameraPreview.surfaceCreated(CameraPreview.java:32) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.SurfaceView.updateWindow(SurfaceView.java:551) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:213) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.View.dispatchWindowVisibilityChanged(View.java:4075) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:742) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:742) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:742) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:742) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.ViewRoot.performTraversals(ViewRoot.java:858) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.view.ViewRoot.handleMessage(ViewRoot.java:1995) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.os.Handler.dispatchMessage(Handler.java:99) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.os.Looper.loop(Looper.java:150) 01-15 17:22:15.017: E/AndroidRuntime(14336): at android.app.ActivityThread.main(ActivityThread.java:4389) 01-15 17:22:15.017: E/AndroidRuntime(14336): at java.lang.reflect.Method.invokeNative(Native Method) 01-15 17:22:15.017: E/AndroidRuntime(14336): at java.lang.reflect.Method.invoke(Method.java:507) 01-15 17:22:15.017: E/AndroidRuntime(14336): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849) 01-15 17:22:15.017: E/AndroidRuntime(14336): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607) 01-15 17:22:15.017: E/AndroidRuntime(14336): at dalvik.system.NativeStart.main(Native Method)
我做了一些调查,发现我需要补充
mCamera.setPreviewCallback(null);
作为Android相机堆栈的解决方法
我的onPause()
现在看起来像这样:
@Override protected void onPause() { super.onPause(); try { // release the camera immediately on pause event //releaseCamera(); mCamera.stopPreview(); mCamera.setPreviewCallback(null); mCamera.release(); mCamera = null; } catch(Exception e) { e.printStackTrace(); } }
和我的onResume()
:
@Override protected void onResume() { super.onResume(); try { mCamera.setPreviewCallback(null); mCamera = getCameraInstance(); //mCamera.setPreviewCallback(null); mPreview = new CameraPreview(Imageupload.this, mCamera);//set preview preview.addView(mPreview); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage()); } } }
最后是我的getCameraInstance()
方法:
public Camera getCameraInstance(){ Camera camera = null; try { camera = Camera.open(); // attempt to get a Camera instance } catch (Exception e){ // Camera is not available (in use or does not exist) } Camera.Parameters parameters = camera.getParameters(); //mPreviewSize = getBestPreviewSize(parameters, wt, ht); //mPictureSize = getBestPictureSize(parameters, wt, ht); //Shift W & H => if camera rotates 90 deg mPreviewSize = getOptimalPreviewSize(parameters, wt, ht); //original => wt,ht mPictureSize = getOptimalPictureSize(parameters, wt, ht); //original => wt,ht Log.d("CAMERA", "SCREEN RESOLUTION H: "+ht); Log.d("CAMERA", "SCREEN RESOLUTION W: "+wt); Log.d("CAMERA", "PREVIEW RESOLUTION H: "+mPreviewSize.height); Log.d("CAMERA", "PREVIEW RESOLUTION W: "+mPreviewSize.width); Log.d("CAMERA", "PICTURE RESOLUTION H: "+mPictureSize.height); Log.d("CAMERA", "PICTURE RESOLUTION W: "+mPictureSize.width); //set preview size based on device screen parameters.setPreviewSize(mPreviewSize.width, mPreviewSize.height); //set picture size based on device screen parameters.setPictureSize(mPictureSize.width, mPictureSize.height); //set output camera mode parameters.setPictureFormat(PixelFormat.JPEG); //set focous mode parameters.setFocusMode(FOCUS_MODE_AUTO); //set flash mode parameters.setFlashMode("auto"); List<int[]> fps = parameters.getSupportedPreviewFpsRange(); //System.out.println("FPS size: " +fps.size()); //System.out.println("MAX FPS:"+(fps.get(fps.size()-1)[1])/1000); //log min and max camera supported fps Log.d("CAMERA", "CAMERA MAX FPS: "+(fps.get(fps.size()-1)[1])/1000); Log.d("CAMERA", "CAMERA MIN FPS: "+(fps.get(fps.size()-1)[0])/1000); if(camera_fps) { parameters.setPreviewFpsRange(fps.get(fps.size()-1)[1], fps.get(fps.size()-1)[1]); } //set camera parameters camera.setParameters(parameters); Toast.makeText(getApplicationContext(), "Your device are capable of previewing @" + fps.get(fps.size()-1)[1]/1000+"fps!",Toast.LENGTH_SHORT).show(); return camera; // returns null if camera is unavailable }
任何想法如何解决这个问题?
我有同样的问题。 mCamera.setPreviewCallback(null);
没有帮助。 在我的活动中,我已经添加了这个releaseCamera
:
mPreview.getHolder().removeCallback(mPreview);
现在它工作。
@ ookami.kb解决scheme也为我工作,以及@srunni评论。
public void onPause() { super.onPause(); if (mCamera != null) { mCamera.setPreviewCallback(null); mPreview.getHolder().removeCallback(mPreview); mCamera.release(); } }
我也删除了onDestroy方法。
该文件清楚地说, camera.release()
释放所有的相机资源。 在这个通话之后,相机参考不能再使用了。
如果你想再次使用相机,你必须通过open(int)
方法来获取它。
这一切都在相机文档中描述。
要正确恢复,您需要这样做:
@Override public void onResume() { super.onResume(); // Get the Camera instance as the activity achieves full user focus if (mCamera == null) { initializeCamera(); // Local method to handle camera initialization } } protected void initializeCamera(){ // Get an instance of Camera Object mCamera = getCameraInstance(); // create a basic camera preview class that can be included in a View layout. mPreview=new CameraPreview(this,mCamera); //add your preview class to the FrameLayout element. preview.addView(mPreview); //Trigger capturing an image by calling the Camera.takePicture() method. captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // get an image from the camera mCamera.takePicture(null, null, mPicture); } } ); }
也只是提醒,在oncreate()除了定义FrameLayout预览和buttoncaptureButton。
@Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { this.getHolder().removeCallback(this); mCamera.stopPreview(); mCamera.release(); mCamera = null; Log.e("surfaceDestroyed", "surfaceDestroyed"); }
并在Resumefunction中重新初始化摄像机。
添加到okambi的答案。
当你恢复时,这个function会搞乱一切。
public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } }
try {}不捕获抛出的exception。 也就是说,mCamera不存在,然后当它试图调用setPreviewDisplay(持有人)时,有一个崩溃。
所以通过删除callback,这个surfaceCreated不会被调用,并避免了崩溃。
这是谷歌非常差的文件。
我面临同样的问题,我解决了 – 添加mCamera = null; 在Preview类的SurfaceDestroyed(SurfaceHolder holder)方法中。
public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when we return, so stop the preview. if (mCamera != null) { mCamera.stopPreview(); mCamera.release(); mCamera = null; } }
和 – 添加
camera = Camera.open(); camera.startPreview(); params = camera.getParameters(); preview.setCamera(camera);
在我的CameraActivity的OnResume()方法中。
如果你得到:
尝试调用虚拟方法'void android.hardware.Camera.setPreviewCallback(android.hardware.Camera $ PreviewCallback)'上的空对象引用
我同意@ ookami.kb – mCamera.setPreviewCallback(null);
还不够,后面还加上这个:
mCameraView.getHolder().removeCallback(mCameraView);
我已经放了
mPreview.getHolder().removeCallback(mPreview);
之间。
mCamera.setPreviewCallback(null);
和
mCamera.release();
它为我工作。
@Override protected void onPause() { super.onPause(); this.saveTextEdits(); try { mCamera.stopPreview(); mCamera.setPreviewCallback(null); **mPreview.getHolder().removeCallback(mPreview);** mCamera.release(); mCamera = null; }catch (Exception e){ } }
- AVFoundation,如何captureStillImageAsynchronouslyFromConnectionclosures快门声音?
- SurfaceHoldercallback如何与Activity生命周期相关?
- Android:在Android相机预览上叠加
- 将使用相机拍摄的照片捕获并存储到本地数据库/ PhoneGap / Cordova / iOS中
- 在Android中使用相机活动
- 列出Android中的所有相机图像
- 将图像叠加到相机预览SurfaceView上
- Android – 通过Intent将照片和自定义名称保存到自定义目的地
- 有没有办法要求用户访问相机访问后,他们已经否认了iOS 8?