title: Android Simple Camera Control App crashes when returning from Stopped
body: <p>I was working through the developer.Android Tutorials on <a href="http://developer.android.com/guide/topics/media/camera.html#custom-camera" rel="nofollow">building a Camera App</a> but I always encounter the following problem: When my app is put into the background, i.e. Stopped according to the activity lifecycle, and I try to return to it it crashes, telling me the App has stopped working.</p>
  
  <p>I searched other questions, but none of them seemed to have this same problem or I wasn't able to recognise it.</p>
  
  <p>I tried to figure out the minimum amount of code for this error to occur.
  The (only) Activity:</p>
  
  <pre><code>public class CameraActivity extends ActionBarActivity {
  
  private Camera mCamera;
  private CameraPreview mPreview;
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_camera_layout);
  
      // if device hardware has a camera
      if (checkCameraHardware(this))
          // Create an instance of Camera
          mCamera = getCameraInstance();
  
      // Create our Preview view and set it as the content of our activity.
      mPreview = new CameraPreview(this, mCamera);
      FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
      preview.addView(mPreview);
  
  
  }
  
  /** Check if this device has a camera */
  private boolean checkCameraHardware(Context context) {
      if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
          // this device has a camera
          return true;
      } else {
          // no camera on this device
          return false;
      }
  }
  
  /** A safe way to get an instance of the Camera object. */
  public static Camera getCameraInstance(){
      Camera c = null;
      try {
          c = Camera.open(); // attempt to get a Camera instance
      }
      catch (Exception e){
          // Camera is not available (in use or does not exist)
      }
      return c; // returns null if camera is unavailable
  }
  
  @Override
  public void onPause() {
      super.onPause();
      releaseCamera();              // release the camera immediately on pause event
  }
  
  private void releaseCamera(){
      if (mCamera != null){
          mCamera.stopPreview();      // stop the preview
          mCamera.release();        // release the camera for other applications
          mCamera = null;
      }
  }
  
  @Override
  public void onResume() {
      super.onResume();
  
      if (mCamera == null)
          mCamera = getCameraInstance();
  }
  
  
  }
  </code></pre>
  
  <p>The CameraPreview is instantiated using this class:</p>
  
  <pre><code>public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
      private SurfaceHolder mHolder;
      private Camera mCamera;
  
  public CameraPreview(Context context, Camera camera) {
      super(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("PandaHero", "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) {
      // .. same as in the example of the link
  }
  }
  </code></pre>
  
  <p>As for error messages, it always shows me that surfaceCreated() is called after release(). This made me think that I have to be missing some important reinstantiation of the camera or preview somewhere. I tried to stop the preview and release the camera within surfaceDestroyed(), onStop() and also to reopen the preview inside onStart() but the error persisted. 
  Also, no crashes occur if I do not include the Preview in the first place (but then my users wouldn't be able to see it either, so that's no option).</p>
  
  <p>So yeah, I think there is something vital I am missing here in terms of making use of the life cycle.</p>
  
  <p>Edit: The Error message I mentioned.</p>
  
  <pre><code>03-02 14:33:45.553  15462-15462/com.example.vrevru.viewlate_camerasetupsimple E/AndroidRuntime﹕ FATAL EXCEPTION: main
  java.lang.RuntimeException: Method called after release()
          at android.hardware.Camera.setPreviewDisplay(Native Method)
          at android.hardware.Camera.setPreviewDisplay(Camera.java:428)
          at com.example.thorsten.viewlate_camerasetupsimple.CameraPreview.surfaceCreated(CameraPreview.java:32)
          at android.view.SurfaceView.updateWindow(SurfaceView.java:639)
          at android.view.SurfaceView.onWindowVisibilityChanged(SurfaceView.java:262)
          at android.view.View.dispatchWindowVisibilityChanged(View.java:7440)
          at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042)
          at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042)
          at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042)
          at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042)
          at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042)
          at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042)
          at android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:1042)
          at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1237)
          at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1009)
          at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:4236)
          at android.view.Choreographer$CallbackRecord.run(Choreographer.java:725)
          at android.view.Choreographer.doCallbacks(Choreographer.java:555)
          at android.view.Choreographer.doFrame(Choreographer.java:525)
          at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:711)
          at android.os.Handler.handleCallback(Handler.java:615)
          at android.os.Handler.dispatchMessage(Handler.java:92)
          at android.os.Looper.loop(Looper.java:137)
          at android.app.ActivityThread.main(ActivityThread.java:4872)
          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:790)
          at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:557)
          at dalvik.system.NativeStart.main(Native Method)
  </code></pre>