diff --git a/zxing-android-embedded/src/com/journeyapps/barcodescanner/CameraPreview.java b/zxing-android-embedded/src/com/journeyapps/barcodescanner/CameraPreview.java index d4a0a9311..b303ff829 100644 --- a/zxing-android-embedded/src/com/journeyapps/barcodescanner/CameraPreview.java +++ b/zxing-android-embedded/src/com/journeyapps/barcodescanner/CameraPreview.java @@ -91,6 +91,11 @@ public interface StateListener { private boolean previewActive = false; private RotationListener rotationListener; + private int openedOrientation = -1; + + // Delay after rotation change is detected before we reorientate ourselves. + // This is to avoid double-reinitialization when the Activity is destroyed and recreated. + private static final int ROTATION_LISTENER_DELAY_MS = 250; private List stateListeners = new ArrayList<>(); @@ -195,12 +200,12 @@ public boolean handleMessage(Message message) { @Override public void onRotationChanged(int rotation) { // Make sure this is run on the main thread. - stateHandler.post(new Runnable() { + stateHandler.postDelayed(new Runnable() { @Override public void run() { rotationChanged(); } - }); + }, ROTATION_LISTENER_DELAY_MS); } }; @@ -263,8 +268,11 @@ protected void initializeAttributes(AttributeSet attrs) { } private void rotationChanged() { - pause(); - resume(); + // Confirm that it did actually change + if(isActive() && getDisplayRotation() != openedOrientation) { + pause(); + resume(); + } } private void setupSurfaceView() { @@ -550,6 +558,7 @@ public void pause() { Util.validateMainThread(); Log.d(TAG, "pause()"); + openedOrientation = -1; if (cameraInstance != null) { cameraInstance.close(); cameraInstance = null; @@ -640,11 +649,15 @@ private void initCamera() { cameraInstance.setReadyHandler(stateHandler); cameraInstance.open(); + + // Keep track of the orientation we opened at, so that we don't reopen the camera if we + // don't need to. + openedOrientation = getDisplayRotation(); } private void startCameraPreview(CameraSurface surface) { - if (!previewActive) { + if (!previewActive && cameraInstance != null) { Log.i(TAG, "Starting preview"); cameraInstance.setSurface(surface); cameraInstance.startPreview(); diff --git a/zxing-android-embedded/src/com/journeyapps/barcodescanner/camera/CameraManager.java b/zxing-android-embedded/src/com/journeyapps/barcodescanner/camera/CameraManager.java index ca503a230..69048680a 100755 --- a/zxing-android-embedded/src/com/journeyapps/barcodescanner/camera/CameraManager.java +++ b/zxing-android-embedded/src/com/journeyapps/barcodescanner/camera/CameraManager.java @@ -138,6 +138,9 @@ public void open() { * Must be called from camera thread. */ public void configure() { + if(camera == null) { + throw new RuntimeException("Camera not open"); + } setParameters(); } @@ -355,7 +358,7 @@ private void setParameters() { } catch (Exception e) { // Failed, use safe mode try { - setDesiredParameters(false); + setDesiredParameters(true); } catch (Exception e2) { // Well, darn. Give up Log.w(TAG, "Camera rejected even safe-mode parameters! No configuration"); diff --git a/zxing-android-embedded/src/com/journeyapps/barcodescanner/camera/CameraThread.java b/zxing-android-embedded/src/com/journeyapps/barcodescanner/camera/CameraThread.java index 2f0cfeb8f..d9252bf29 100644 --- a/zxing-android-embedded/src/com/journeyapps/barcodescanner/camera/CameraThread.java +++ b/zxing-android-embedded/src/com/journeyapps/barcodescanner/camera/CameraThread.java @@ -33,13 +33,35 @@ private CameraThread() { } /** - * Call from main thread. + * Call from main thread or camera thread. * * Enqueues a task on the camera thread. * * @param runnable the task to enqueue */ protected void enqueue(Runnable runnable) { + synchronized (LOCK) { + checkRunning(); + this.handler.post(runnable); + } + } + + /** + * Call from main thread or camera thread. + * + * Enqueues a task on the camera thread. + * + * @param runnable the task to enqueue + * @param delayMillis the delay in milliseconds before executing the runnable + */ + protected void enqueueDelayed(Runnable runnable, long delayMillis) { + synchronized (LOCK) { + checkRunning(); + this.handler.postDelayed(runnable, delayMillis); + } + } + + private void checkRunning() { synchronized (LOCK) { if (this.handler == null) { if (openCount <= 0) { @@ -49,7 +71,6 @@ protected void enqueue(Runnable runnable) { this.thread.start(); this.handler = new Handler(thread.getLooper()); } - this.handler.post(runnable); } }