diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/overlay/Overlay.java b/cameraview/src/main/java/com/otaliastudios/cameraview/overlay/Overlay.java index 212495cf..44e1661d 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/overlay/Overlay.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/overlay/Overlay.java @@ -15,8 +15,19 @@ public interface Overlay { /** * Called for this overlay to draw itself on the specified target and canvas. + * * @param target target * @param canvas target canvas */ - void draw(@NonNull Target target, @NonNull Canvas canvas); + void drawOn(@NonNull Target target, @NonNull Canvas canvas); + + /** + * Called to understand if this overlay would like to draw onto the given + * target or not. If true is returned, {@link #drawOn(Target, Canvas)} can be + * called at a future time. + * + * @param target the target + * @return true to draw on it + */ + boolean drawsOn(@NonNull Target target); } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/overlay/OverlayLayout.java b/cameraview/src/main/java/com/otaliastudios/cameraview/overlay/OverlayLayout.java index eff94def..cbf85915 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/overlay/OverlayLayout.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/overlay/OverlayLayout.java @@ -81,7 +81,18 @@ public class OverlayLayout extends FrameLayout implements Overlay { @Override public void draw(Canvas canvas) { LOG.i("normal draw called."); - draw(Target.PREVIEW, canvas); + if (drawsOn(Target.PREVIEW)) { + drawOn(Target.PREVIEW, canvas); + } + } + + @Override + public boolean drawsOn(@NonNull Target target) { + for (int i = 0; i < getChildCount(); i++) { + LayoutParams params = (LayoutParams) getChildAt(i).getLayoutParams(); + if (params.drawsOn(target)) return true; + } + return false; } /** @@ -96,7 +107,7 @@ public class OverlayLayout extends FrameLayout implements Overlay { * @param canvas the canvas */ @Override - public void draw(@NonNull Target target, @NonNull Canvas canvas) { + public void drawOn(@NonNull Target target, @NonNull Canvas canvas) { synchronized (this) { currentTarget = target; switch (target) { @@ -134,11 +145,7 @@ public class OverlayLayout extends FrameLayout implements Overlay { @Override protected boolean drawChild(Canvas canvas, View child, long drawingTime) { LayoutParams params = (LayoutParams) child.getLayoutParams(); - boolean draw = ((currentTarget == Target.PREVIEW && params.drawOnPreview) - || (currentTarget == Target.VIDEO_SNAPSHOT && params.drawOnVideoSnapshot) - || (currentTarget == Target.PICTURE_SNAPSHOT && params.drawOnPictureSnapshot) - ); - if (draw) { + if (params.drawsOn(currentTarget)) { LOG.v("Performing drawing for view:", child.getClass().getSimpleName(), "target:", currentTarget, "params:", params); @@ -173,6 +180,12 @@ public class OverlayLayout extends FrameLayout implements Overlay { } } + private boolean drawsOn(@NonNull Target target) { + return ((target == Target.PREVIEW && drawOnPreview) + || (target == Target.VIDEO_SNAPSHOT && drawOnVideoSnapshot) + || (target == Target.PICTURE_SNAPSHOT && drawOnPictureSnapshot)); + } + @NonNull @Override public String toString() { diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/SnapshotGlPictureRecorder.java b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/SnapshotGlPictureRecorder.java index cbe3512b..d13ef3a9 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/picture/SnapshotGlPictureRecorder.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/picture/SnapshotGlPictureRecorder.java @@ -35,9 +35,6 @@ import androidx.annotation.Nullable; import android.view.Surface; -import java.util.ArrayList; -import java.util.List; - public class SnapshotGlPictureRecorder extends PictureRecorder { private static final String TAG = SnapshotGlPictureRecorder.class.getSimpleName(); @@ -61,7 +58,7 @@ public class SnapshotGlPictureRecorder extends PictureRecorder { mPreview = preview; mOutputRatio = outputRatio; mOverlay = overlay; - mHasOverlay = overlay != null; + mHasOverlay = overlay != null && overlay.drawsOn(Overlay.Target.PICTURE_SNAPSHOT); } @TargetApi(Build.VERSION_CODES.KITKAT) @@ -168,7 +165,7 @@ public class SnapshotGlPictureRecorder extends PictureRecorder { try { final Canvas surfaceCanvas = mOverlaySurface.lockCanvas(null); surfaceCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR); - mOverlay.draw(Overlay.Target.PICTURE_SNAPSHOT, surfaceCanvas); + mOverlay.drawOn(Overlay.Target.PICTURE_SNAPSHOT, surfaceCanvas); mOverlaySurface.unlockCanvasAndPost(surfaceCanvas); } catch (Surface.OutOfResourcesException e) { LOG.w("Got Surface.OutOfResourcesException while drawing picture overlays", e); diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/preview/CameraPreview.java b/cameraview/src/main/java/com/otaliastudios/cameraview/preview/CameraPreview.java index a184731d..29470b7c 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/preview/CameraPreview.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/preview/CameraPreview.java @@ -1,14 +1,21 @@ package com.otaliastudios.cameraview.preview; import android.content.Context; + +import androidx.annotation.CallSuper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; +import android.os.Handler; +import android.os.Looper; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; +import com.google.android.gms.tasks.TaskCompletionSource; +import com.google.android.gms.tasks.Tasks; import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.engine.CameraEngine; import com.otaliastudios.cameraview.internal.utils.Op; @@ -240,7 +247,32 @@ public abstract class CameraPreview { * Called by the hosting {@link com.otaliastudios.cameraview.CameraView}, * this is a lifecycle event. */ + @CallSuper public void onDestroy() { + if (Thread.currentThread() == Looper.getMainLooper().getThread()) { + onDestroyView(); + } else { + // Do this on the UI thread and wait. + Handler ui = new Handler(Looper.getMainLooper()); + final TaskCompletionSource task = new TaskCompletionSource<>(); + ui.post(new Runnable() { + @Override + public void run() { + onDestroyView(); + task.setResult(null); + } + }); + try { Tasks.await(task.getTask()); } catch (Exception ignore) {} + } + } + + /** + * At this point we undo the work that was done during {@link #onCreateView(Context, ViewGroup)}, + * which basically means removing the root view from the hierarchy. + */ + @SuppressWarnings("WeakerAccess") + @UiThread + protected void onDestroyView() { View root = getRootView(); ViewParent parent = root.getParent(); if (parent instanceof ViewGroup) { diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/preview/GlCameraPreview.java b/cameraview/src/main/java/com/otaliastudios/cameraview/preview/GlCameraPreview.java index b3b5a63d..54f62371 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/preview/GlCameraPreview.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/preview/GlCameraPreview.java @@ -5,7 +5,6 @@ import android.graphics.SurfaceTexture; import android.opengl.GLSurfaceView; import android.opengl.Matrix; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import android.view.LayoutInflater; @@ -91,7 +90,7 @@ public class GlCameraPreview extends CameraPreview extends Med int rotation; String mimeType; - Config(int width, int height, int bitRate, int frameRate, int rotation, String mimeType) { + Config(int width, int height, int bitRate, int frameRate, int rotation, @NonNull String mimeType) { this.width = width; this.height = height; this.bitRate = bitRate;