From e7330fcd7b3b8a67703cf8d2d6b7849667ddfb18 Mon Sep 17 00:00:00 2001 From: Mattia Iavarone Date: Wed, 2 Aug 2017 23:08:38 +0200 Subject: [PATCH] Smart sizing behavior, removed adjustViewBounds --- .../api16/com/flurgle/camerakit/Camera1.java | 14 +- .../com/flurgle/camerakit/CameraImpl.java | 1 + .../com/flurgle/camerakit/PreviewImpl.java | 52 ++--- .../flurgle/camerakit/SurfaceViewPreview.java | 1 + .../flurgle/camerakit/TextureViewPreview.java | 1 + .../com/flurgle/camerakit/CameraView.java | 187 ++++++++++++------ .../flurgle/camerakit/demo/MainActivity.java | 10 +- .../demo/PicturePreviewActivity.java | 13 +- .../flurgle/camerakit/demo/ResultHolder.java | 50 ----- .../camerakit/demo/VideoPreviewActivity.java | 7 +- 10 files changed, 185 insertions(+), 151 deletions(-) delete mode 100644 demo/src/main/java/com/flurgle/camerakit/demo/ResultHolder.java diff --git a/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java b/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java index f6cd7025..32966843 100644 --- a/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java +++ b/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java @@ -43,7 +43,6 @@ class Camera1 extends CameraImpl { private MediaRecorder mMediaRecorder; private File mVideoFile; private Camera.AutoFocusCallback mAutofocusCallback; - private boolean isCapturingImage = false; private int mDisplayOffset; private int mDeviceOrientation; @@ -63,6 +62,7 @@ class Camera1 extends CameraImpl { private Handler mFocusHandler = new Handler(); private ConstantMapper.MapperImpl mMapper = new ConstantMapper.Mapper1(); private boolean mIsSetup = false; + private boolean mIsCapturingImage = false; private final Object mLock = new Object(); @@ -91,6 +91,7 @@ class Camera1 extends CameraImpl { Size newSize = computePreviewSize(); if (!newSize.equals(mPreviewSize)) { mPreviewSize = newSize; + mCameraListener.onCameraPreviewSizeChanged(); synchronized (mLock) { mCamera.stopPreview(); Camera.Parameters params = mCamera.getParameters(); @@ -127,6 +128,7 @@ class Camera1 extends CameraImpl { boolean invertPreviewSizes = shouldFlipSizes(); // mDisplayOffset % 180 != 0; mCaptureSize = computeCaptureSize(); mPreviewSize = computePreviewSize(); + mCameraListener.onCameraPreviewSizeChanged(); mPreview.setDesiredSize( invertPreviewSizes ? mPreviewSize.getHeight() : mPreviewSize.getWidth(), invertPreviewSizes ? mPreviewSize.getWidth() : mPreviewSize.getHeight() @@ -356,12 +358,12 @@ class Camera1 extends CameraImpl { @Override void captureImage() { - if (isCapturingImage) return; + if (mIsCapturingImage) return; if (!isCameraOpened()) return; switch (mSessionType) { case SESSION_TYPE_PICTURE: // Set boolean to wait for image callback - isCapturingImage = true; + mIsCapturingImage = true; synchronized (mLock) { Camera.Parameters parameters = mCamera.getParameters(); parameters.setRotation(computeExifOrientation()); @@ -372,7 +374,7 @@ class Camera1 extends CameraImpl { @Override public void onPictureTaken(byte[] data, Camera camera) { mCameraListener.onPictureTaken(data); - isCapturingImage = false; + mIsCapturingImage = false; camera.startPreview(); // This is needed, read somewhere in the docs. } }); @@ -382,7 +384,7 @@ class Camera1 extends CameraImpl { // If we are in a video session, camera captures are fast captures coming // from the preview stream. // TODO: will this work while recording a video? test... - isCapturingImage = true; + mIsCapturingImage = true; mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() { @Override public void onPreviewFrame(final byte[] data, Camera camera) { @@ -402,7 +404,7 @@ class Camera1 extends CameraImpl { byte[] rotatedData = RotationHelper.rotate(data, preWidth, preHeight, rotation); YuvImage yuv = new YuvImage(rotatedData, format, postWidth, postHeight, null); mCameraListener.processYuvImage(yuv); - isCapturingImage = false; + mIsCapturingImage = false; } }).start(); } diff --git a/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java b/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java index da19b35f..d59fc761 100644 --- a/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java @@ -1,5 +1,6 @@ package com.flurgle.camerakit; +import android.support.annotation.CallSuper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.view.MotionEvent; diff --git a/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java b/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java index 10e625d3..926e7c98 100644 --- a/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java @@ -1,12 +1,16 @@ package com.flurgle.camerakit; +import android.content.Context; import android.graphics.SurfaceTexture; import android.view.Surface; import android.view.SurfaceHolder; import android.view.View; +import android.view.ViewGroup; abstract class PreviewImpl { + // This is used to notify CameraImpl to recompute its camera Preview size. + // After that, CameraView will need a new layout pass to adapt to the Preview size. interface SurfaceCallback { void onSurfaceAvailable(); void onSurfaceChanged(); @@ -23,35 +27,48 @@ abstract class PreviewImpl { private int mDesiredWidth; private int mDesiredHeight; - void setSurfaceCallback(SurfaceCallback callback) { - mSurfaceCallback = callback; - } + PreviewImpl(Context context, ViewGroup parent) {} abstract Surface getSurface(); - abstract View getView(); - abstract Class getOutputClass(); - + abstract boolean isReady(); protected void onDisplayOffset(int displayOrientation) {} protected void onDeviceOrientation(int deviceOrientation) {} - - abstract boolean isReady(); - SurfaceHolder getSurfaceHolder() { return null; } - SurfaceTexture getSurfaceTexture() { return null; } + + // As far as I can see, these are the actual preview dimensions, as set in CameraParameters. + // This is called by the CameraImpl. + // These must be alredy rotated, if needed, to be consistent with surface/view sizes. + void setDesiredSize(int width, int height) { + this.mDesiredWidth = width; + this.mDesiredHeight = height; + refreshScale(); + } + + final Size getSurfaceSize() { + return new Size(mSurfaceWidth, mSurfaceHeight); + } + + final void setSurfaceCallback(SurfaceCallback callback) { + mSurfaceCallback = callback; + } + + protected final void onSurfaceAvailable(int width, int height) { mSurfaceWidth = width; mSurfaceHeight = height; refreshScale(); mSurfaceCallback.onSurfaceAvailable(); } + + // As far as I can see, these are the view/surface dimensions. // This is called by subclasses. protected final void onSurfaceSizeChanged(int width, int height) { @@ -63,31 +80,20 @@ abstract class PreviewImpl { } } + protected final void onSurfaceDestroyed() { mSurfaceWidth = 0; mSurfaceHeight = 0; refreshScale(); } - // As far as I can see, these are the actual preview dimensions, as set in CameraParameters. - // This is called by the CameraImpl. - // These must be alredy rotated, if needed, to be consistent with surface/view sizes. - void setDesiredSize(int width, int height) { - this.mDesiredWidth = width; - this.mDesiredHeight = height; - refreshScale(); - } - - Size getSurfaceSize() { - return new Size(mSurfaceWidth, mSurfaceHeight); - } /** * As far as I can see, this extends either width or height of the surface, * to match the desired aspect ratio. * This means that the external part of the surface will be cropped by the outer view. */ - private void refreshScale() { + private final void refreshScale() { getView().post(new Runnable() { @Override public void run() { diff --git a/camerakit/src/main/base/com/flurgle/camerakit/SurfaceViewPreview.java b/camerakit/src/main/base/com/flurgle/camerakit/SurfaceViewPreview.java index e2fc77d7..af432cc7 100644 --- a/camerakit/src/main/base/com/flurgle/camerakit/SurfaceViewPreview.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/SurfaceViewPreview.java @@ -13,6 +13,7 @@ class SurfaceViewPreview extends PreviewImpl { private final SurfaceView mSurfaceView; SurfaceViewPreview(Context context, ViewGroup parent) { + super(context, parent); final View view = View.inflate(context, R.layout.surface_view, parent); // MATCH_PARENT mSurfaceView = (SurfaceView) view.findViewById(R.id.surface_view); final SurfaceHolder holder = mSurfaceView.getHolder(); diff --git a/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java b/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java index 44633593..1c74b0cc 100644 --- a/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java +++ b/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java @@ -15,6 +15,7 @@ class TextureViewPreview extends PreviewImpl { private Surface mSurface; TextureViewPreview(Context context, ViewGroup parent) { + super(context, parent); final View view = View.inflate(context, R.layout.texture_view, parent); // MATCH_PARENT mTextureView = (TextureView) view.findViewById(R.id.texture_view); mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java index c7a05c4e..b885ec4b 100644 --- a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java +++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java @@ -42,6 +42,12 @@ import static com.flurgle.camerakit.CameraKit.Constants.FLASH_TORCH; import static com.flurgle.camerakit.CameraKit.Constants.SESSION_TYPE_PICTURE; import static com.flurgle.camerakit.CameraKit.Constants.SESSION_TYPE_VIDEO; +import static android.view.View.MeasureSpec.AT_MOST; +import static android.view.View.MeasureSpec.EXACTLY; +import static android.view.View.MeasureSpec.UNSPECIFIED; + +import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; + /** * The CameraView implements the LifecycleObserver interface for ease of use. To take advantage of * this, simply call the following from any LifecycleOwner: @@ -188,79 +194,139 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } + private String ms(int mode) { + switch (mode) { + case AT_MOST: return "AT_MOST"; + case EXACTLY: return "EXACTLY"; + case UNSPECIFIED: return "UNSPECIFIED"; + } + return null; + } + /** - * If adjustViewBounds was set AND one of the dimensions is set to WRAP_CONTENT, - * CameraView will adjust that dimensions to fit the preview aspect ratio as returned by - * {@link #getPreviewSize()}. + * Measuring is basically controlled by layout params width and height. + * The basic semantics are: * - * If this is not true, the surface will adapt to the dimension specified in the layout file. - * Having fixed dimensions means that, very likely, what the user sees is different from what - * the final picture will be. This is also due to what happens in {@link PreviewImpl#refreshScale()}. + * - MATCH_PARENT: CameraView should completely fill this dimension, even if this might mean + * not respecting the preview aspect ratio. + * - WRAP_CONTENT: CameraView should try to adapt this dimension to respect the preview + * aspect ratio. * - * If this is a problem, you can use {@link #setCropOutput(boolean)} set to true. - * In that case, the final image will have the same aspect ratio of the preview. + * When both dimensions are MATCH_PARENT, CameraView will fill its + * parent no matter the preview. Thanks to what happens in {@link PreviewImpl}, this acts like + * a CENTER CROP scale type. + * + * When both dimensions are WRAP_CONTENT, CameraView will take the biggest dimensions that + * fit the preview aspect ratio. This acts like a CENTER INSIDE scale type. */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - if (!mAdjustViewBounds) { - Log.e(TAG, "onMeasure, adjustViewBounds=false"); + Size previewSize = getPreviewSize(); + if (previewSize == null) { + Log.e(TAG, "onMeasure, surface is not ready. Calling default behavior."); super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } - Size previewSize = getPreviewSize(); - if (previewSize == null) { // Early measure. - Log.e(TAG, "onMeasure, early measure"); + // Let's which dimensions need to be adapted. + int widthMode = MeasureSpec.getMode(widthMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + final int widthValue = MeasureSpec.getSize(widthMeasureSpec); + final int heightValue = MeasureSpec.getSize(heightMeasureSpec); + final boolean flip = mCameraImpl.shouldFlipSizes(); + final float previewWidth = flip ? previewSize.getHeight() : previewSize.getWidth(); + final float previewHeight = flip ? previewSize.getWidth() : previewSize.getHeight(); + + // If MATCH_PARENT is interpreted as AT_MOST, transform to EXACTLY + // to be consistent with our semantics. + final ViewGroup.LayoutParams lp = getLayoutParams(); + if (widthMode == AT_MOST && lp.width == MATCH_PARENT) widthMode = EXACTLY; + if (heightMode == AT_MOST && lp.height == MATCH_PARENT) heightMode = EXACTLY; + Log.e(TAG, "onMeasure, requested dimensions are (" + + widthValue + "[" + ms(widthMode) + "]x" + + heightValue + "[" + ms(heightMode) + "])"); + Log.e(TAG, "onMeasure, previewSize is (" + previewWidth + "x" + previewHeight + ")"); + + + // If we have fixed dimensions (either 300dp or MATCH_PARENT), there's nothing we should do, + // other than respect it. The preview will eventually be cropped at the sides (by PreviewImpl scaling) + // except the case in which these fixed dimensions somehow fit exactly the preview aspect ratio. + if (widthMode == EXACTLY && heightMode == EXACTLY) { + Log.e(TAG, "onMeasure, both are MATCH_PARENT or fixed value. We adapt. This means CROP_INSIDE. " + + "(" + widthValue + "x" + heightValue + ")"); super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } - boolean wwc = getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT; - boolean hwc = getLayoutParams().height == ViewGroup.LayoutParams.WRAP_CONTENT; - boolean flip = mCameraImpl.shouldFlipSizes(); - float previewWidth = flip ? previewSize.getHeight() : previewSize.getWidth(); - float previewHeight = flip ? previewSize.getWidth() : previewSize.getHeight(); - float parentHeight = MeasureSpec.getSize(heightMeasureSpec); - float parentWidth = MeasureSpec.getSize(widthMeasureSpec); // mode = AT_MOST - Log.e(TAG, "onMeasure, parent size is "+new Size((int)parentWidth, (int)parentHeight)); // 1080x1794 - Log.e(TAG, "onMeasure, surface size is "+new Size((int)previewWidth, (int)previewHeight)); // 1600x1200 - - if (wwc && hwc) { - // If both dimensions are WRAP_CONTENT, let's try to fit the preview size perfectly - // without cropping. - // TODO: This should actually be a flag, like scaleMode, that replaces cropOutput and adjustViewBounds. - // This is like a fitCenter. - float targetRatio = previewHeight / previewWidth; - float currentRatio = parentHeight / parentWidth; - if (currentRatio > targetRatio) { - // View is too tall. Must reduce height. - int newHeight = (int) (parentWidth * targetRatio); - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY)); + // If both dimensions are free, with no limits, then our size will be exactly the + // preview size. This can happen rarely, for example in scrollable containers. + if (widthMode == UNSPECIFIED && heightMode == UNSPECIFIED) { + Log.e(TAG, "onMeasure, both are completely free. We respect that and extend to the whole preview size. " + + "(" + previewWidth + "x" + previewHeight + ")"); + super.onMeasure(MeasureSpec.makeMeasureSpec((int) previewWidth, EXACTLY), + MeasureSpec.makeMeasureSpec((int) previewHeight, EXACTLY)); + return; + } + + // It sure now that at least one dimension can be determined (either because EXACTLY or AT_MOST). + // This starts to seem a pleasant situation. + + // If one of the dimension is completely free, take the other and fit the ratio. + // One of the two might be AT_MOST, but we use the value anyway. + float ratio = previewHeight / previewWidth; + if (widthMode == UNSPECIFIED || heightMode == UNSPECIFIED) { + boolean freeWidth = widthMode == UNSPECIFIED; + int height, width; + if (freeWidth) { + height = heightValue; + width = (int) (height / ratio); } else { - // View is too wide. Must reduce width. - int newWidth = (int) (parentHeight / targetRatio); - super.onMeasure(MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY), heightMeasureSpec); + width = widthValue; + height = (int) (width * ratio); } + Log.e(TAG, "onMeasure, one dimension was free, we adapted it to fit the aspect ratio. " + + "(" + width + "x" + height + ")"); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, EXACTLY), + MeasureSpec.makeMeasureSpec(height, EXACTLY)); + return; + } - } else if (wwc) { - // Legacy behavior, with just a WC dimension. This is dangerous because the final size - // might be bigger than the available size, resulting in part of the surface getting cropped. - // Think for example of a 4:3 preview in a 16:9 screen, with width=MP and height=WC. - // This is like a cropCenter. - float height = MeasureSpec.getSize(heightMeasureSpec); - float ratio = height / previewWidth; - int width = (int) (previewHeight * ratio); - super.onMeasure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY), heightMeasureSpec); - - } else if (hwc) { - float width = MeasureSpec.getSize(widthMeasureSpec); - float ratio = width / previewHeight; - int height = (int) (previewWidth * ratio); - super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)); + // At this point both dimensions are either AT_MOST-AT_MOST, EXACTLY-AT_MOST or AT_MOST-EXACTLY. + // Let's manage this sanely. If only one is EXACTLY, we can TRY to fit the aspect ratio, + // but it is not guaranteed to succeed. It depends on the AT_MOST value of the other dimensions. + if (widthMode == EXACTLY || heightMode == EXACTLY) { + boolean freeWidth = widthMode == AT_MOST; + int height, width; + if (freeWidth) { + height = heightValue; + width = Math.min((int) (height / ratio), widthValue); + } else { + width = widthValue; + height = Math.min((int) (width * ratio), heightValue); + } + Log.e(TAG, "onMeasure, one dimension was EXACTLY, another AT_MOST. We have TRIED to fit " + + "the aspect ratio, but it's not guaranteed. (" + width + "x" + height + ")"); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, EXACTLY), + MeasureSpec.makeMeasureSpec(height, EXACTLY)); + return; + } + // Last case, AT_MOST and AT_MOST. Here we can SURELY fit the aspect ratio by filling one + // dimension and adapting the other. + int height, width; + float atMostRatio = heightValue / widthValue; + if (atMostRatio >= ratio) { + // We must reduce height. + width = widthValue; + height = (int) (width * ratio); } else { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); + height = heightValue; + width = (int) (height / ratio); } + Log.e(TAG, "onMeasure, both dimension were AT_MOST. We fit the preview aspect ratio. " + + "(" + width + "x" + height + ")"); + super.onMeasure(MeasureSpec.makeMeasureSpec(width, EXACTLY), + MeasureSpec.makeMeasureSpec(height, EXACTLY)); } @@ -759,23 +825,29 @@ public class CameraView extends FrameLayout implements LifecycleObserver { @Override public void onCameraOpened() { - super.onCameraOpened(); if (mWrappedListener == null) return; mWrappedListener.onCameraOpened(); } @Override public void onCameraClosed() { - super.onCameraClosed(); if (mWrappedListener == null) return; mWrappedListener.onCameraClosed(); } + public void onCameraPreviewSizeChanged() { + // Camera preview size, as returned by getPreviewSize(), has changed. + // Request a layout pass for onMeasure() to do its stuff. + // Potentially this will change CameraView size, which changes Surface size, + // which triggers a new Preview size. But hopefully it will converge. + requestLayout(); + } + @Override public void onPictureTaken(byte[] jpeg) { - super.onPictureTaken(jpeg); if (mWrappedListener == null) return; if (mCropOutput) { + // TODO cropOutput won't work if image is rotated (e.g. byte[] contains exif orientation). AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight()); mWrappedListener.onPictureTaken(new CenterCrop(jpeg, outputRatio, mJpegQuality).getJpeg()); } else { @@ -783,7 +855,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver { } } - void processYuvImage(YuvImage yuv) { + public void processYuvImage(YuvImage yuv) { if (mWrappedListener == null) return; if (mCropOutput) { AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight()); @@ -797,7 +869,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver { @Override public void onVideoTaken(File video) { - super.onVideoTaken(video); mWrappedListener.onVideoTaken(video); } diff --git a/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java b/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java index 6844d91c..7b22570c 100644 --- a/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java +++ b/demo/src/main/java/com/flurgle/camerakit/demo/MainActivity.java @@ -121,10 +121,9 @@ public class MainActivity extends AppCompatActivity implements View.OnLayoutChan mCapturing = false; long callbackTime = System.currentTimeMillis(); Bitmap bitmap = BitmapFactory.decodeByteArray(jpeg, 0, jpeg.length); - ResultHolder.dispose(); - ResultHolder.setImage(bitmap); - ResultHolder.setTimeToCallback(callbackTime - startTime); + PicturePreviewActivity.setImage(bitmap); Intent intent = new Intent(MainActivity.this, PicturePreviewActivity.class); + intent.putExtra("delay", callbackTime-startTime); startActivity(intent); } }); @@ -144,9 +143,8 @@ public class MainActivity extends AppCompatActivity implements View.OnLayoutChan public void onVideoTaken(File video) { super.onVideoTaken(video); mCapturing = false; - ResultHolder.dispose(); - ResultHolder.setVideo(Uri.fromFile(video)); Intent intent = new Intent(MainActivity.this, VideoPreviewActivity.class); + intent.putExtra("video", Uri.fromFile(video)); startActivity(intent); } }); @@ -169,7 +167,6 @@ public class MainActivity extends AppCompatActivity implements View.OnLayoutChan break; case CameraKit.Constants.FACING_FRONT: - Toast.makeText(this, "Switched to front camera!", Toast.LENGTH_SHORT).show(); break; } @@ -307,6 +304,7 @@ public class MainActivity extends AppCompatActivity implements View.OnLayoutChan break; case R.id.heightMatchParent: + // We are in a vertically scrolling container, match parent would not work at all. height = parent.getHeight(); break; } diff --git a/demo/src/main/java/com/flurgle/camerakit/demo/PicturePreviewActivity.java b/demo/src/main/java/com/flurgle/camerakit/demo/PicturePreviewActivity.java index 3d6adcfd..6c4c1f48 100644 --- a/demo/src/main/java/com/flurgle/camerakit/demo/PicturePreviewActivity.java +++ b/demo/src/main/java/com/flurgle/camerakit/demo/PicturePreviewActivity.java @@ -10,6 +10,8 @@ import android.widget.TextView; import com.flurgle.camerakit.AspectRatio; import com.flurgle.camerakit.Size; +import java.lang.ref.WeakReference; + import butterknife.BindView; import butterknife.ButterKnife; @@ -30,13 +32,20 @@ public class PicturePreviewActivity extends Activity { @BindView(R.id.captureLatency) TextView captureLatency; + private static WeakReference image; + + public static void setImage(@Nullable Bitmap im) { + image = im != null ? new WeakReference<>(im) : null; + } + @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_picture_preview); ButterKnife.bind(this); - Bitmap bitmap = ResultHolder.getImage(); + long delay = getIntent().getLongExtra("delay", 0); + Bitmap bitmap = image == null ? null : image.get(); if (bitmap == null) { finish(); return; @@ -51,7 +60,7 @@ public class PicturePreviewActivity extends Activity { actualResolution.setText(bitmap.getWidth() + " x " + bitmap.getHeight()); approxUncompressedSize.setText(getApproximateFileMegabytes(bitmap) + "MB"); - captureLatency.setText(ResultHolder.getTimeToCallback() + " milliseconds"); + captureLatency.setText(delay + " milliseconds"); } private static float getApproximateFileMegabytes(Bitmap bitmap) { diff --git a/demo/src/main/java/com/flurgle/camerakit/demo/ResultHolder.java b/demo/src/main/java/com/flurgle/camerakit/demo/ResultHolder.java deleted file mode 100644 index 8c439558..00000000 --- a/demo/src/main/java/com/flurgle/camerakit/demo/ResultHolder.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.flurgle.camerakit.demo; - -import android.graphics.Bitmap; -import android.net.Uri; -import android.support.annotation.Nullable; - -import com.flurgle.camerakit.Size; - -import java.lang.ref.WeakReference; - -public class ResultHolder { - - private static WeakReference image; - private static Size nativeCaptureSize; - private static long timeToCallback; - private static Uri video; - - - public static Uri getVideo() { - return video; - } - - public static void setVideo(Uri video) { - ResultHolder.video = video; - } - - public static void setImage(@Nullable Bitmap image) { - ResultHolder.image = image != null ? new WeakReference<>(image) : null; - } - - @Nullable - public static Bitmap getImage() { - return image != null ? image.get() : null; - } - - public static void setTimeToCallback(long timeToCallback) { - ResultHolder.timeToCallback = timeToCallback; - } - - public static long getTimeToCallback() { - return timeToCallback; - } - - public static void dispose() { - setImage(null); - setVideo(null); - setTimeToCallback(0); - } - -} diff --git a/demo/src/main/java/com/flurgle/camerakit/demo/VideoPreviewActivity.java b/demo/src/main/java/com/flurgle/camerakit/demo/VideoPreviewActivity.java index 7c6e8c3c..34c9fb8b 100644 --- a/demo/src/main/java/com/flurgle/camerakit/demo/VideoPreviewActivity.java +++ b/demo/src/main/java/com/flurgle/camerakit/demo/VideoPreviewActivity.java @@ -33,12 +33,7 @@ public class VideoPreviewActivity extends Activity { setContentView(R.layout.activity_video_preview); ButterKnife.bind(this); - Uri videoUri = ResultHolder.getVideo(); - if (videoUri == null) { - finish(); - return; - } - + Uri videoUri = getIntent().getParcelableExtra("video"); MediaController controller = new MediaController(this); controller.setAnchorView(videoView); controller.setMediaPlayer(videoView);