diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java index a5f603bd..0537cf9f 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java @@ -191,7 +191,7 @@ class Camera1 extends CameraController { Exception error = null; LOG.i("onStop:", "About to clean up."); mHandler.get().removeCallbacks(mPostFocusResetRunnable); - if (isCameraAvailable()) { + if (mCamera != null) { LOG.i("onStop:", "Clean up.", "Ending video?", mIsCapturingVideo); if (mIsCapturingVideo) endVideo(); @@ -510,7 +510,20 @@ class Camera1 extends CameraController { } private boolean isCameraAvailable() { - return mCamera != null; + switch (mState) { + // If we are stopped, don't. + case STATE_STOPPED: return false; + // If we are going to be closed, don't act on camera. + // Even if mCamera != null, it might have been released. + case STATE_STOPPING: return false; + // If we are started, act as long as there is no stop/restart scheduled. + // At this point mCamera should never be null. + case STATE_STARTED: return !mScheduledForStop && !mScheduledForRestart; + // If we are starting, theoretically we could act. + // Just check that camera is available. + case STATE_STARTING: return mCamera != null && !mScheduledForStop && !mScheduledForRestart; + } + return false; } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java index c9c1038c..be221965 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraController.java @@ -38,6 +38,10 @@ abstract class CameraController implements CameraPreview.SurfaceCallback { protected int mDisplayOffset; protected int mDeviceOrientation; + + protected boolean mScheduledForStart = false; + protected boolean mScheduledForStop = false; + protected boolean mScheduledForRestart = false; protected int mState = STATE_STOPPED; protected WorkerHandler mHandler; @@ -84,11 +88,13 @@ abstract class CameraController implements CameraPreview.SurfaceCallback { // Starts the preview asynchronously. final void start() { LOG.i("Start:", "posting runnable. State:", ss()); + mScheduledForStart = true; mHandler.post(new Runnable() { @Override public void run() { try { LOG.i("Start:", "executing. State:", ss()); + mScheduledForStart = false; if (mState >= STATE_STARTING) return; mState = STATE_STARTING; LOG.i("Start:", "about to call onStart()", ss()); @@ -108,11 +114,13 @@ abstract class CameraController implements CameraPreview.SurfaceCallback { // Stops the preview asynchronously. final void stop() { LOG.i("Stop:", "posting runnable. State:", ss()); + mScheduledForStop = true; mHandler.post(new Runnable() { @Override public void run() { try { LOG.i("Stop:", "executing. State:", ss()); + mScheduledForStop = false; if (mState <= STATE_STOPPED) return; mState = STATE_STOPPING; LOG.i("Stop:", "about to call onStop()"); @@ -148,11 +156,13 @@ abstract class CameraController implements CameraPreview.SurfaceCallback { // Forces a restart. protected final void restart() { LOG.i("Restart:", "posting runnable"); + mScheduledForRestart = true; mHandler.post(new Runnable() { @Override public void run() { try { LOG.i("Restart:", "executing. Needs stopping:", mState > STATE_STOPPED, ss()); + mScheduledForRestart = false; // Don't stop if stopped. if (mState > STATE_STOPPED) { mState = STATE_STOPPING;