方法调用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){ } }