Android: java.lang.RuntimeException: takePicture failed
Assuming that you want the jpeg saved, you don't need raw callback, so change the call to takePicture() from:
mCamera.takePicture(null, mPicture, mPicture);
to
mCamera.takePicture(null, null, mPicture);
in your onTouchEvent(). This will use jpeg picture callback.
Calling takePicture() also causes the preview to stop, so you might want to call startPreview() again in your onPictureTaken() callback, if you want to take more pictures or have a preview restarted.
Also, in your onTouchEvent(), you might be getting multiple events, so filter for the one that works for you:
@Override
public boolean onTouchEvent(MotionEvent event) {
Toast.makeText(context, "Picture taken", Toast.LENGTH_SHORT).show();
//System.gc(); tried this because it was suggested in a stackoverflow question but it didn't help.
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// A pressed gesture has started, the motion contains the initial starting location
break;
case MotionEvent.ACTION_UP:
// A pressed gesture has finished, the motion contains the final release location
// as well as any intermediate points since the last down or move event.
mCamera.takePicture(null, mPicture, mPicture);
break;
default:
break;
}
return true; //processed
}
If you place takePicture() in ACTION_DOWN, it will be called as soon as you touch the screen, whereas when in ACTION_UP, it will happen when you remove finger. See which one works for you.
MeesterPatat
Updated on June 04, 2022Comments
-
MeesterPatat almost 2 years
I'm am trying to capture an image in the ontouchevent of surfaceview. However, everytime a touch the screen, the app crashes with the following exception:
01-05 21:03:18.500: ERROR/AndroidRuntime(10367): FATAL EXCEPTION: main java.lang.RuntimeException: takePicture failed at android.hardware.Camera.native_takePicture(Native Method) at android.hardware.Camera.takePicture(Camera.java:1126) at android.hardware.Camera.takePicture(Camera.java:1071) at com.test.MotionDetector.CameraSurfaceView.onTouchEvent(CameraSurfaceView.java:107) at android.view.View.dispatchTouchEvent(View.java:7350) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212) at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2470) at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2212) at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2151) at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1480) at android.app.Activity.dispatchTouchEvent(Activity.java:2469) at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2099) at android.view.View.dispatchPointerEvent(View.java:7535) at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:3492) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3424) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4534) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4512) at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4616) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:125) at android.os.Looper.loop(Looper.java:124) at android.app.ActivityThread.main(ActivityThread.java:4921) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1038) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:805) at dalvik.system.NativeStart.main(Native Method)
My code:
package com.nadim.MotionDetector; import android.content.Context; import android.hardware.Camera; import android.os.Environment; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.Toast; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; private Context context; public CameraSurfaceView(Context context, Camera camera) { super(context); this.context = context; mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0 mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } 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("MotionDetector", "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity. } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null) { // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e) { // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e) { Log.d("MotionDetector", "Error starting camera preview: " + e.getMessage()); } } @Override public boolean onTouchEvent(MotionEvent event) { Toast.makeText(context, "Picture taken", Toast.LENGTH_SHORT).show(); //System.gc(); tried this because it was suggested in a stackoverflow question but it didn't help. mCamera.takePicture(null, mPicture, mPicture); return true; //processed } private Camera.PictureCallback mPicture = new Camera.PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(); if (pictureFile == null) { return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d("MotionDetector", "File not found: " + e.getMessage()); } catch (IOException e) { Log.d("MotionDetector", "Error accessing file: " + e.getMessage()); } } }; private static File getOutputMediaFile() { File mediaStorageDir = new File(Environment.getExternalStorageDirectory(), "motiondetect"); if (!mediaStorageDir.exists()) { if (!mediaStorageDir.mkdirs()) { Log.d("MyCameraApp", "failed to create directory"); return null; } } // Create a media file name String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date()); File mediaFile; mediaFile = new File(mediaStorageDir, timeStamp + ".jpg"); return mediaFile; } }
Permissions and features used:
<uses-permission android:name="android.permission.CAMERA"/> <uses-feature android:name="android.hardware.camera"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera.autofocus" /> <uses-feature android:name="android.hardware.camera.flash" />
I don't know why the crash occurs. Many other topic suggest calling Camera.startPreview first. I am doing that, but it doesn't solve the issue.
LogCat before taking picture:
01-05 21:45:57.667: WARN/ActivityManager(754): No content provider found for permission revoke: file:///data/local/tmp/com.test.MotionDetector 01-05 21:45:57.667: WARN/ActivityManager(754): No content provider found for permission revoke: file:///data/local/tmp/com.test.MotionDetector 01-05 21:45:57.687: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=-1: uninstall pkg 01-05 21:45:57.687: INFO/ActivityManager(754): Killing 4264:com.test.MotionDetector/u0a103 (adj 7): stop com.test.MotionDetector 01-05 21:45:57.687: INFO/ActivityManager(754): Force finishing activity ActivityRecord{437a6678 u0 com.test.MotionDetector/.MotionDetectActivity t144} 01-05 21:45:57.697: WARN/InputDispatcher(754): channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)' ~ Consumer closed input channel or an error occurred. events=0x9 01-05 21:45:57.697: ERROR/InputDispatcher(754): channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)' ~ Channel is unrecoverably broken and will be disposed! 01-05 21:45:57.697: WARN/InputDispatcher(754): Attempted to unregister already unregistered input channel '42adff40 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity (server)' 01-05 21:45:57.697: INFO/WindowState(754): WIN DEATH: Window{42adff40 u0 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity} 01-05 21:45:57.757: INFO/PackageManager(754): Running dexopt on: com.test.MotionDetector 01-05 21:45:57.757: INFO/PackageManager(754): Package com.test.MotionDetector codePath changed from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk; Retaining data and using new 01-05 21:45:57.807: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=-1: update pkg 01-05 21:45:57.807: WARN/PackageManager(754): Code path for pkg : com.test.MotionDetector changing from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk 01-05 21:45:57.807: WARN/PackageManager(754): Resource path for pkg : com.test.MotionDetector changing from /data/app/com.test.MotionDetector-1.apk to /data/app/com.test.MotionDetector-2.apk 01-05 21:45:57.937: INFO/ActivityManager(754): Force stopping com.test.MotionDetector appid=10103 user=0: pkg removed 01-05 21:45:57.987: DEBUG/BackupManagerService(754): Received broadcast Intent { act=android.intent.action.PACKAGE_REMOVED dat=package:com.test.MotionDetector flg=0x4000010 (has extras) } 01-05 21:45:58.047: DEBUG/BackupManagerService(754): Received broadcast Intent { act=android.intent.action.PACKAGE_ADDED dat=package:com.test.MotionDetector flg=0x4000010 (has extras) } 01-05 21:45:58.567: INFO/Icing.InternalIcingCorporaProvider(12750): Updating corpora: A: com.test.MotionDetector, C: MAYBE 01-05 21:45:58.647: DEBUG/PackageAddedReceiver(1086): package added com.test.MotionDetector 01-05 21:45:58.737: INFO/ActivityManager(754): START u0 {flg=0x10000000 cmp=com.test.MotionDetector/.MotionDetectActivity} from pid 4578 01-05 21:45:58.777: INFO/ActivityManager(754): Start proc com.test.MotionDetector for activity com.test.MotionDetector/.MotionDetectActivity: pid=4630 uid=10103 gids={50103, 1028, 1015} 01-05 21:45:59.627: INFO/ActivityManager(754): Displayed com.test.MotionDetector/.MotionDetectActivity: +861ms (total +972ms) 01-05 21:45:59.657: INFO/WindowManager(754): Screen frozen for +869ms due to Window{43cb77a8 u0 com.test.MotionDetector/com.test.MotionDetector.MotionDetectActivity}