title: Android: java.lang.RuntimeException: takePicture failed
body: <p>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:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>My code:</p>
  
  <pre><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;
      }
  }
  </code></pre>
  
  <p>Permissions and features used:</p>
  
  <pre><code>&lt;uses-permission android:name="android.permission.CAMERA"/&gt;
  &lt;uses-feature android:name="android.hardware.camera"/&gt;
  &lt;uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /&gt;
  &lt;uses-feature android:name="android.hardware.camera.autofocus" /&gt;
  &lt;uses-feature android:name="android.hardware.camera.flash" /&gt;
  </code></pre>
  
  <p>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.</p>
  
  <p>LogCat before taking picture:</p>
  
  <pre><code>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}
  </code></pre>