java.lang.RuntimeException:takePicture失败
当我连续点击捕获button(没有任何中断),得到运行时exception如何解决这个问题?
如果它不可能,那么我怎么处理这个exception呢?
btnCapture = (ImageButton) findViewById(R.id.btnCapture); final MediaPlayer mp = MediaPlayer.create(CameraLauncherActivity.this, R.raw.button); btnCapture.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // line where getting RuntimeException camera.takePicture(null, null, mPicture); } });
日志:
02-12 14:48:41.580: E/AndroidRuntime(6997): FATAL EXCEPTION: main 02-12 14:48:41.580: E/AndroidRuntime(6997): java.lang.RuntimeException: takePicture failed 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.hardware.Camera.native_takePicture(Native Method) 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.hardware.Camera.takePicture(Camera.java:1126) 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.hardware.Camera.takePicture(Camera.java:1071) 02-12 14:48:41.580: E/AndroidRuntime(6997): at app.cam.shane.CameraLauncherActivity$3.onClick(CameraLauncherActivity.java:116) 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.view.View.performClick(View.java:4223) 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.view.View$PerformClick.run(View.java:17275) 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.os.Handler.handleCallback(Handler.java:615) 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.os.Handler.dispatchMessage(Handler.java:92) 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.os.Looper.loop(Looper.java:137) 02-12 14:48:41.580: E/AndroidRuntime(6997): at android.app.ActivityThread.main(ActivityThread.java:4921) 02-12 14:48:41.580: E/AndroidRuntime(6997): at java.lang.reflect.Method.invokeNative(Native Method) 02-12 14:48:41.580: E/AndroidRuntime(6997): at java.lang.reflect.Method.invoke(Method.java:511) 02-12 14:48:41.580: E/AndroidRuntime(6997): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1036) 02-12 14:48:41.580: E/AndroidRuntime(6997): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:803) 02-12 14:48:41.580: E/AndroidRuntime(6997): at dalvik.system.NativeStart.main(Native Method)
注意: –像在布丁相机 ,他们允许用户连续点击捕捉button,但他们永远不会显示exception,如果你点击50次,它将捕捉10个或更多的图像,每个图像在特定的时间后,但没有显示exception,像我得到我的代码,以同样的方式如何处理这个exception?
完整代码:
@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_camera); setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); preview=(SurfaceView)findViewById(R.id.surface); previewHolder=preview.getHolder(); previewHolder.addCallback(surfaceCallback); previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); btnCapture = (ImageButton) findViewById(R.id.btnCapture); final MediaPlayer mp = MediaPlayer.create(CameraLauncherActivity.this, R.raw.button); btnCapture.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mp.start(); camera.takePicture(null, null, mPicture); } }); @Override public void onResume() { super.onResume(); camera=Camera.open(); } @Override public void onPause() { super.onPause(); if (inPreview) { camera.stopPreview(); } camera.release(); camera=null; inPreview=false; } private Camera.Size getBestPreviewSize(int width, int height, Camera.Parameters parameters) { Camera.Size result=null; for (Camera.Size size : parameters.getSupportedPreviewSizes()) { if (size.width <= width && size.height <= height) { if (result == null) { result=size; } else { int resultArea=result.width * result.height; int newArea=size.width * size.height; if (newArea > resultArea) { result=size; } } } } return(result); } private Camera.Size getSmallestPictureSize(Camera.Parameters parameters) { Camera.Size result=null; for (Camera.Size size : parameters.getSupportedPictureSizes()) { if (result == null) { result=size; } else { int resultArea=result.width * result.height; int newArea=size.width * size.height; if (newArea < resultArea) { result=size; } } } return(result); } SurfaceHolder.Callback surfaceCallback=new SurfaceHolder.Callback(){ public void surfaceCreated(SurfaceHolder holder) { try { camera.setPreviewDisplay(previewHolder); } catch (Throwable t) { Log.e("PreviewDemo-surfaceCallback", "Exception in setPreviewDisplay()", t); Toast.makeText(CameraLauncherActivity.this, t.getMessage(), Toast.LENGTH_LONG).show(); } } public void surfaceChanged(SurfaceHolder holder,int format, int width,int height) { params = camera.getParameters(); params.setFlashMode(Camera.Parameters.FLASH_MODE_ON); Camera.Size size = getBestPreviewSize(width, height, params); Camera.Size pictureSize=getSmallestPictureSize(params); if (size != null && pictureSize != null) { params.setPreviewSize(size.width, size.height); params.setPictureSize(pictureSize.width, pictureSize.height); camera.setParameters(params); camera.startPreview(); inPreview=true; } } public void surfaceDestroyed(SurfaceHolder holder) { } }; PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { pictureFile = getOutputMediaFile(); camera.startPreview(); if (pictureFile == null) { return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { } catch (IOException e) { } } }; static File getOutputMediaFile() { /* yyyy-MM-dd'T'HH:mm:ss.SSSZ */ timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss") .format(new Date()); // file name mediaFile = new File(LoginActivity.mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); return mediaFile; } }
首先,在onPictureTaken中捕获你的exception,留下空的catch部分不是一个好的做法。 然后,我将添加一个标志,防止在保存前一张图片时调用takePicture()。 稍后在onClickbutton中,您将检查是否可以调用takePicture()。
-
声明一个标志作为你的Activity的成员:
private boolean safeToTakePicture = false;
-
在
surfaceChanged()
,只需在调用startPreview()之后将该标志设置为true:camera.startPreview(); safeToTakePicture = true;
-
在
onClick()
监听器中检查标志并拍照,如果可以的话:if (safeToTakePicture) { mp.start(); camera.takePicture(null, null, mPicture); safeToTakePicture = false; }
-
在
onPictureTaken()
,保存图片(并添加exception打印)后,将标志再次设置为true:PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { pictureFile = getOutputMediaFile(); camera.startPreview(); if (pictureFile == null) { //no path to picture, return safeToTakePicture = true; return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { e.printStackTrace(); //<-------- show exception } catch (IOException e) { e.printStackTrace(); //<-------- show exception } //finished saving picture safeToTakePicture = true; } };
注意:正如文档所说, “必须先开始预览才能拍摄照片”。 ,所以可能的增强将是使用setPreviewCallback()来注册将在预览数据可用时调用的callback,并且在调用onPreviewFrame时将标志设置为true。
我也有类似的问题。 后来我发现startPreview
是非常重要的。
_camera.startPreview()
在takePicutre签出这个链接中的点5和6之前是非常重要的。
你忘了在相机上调用startPreview()
吗?
在这里看到更多的信息。
这种方法将帮助你解决这个问题。
private void safeCameraOpen(int id) { try { releaseCameraAndPreview(); mCamera = Camera.open(id); } catch (Exception e) { Log.e(getString(R.string.app_name), "failed to open Camera"); e.printStackTrace(); } } private void releaseCameraAndPreview() { if (mCamera != null) { mCamera.release(); mCamera = null; } }