diff --git a/camerakit/build.gradle b/camerakit/build.gradle
index 793d9410..e67385f7 100644
--- a/camerakit/build.gradle
+++ b/camerakit/build.gradle
@@ -7,14 +7,14 @@ ext {
}
android {
- compileSdkVersion 25
- buildToolsVersion "25.0.2"
+ compileSdkVersion rootProject.ext.compileSdkVersion
+ buildToolsVersion rootProject.ext.buildToolsVersion
defaultConfig {
- minSdkVersion 15
- targetSdkVersion 25
+ minSdkVersion rootProject.ext.minSdkVersion
+ targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
- versionName "1.0"
+ versionName "0.1"
}
buildTypes {
release {
@@ -40,5 +40,5 @@ dependencies {
annotationProcessor 'android.arch.lifecycle:compiler:1.0.0-alpha1'
}
-apply from: 'https://raw.githubusercontent.com/blundell/release-android-library/master/android-release-aar.gradle'
+// apply from: 'https://raw.githubusercontent.com/blundell/release-android-library/master/android-release-aar.gradle'
diff --git a/camerakit/src/main/AndroidManifest.xml b/camerakit/src/main/AndroidManifest.xml
index 31b72ed2..0b5e8472 100644
--- a/camerakit/src/main/AndroidManifest.xml
+++ b/camerakit/src/main/AndroidManifest.xml
@@ -2,19 +2,24 @@
package="com.flurgle.camerakit">
-
-
+
+
+
+
+ android:required="false"/>
+ android:required="false"/>
+ android:required="false"/>
-
+
\ No newline at end of file
diff --git a/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java b/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java
index f964d7a5..6d3e9af4 100644
--- a/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java
+++ b/camerakit/src/main/api16/com/flurgle/camerakit/Camera1.java
@@ -5,7 +5,6 @@ import android.graphics.YuvImage;
import android.hardware.Camera;
import android.media.CamcorderProfile;
import android.media.MediaRecorder;
-import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.support.annotation.Nullable;
@@ -16,11 +15,8 @@ import android.view.View;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
+import java.util.Collections;
import java.util.List;
-import java.util.Set;
-import java.util.TreeSet;
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.FOCUS_CONTINUOUS;
@@ -30,7 +26,7 @@ import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STANDARD;
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STILL;
@SuppressWarnings("deprecation")
-public class Camera1 extends CameraImpl {
+class Camera1 extends CameraImpl {
private static final String TAG = Camera1.class.getSimpleName();
@@ -50,35 +46,26 @@ public class Camera1 extends CameraImpl {
private Camera.AutoFocusCallback mAutofocusCallback;
private boolean capturingImage = false;
- private int mDisplayOrientation;
+ private int mDisplayOffset;
+ private int mDeviceOrientation;
- @Facing
- private int mFacing;
-
- @Flash
- private int mFlash;
-
- @Focus
- private int mFocus;
-
- @Method
- private int mMethod;
-
- @Zoom
- private int mZoom;
-
- @VideoQuality
- private int mVideoQuality;
+ @Facing private int mFacing;
+ @Flash private int mFlash;
+ @Focus private int mFocus;
+ @Method private int mMethod;
+ @Zoom private int mZoom;
+ @VideoQuality private int mVideoQuality;
private Handler mHandler = new Handler();
Camera1(CameraListener callback, PreviewImpl preview) {
super(callback, preview);
- preview.setCallback(new PreviewImpl.Callback() {
+ preview.setCallback(new PreviewImpl.OnSurfaceChangedCallback() {
@Override
public void onSurfaceChanged() {
if (mCamera != null) {
setupPreview();
+ collectCameraSizes();
adjustCameraParameters();
}
}
@@ -105,9 +92,32 @@ public class Camera1 extends CameraImpl {
releaseCamera();
}
+ /**
+ * Sets the output stream for our preview.
+ * To be called when preview is ready.
+ */
+ private void setupPreview() {
+ try {
+ if (mPreview.getOutputClass() == SurfaceHolder.class) {
+ mCamera.setPreviewDisplay(mPreview.getSurfaceHolder());
+ } else {
+ mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
+ }
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ @Override
+ void onDisplayOffset(int displayOrientation) {
+ // I doubt this will ever change.
+ this.mDisplayOffset = displayOrientation;
+ }
+
@Override
- void setDisplayOrientation(int displayOrientation) {
- this.mDisplayOrientation = displayOrientation;
+ void onDeviceOrientation(int deviceOrientation) {
+ this.mDeviceOrientation = deviceOrientation;
}
@Override
@@ -217,19 +227,18 @@ public class Camera1 extends CameraImpl {
case METHOD_STANDARD:
// Null check required for camera here as is briefly null when View is detached
if (!capturingImage && mCamera != null) {
-
// Set boolean to wait for image callback
capturingImage = true;
-
+ Camera.Parameters parameters = mCamera.getParameters();
+ parameters.setRotation(computeExifOrientation());
+ mCamera.setParameters(parameters);
mCamera.takePicture(null, null, null,
new Camera.PictureCallback() {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
mCameraListener.onPictureTaken(data);
-
// Reset capturing state to allow photos to be taken
capturingImage = false;
-
camera.startPreview();
}
});
@@ -240,6 +249,7 @@ public class Camera1 extends CameraImpl {
break;
case METHOD_STILL:
+ // TODO: will calculateCaptureRotation work here? It's the only usage. Test...
mCamera.setOneShotPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
@@ -270,79 +280,14 @@ public class Camera1 extends CameraImpl {
mCameraListener.onVideoTaken(mVideoFile);
}
- // Code from SandriosCamera library
- // https://github.com/sandrios/sandriosCamera/blob/master/sandriosCamera/src/main/java/com/sandrios/sandriosCamera/internal/utils/CameraHelper.java#L218
- public static Size getSizeWithClosestRatio(List sizes, int width, int height)
- {
- if (sizes == null) return null;
-
- double MIN_TOLERANCE = 100;
- double targetRatio = (double) height / width;
- Size optimalSize = null;
- double minDiff = Double.MAX_VALUE;
-
- int targetHeight = height;
-
- for (Size size : sizes) {
- if (size.getWidth() == width && size.getHeight() == height)
- return size;
-
- double ratio = (double) size.getHeight() / size.getWidth();
-
- if (Math.abs(ratio - targetRatio) < MIN_TOLERANCE) MIN_TOLERANCE = ratio;
- else continue;
-
- if (Math.abs(size.getHeight() - targetHeight) < minDiff) {
- optimalSize = size;
- minDiff = Math.abs(size.getHeight() - targetHeight);
- }
- }
-
- if (optimalSize == null) {
- minDiff = Double.MAX_VALUE;
- for (Size size : sizes) {
- if (Math.abs(size.getHeight() - targetHeight) < minDiff) {
- optimalSize = size;
- minDiff = Math.abs(size.getHeight() - targetHeight);
- }
- }
- }
- return optimalSize;
- }
-
- List sizesFromList(List sizes) {
- if (sizes == null) return null;
- List result = new ArrayList<>(sizes.size());
-
- for (Camera.Size size : sizes) {
- result.add(new Size(size.width, size.height));
- }
-
- return result;
- }
-
- // Code from SandriosCamera library
- // https://github.com/sandrios/sandriosCamera/blob/master/sandriosCamera/src/main/java/com/sandrios/sandriosCamera/internal/manager/impl/Camera1Manager.java#L212
- void initResolutions() {
- List previewSizes = sizesFromList(mCameraParameters.getSupportedPreviewSizes());
- List videoSizes = (Build.VERSION.SDK_INT > 10) ? sizesFromList(mCameraParameters.getSupportedVideoSizes()) : previewSizes;
-
- CamcorderProfile camcorderProfile = getCamcorderProfile(mVideoQuality);
-
- mCaptureSize = getSizeWithClosestRatio(
- (videoSizes == null || videoSizes.isEmpty()) ? previewSizes : videoSizes,
- camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight);
-
- mPreviewSize = getSizeWithClosestRatio(previewSizes, mCaptureSize.getWidth(), mCaptureSize.getHeight());
- }
@Override
- Size getCaptureResolution() {
+ Size getCaptureSize() {
return mCaptureSize;
}
@Override
- Size getPreviewResolution() {
+ Size getPreviewSize() {
return mPreviewSize;
}
@@ -368,24 +313,12 @@ public class Camera1 extends CameraImpl {
mCameraParameters = mCamera.getParameters();
collectCameraProperties();
+ collectCameraSizes();
adjustCameraParameters();
- mCamera.setDisplayOrientation(calculatePreviewRotation());
-
+ mCamera.setDisplayOrientation(computeCameraToDisplayOffset());
mCameraListener.onCameraOpened();
}
- private void setupPreview() {
- try {
- if (mPreview.getOutputClass() == SurfaceHolder.class) {
- mCamera.setPreviewDisplay(mPreview.getSurfaceHolder());
- } else {
- mCamera.setPreviewTexture(mPreview.getSurfaceTexture());
- }
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
-
private void releaseCamera() {
if (mCamera != null) {
mCamera.release();
@@ -397,48 +330,75 @@ public class Camera1 extends CameraImpl {
}
}
- private int calculatePreviewRotation() {
+ /**
+ * Returns how much should the sensor image be rotated before being shown.
+ * It is meant to be fed to Camera.setDisplayOrientation().
+ */
+ private int computeCameraToDisplayOffset() {
if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
- return ((mCameraInfo.orientation - mDisplayOrientation) + 360 + 180) % 360;
+ // or: (360 - ((info.orientation + displayOrientation) % 360)) % 360;
+ return ((mCameraInfo.orientation - mDisplayOffset) + 360 + 180) % 360;
} else {
- return (mCameraInfo.orientation - mDisplayOrientation + 360) % 360;
+ return (mCameraInfo.orientation - mDisplayOffset + 360) % 360;
}
}
+ /**
+ * Returns the orientation to be set as a exif tag. This is already managed by
+ * the camera APIs as long as you call {@link Camera.Parameters#setRotation(int)}.
+ */
+ private int computeExifOrientation() {
+ return (mDeviceOrientation + mCameraInfo.orientation) % 360;
+ }
+
private int calculateCaptureRotation() {
- int previewRotation = calculatePreviewRotation();
+ int previewRotation = computeCameraToDisplayOffset();
if (mCameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
//Front is flipped
- return (previewRotation + 180 + 2*mDisplayOrientation + 720) %360;
+ return (previewRotation + 180 + 2* mDisplayOffset + 720) % 360;
} else {
return previewRotation;
}
}
- private void adjustCameraParameters() {
- initResolutions();
- boolean invertPreviewSizes = mDisplayOrientation%180 != 0;
- mPreview.setTruePreviewSize(
- invertPreviewSizes? getPreviewResolution().getHeight() : getPreviewResolution().getWidth(),
- invertPreviewSizes? getPreviewResolution().getWidth() : getPreviewResolution().getHeight()
- );
+ /**
+ * This is called either on cameraView.start(), or when the underlying surface changes.
+ * It is possible that in the first call the preview surface has not already computed its
+ * dimensions.
+ * But when it does, the {@link PreviewImpl.OnSurfaceChangedCallback} should be called,
+ * and this should be refreshed.
+ *
+ *
+ * TODO: either camera or video.
+ */
+ private void collectCameraSizes() {
+ List previewSizes = sizesFromList(mCameraParameters.getSupportedPreviewSizes());
+ List captureSizes = sizesFromList(mCameraParameters.getSupportedPictureSizes());
- mCameraParameters.setPreviewSize(
- getPreviewResolution().getWidth(),
- getPreviewResolution().getHeight()
- );
+ /* video stuff: CamcorderProfile camcorderProfile = getCamcorderProfile(mVideoQuality);
+ mCaptureSize = getSizeWithClosestRatio(
+ (videoSizes == null || videoSizes.isEmpty()) ? previewSizes : videoSizes,
+ camcorderProfile.videoFrameWidth, camcorderProfile.videoFrameHeight); */
- mCameraParameters.setPictureSize(
- getCaptureResolution().getWidth(),
- getCaptureResolution().getHeight()
- );
- int rotation = calculateCaptureRotation();
- mCameraParameters.setRotation(rotation);
+ Size surfaceSize = mPreview.getSurfaceSize();
+ mCaptureSize = Collections.max(captureSizes);
+ mPreviewSize = computePreviewSize(previewSizes, mCaptureSize, surfaceSize);
+ }
+
+ private void adjustCameraParameters() {
+ boolean invertPreviewSizes = mDisplayOffset % 180 != 0;
+ mPreview.setDesiredSize(
+ invertPreviewSizes? getPreviewSize().getHeight() : getPreviewSize().getWidth(),
+ invertPreviewSizes? getPreviewSize().getWidth() : getPreviewSize().getHeight()
+ );
+ mCameraParameters.setPreviewSize(getPreviewSize().getWidth(), getPreviewSize().getHeight());
+ mCameraParameters.setPictureSize(getCaptureSize().getWidth(), getCaptureSize().getHeight());
+ // int rotation = calculateCaptureRotation();
+ // mCameraParameters.setRotation(rotation);
setFocus(mFocus);
setFlash(mFlash);
-
mCamera.setParameters(mCameraParameters);
}
@@ -447,28 +407,6 @@ public class Camera1 extends CameraImpl {
mCameraParameters.getHorizontalViewAngle());
}
- private TreeSet findCommonAspectRatios(List previewSizes, List captureSizes) {
- Set previewAspectRatios = new HashSet<>();
- for (Camera.Size size : previewSizes) {
- if (size.width >= CameraKit.Internal.screenHeight && size.height >= CameraKit.Internal.screenWidth) {
- previewAspectRatios.add(AspectRatio.of(size.width, size.height));
- }
- }
-
- Set captureAspectRatios = new HashSet<>();
- for (Camera.Size size : captureSizes) {
- captureAspectRatios.add(AspectRatio.of(size.width, size.height));
- }
-
- TreeSet output = new TreeSet<>();
- for (AspectRatio aspectRatio : previewAspectRatios) {
- if (captureAspectRatios.contains(aspectRatio)) {
- output.add(aspectRatio);
- }
- }
-
- return output;
- }
private void initMediaRecorder() {
mMediaRecorder = new MediaRecorder();
@@ -483,7 +421,7 @@ public class Camera1 extends CameraImpl {
mVideoFile = new File(mPreview.getView().getContext().getExternalFilesDir(null), "video.mp4");
mMediaRecorder.setOutputFile(mVideoFile.getAbsolutePath());
- mMediaRecorder.setOrientationHint(calculatePreviewRotation());
+ mMediaRecorder.setOrientationHint(computeCameraToDisplayOffset());
mMediaRecorder.setVideoSize(mCaptureSize.getWidth(), mCaptureSize.getHeight());
}
@@ -644,7 +582,7 @@ public class Camera1 extends CameraImpl {
if (camera != null) {
camera.cancelAutoFocus();
Camera.Parameters params = camera.getParameters();
- if (params.getFocusMode() != Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE) {
+ if (!params.getFocusMode().equals(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
params.setFocusAreas(null);
params.setMeteringAreas(null);
@@ -684,4 +622,53 @@ public class Camera1 extends CameraImpl {
}
}
+
+
+ // Size static stuff.
+
+ /**
+ * Returns a list of {@link Size} out of Camera.Sizes.
+ */
+ private static List sizesFromList(List sizes) {
+ if (sizes == null) return null;
+ List result = new ArrayList<>(sizes.size());
+ for (Camera.Size size : sizes) {
+ result.add(new Size(size.width, size.height));
+ }
+ return result;
+ }
+
+
+ /**
+ * Policy here is to return a size that is big enough to fit the surface size,
+ * and possibly consistent with the capture size.
+ * @param sizes list of possible sizes
+ * @param captureSize size representing desired aspect ratio
+ * @param surfaceSize size representing the current surface size. We'd like the returned value to be bigger.
+ * @return chosen size
+ */
+ private static Size computePreviewSize(List sizes, Size captureSize, Size surfaceSize) {
+ if (sizes == null) return null;
+
+ List consistent = new ArrayList<>(5);
+ List bigEnoughAndConsistent = new ArrayList<>(5);
+
+ final AspectRatio targetRatio = AspectRatio.of(captureSize.getWidth(), captureSize.getHeight());
+ final Size targetSize = captureSize;
+ for (Size size : sizes) {
+ AspectRatio ratio = AspectRatio.of(size.getWidth(), size.getHeight());
+ if (ratio.equals(targetRatio)) {
+ consistent.add(size);
+ if (size.getHeight() >= targetSize.getHeight() && size.getWidth() >= targetSize.getWidth()) {
+ bigEnoughAndConsistent.add(size);
+ }
+ }
+ }
+
+ if (bigEnoughAndConsistent.size() > 0) return Collections.min(bigEnoughAndConsistent);
+ if (consistent.size() > 0) return Collections.max(consistent);
+ return Collections.max(sizes);
+ }
+
+
}
diff --git a/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java b/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java
index 828c01bb..c4a37257 100644
--- a/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java
+++ b/camerakit/src/main/api21/com/flurgle/camerakit/Camera2.java
@@ -3,7 +3,6 @@ package com.flurgle.camerakit;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.ImageFormat;
-import android.graphics.PointF;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
@@ -36,7 +35,7 @@ class Camera2 extends CameraImpl {
Camera2(CameraListener callback, PreviewImpl preview, Context context) {
super(callback, preview);
- preview.setCallback(new PreviewImpl.Callback() {
+ preview.setCallback(new PreviewImpl.OnSurfaceChangedCallback() {
@Override
public void onSurfaceChanged() {
@@ -89,7 +88,12 @@ class Camera2 extends CameraImpl {
}
@Override
- void setDisplayOrientation(int displayOrientation) {
+ void onDisplayOffset(int displayOrientation) {
+
+ }
+
+ @Override
+ void onDeviceOrientation(int deviceOrientation) {
}
@@ -176,7 +180,7 @@ class Camera2 extends CameraImpl {
}
@Override
- Size getCaptureResolution() {
+ Size getCaptureSize() {
if (mCaptureSize == null && mCameraCharacteristics != null) {
TreeSet sizes = new TreeSet<>();
sizes.addAll(getAvailableCaptureResolutions());
@@ -202,7 +206,7 @@ class Camera2 extends CameraImpl {
}
@Override
- Size getPreviewResolution() {
+ Size getPreviewSize() {
if (mPreviewSize == null && mCameraCharacteristics != null) {
TreeSet sizes = new TreeSet<>();
sizes.addAll(getAvailablePreviewResolutions());
diff --git a/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java b/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java
index 5a5aecc8..72c4e2f7 100644
--- a/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java
+++ b/camerakit/src/main/base/com/flurgle/camerakit/CameraImpl.java
@@ -15,7 +15,8 @@ abstract class CameraImpl {
abstract void start();
abstract void stop();
- abstract void setDisplayOrientation(int displayOrientation);
+ abstract void onDisplayOffset(int displayOrientation);
+ abstract void onDeviceOrientation(int deviceOrientation);
abstract void setFacing(@Facing int facing);
abstract void setFlash(@Flash int flash);
@@ -28,8 +29,8 @@ abstract class CameraImpl {
abstract void startVideo();
abstract void endVideo();
- abstract Size getCaptureResolution();
- abstract Size getPreviewResolution();
+ abstract Size getCaptureSize();
+ abstract Size getPreviewSize();
abstract boolean isCameraOpened();
@Nullable
diff --git a/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java b/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java
index 6afcb182..81e50edd 100644
--- a/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java
+++ b/camerakit/src/main/base/com/flurgle/camerakit/PreviewImpl.java
@@ -7,20 +7,22 @@ import android.view.View;
abstract class PreviewImpl {
- interface Callback {
+ interface OnSurfaceChangedCallback {
void onSurfaceChanged();
}
- private Callback mCallback;
+ private OnSurfaceChangedCallback mOnSurfaceChangedCallback;
- private int mWidth;
- private int mHeight;
+ // As far as I can see, these are the view/surface dimensions.
+ private int mSurfaceWidth;
+ private int mSurfaceHeight;
- protected int mTrueWidth;
- protected int mTrueHeight;
+ // As far as I can see, these are the actual preview dimensions, as set in CameraParameters.
+ private int mDesiredWidth;
+ private int mDesiredHeight;
- void setCallback(Callback callback) {
- mCallback = callback;
+ void setCallback(OnSurfaceChangedCallback callback) {
+ mOnSurfaceChangedCallback = callback;
}
abstract Surface getSurface();
@@ -29,12 +31,13 @@ abstract class PreviewImpl {
abstract Class getOutputClass();
- abstract void setDisplayOrientation(int displayOrientation);
+ protected void onDisplayOffset(int displayOrientation) {}
+ protected void onDeviceOrientation(int deviceOrientation) {}
abstract boolean isReady();
protected void dispatchSurfaceChanged() {
- mCallback.onSurfaceChanged();
+ mOnSurfaceChangedCallback.onSurfaceChanged();
}
SurfaceHolder getSurfaceHolder() {
@@ -45,30 +48,37 @@ abstract class PreviewImpl {
return null;
}
- void setSize(int width, int height) {
- mWidth = width;
- mHeight = height;
-
- // Refresh true preview size to adjust scaling
- setTruePreviewSize(mTrueWidth, mTrueHeight);
+ // As far as I can see, these are the view/surface dimensions.
+ // This is called by subclasses.
+ protected void setSurfaceSize(int width, int height) {
+ this.mSurfaceWidth = width;
+ this.mSurfaceHeight = height;
+ refreshScale(); // Refresh true preview size to adjust scaling
}
- int getWidth() {
- return mWidth;
+ // As far as I can see, these are the actual preview dimensions, as set in CameraParameters.
+ // This is called by the CameraImpl.
+ void setDesiredSize(int width, int height) {
+ this.mDesiredWidth = width;
+ this.mDesiredHeight = height;
+ refreshScale();
}
- int getHeight() {
- return mHeight;
+ Size getSurfaceSize() {
+ return new Size(mSurfaceWidth, mSurfaceHeight);
}
- void setTruePreviewSize(final int width, final int height) {
- this.mTrueWidth = width;
- this.mTrueHeight = height;
+ /**
+ * 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.
+ */
+ protected void refreshScale() {
getView().post(new Runnable() {
@Override
public void run() {
- if (width != 0 && height != 0) {
- AspectRatio aspectRatio = AspectRatio.of(width, height);
+ if (mDesiredWidth != 0 && mDesiredHeight != 0) {
+ AspectRatio aspectRatio = AspectRatio.of(mDesiredWidth, mDesiredHeight);
int targetHeight = (int) (getView().getWidth() * aspectRatio.toFloat());
float scaleY;
if (getView().getHeight() > 0) {
@@ -88,13 +98,4 @@ abstract class PreviewImpl {
}
});
}
-
- int getTrueWidth() {
- return mTrueWidth;
- }
-
- int getTrueHeight() {
- return mTrueHeight;
- }
-
}
diff --git a/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java b/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java
index 4f2e226d..b717c1d1 100644
--- a/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java
+++ b/camerakit/src/main/base/com/flurgle/camerakit/TextureViewPreview.java
@@ -13,8 +13,6 @@ class TextureViewPreview extends PreviewImpl {
private final TextureView mTextureView;
- private int mDisplayOrientation;
-
TextureViewPreview(Context context, ViewGroup parent) {
final View view = View.inflate(context, R.layout.texture_view, parent);
mTextureView = (TextureView) view.findViewById(R.id.texture_view);
@@ -22,20 +20,20 @@ class TextureViewPreview extends PreviewImpl {
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
- setSize(width, height);
+ setSurfaceSize(width, height);
dispatchSurfaceChanged();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
- setSize(width, height);
+ setSurfaceSize(width, height);
dispatchSurfaceChanged();
- setTruePreviewSize(mTrueWidth, mTrueHeight);
+ refreshScale();
}
@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
- setSize(0, 0);
+ setSurfaceSize(0, 0);
return true;
}
@@ -45,11 +43,6 @@ class TextureViewPreview extends PreviewImpl {
});
}
- @Override
- void setCallback(Callback callback) {
- super.setCallback(callback);
- }
-
@Override
Surface getSurface() {
return new Surface(mTextureView.getSurfaceTexture());
@@ -65,21 +58,11 @@ class TextureViewPreview extends PreviewImpl {
return SurfaceTexture.class;
}
- @Override
- void setDisplayOrientation(int displayOrientation) {
- mDisplayOrientation = displayOrientation;
- }
-
@Override
boolean isReady() {
return mTextureView.getSurfaceTexture() != null;
}
- @Override
- protected void dispatchSurfaceChanged() {
- super.dispatchSurfaceChanged();
- }
-
@Override
SurfaceTexture getSurfaceTexture() {
return mTextureView.getSurfaceTexture();
@@ -87,8 +70,8 @@ class TextureViewPreview extends PreviewImpl {
@TargetApi(15)
@Override
- void setTruePreviewSize(int width, int height) {
- super.setTruePreviewSize(width, height);
+ void setDesiredSize(int width, int height) {
+ super.setDesiredSize(width, height);
if (mTextureView.getSurfaceTexture() != null) {
mTextureView.getSurfaceTexture().setDefaultBufferSize(width, height);
}
diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java
index bce758db..033ae806 100644
--- a/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java
+++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraKit.java
@@ -4,16 +4,9 @@ import android.content.res.Resources;
public class CameraKit {
- static class Internal {
-
- static final int screenWidth = Resources.getSystem().getDisplayMetrics().widthPixels;
- static final int screenHeight = Resources.getSystem().getDisplayMetrics().heightPixels;
-
- }
-
public static class Constants {
- public static final int PERMISSION_REQUEST_CAMERA = 16;
+ public static final int PERMISSION_REQUEST_CODE = 16;
public static final int FACING_BACK = 0;
public static final int FACING_FRONT = 1;
@@ -35,9 +28,21 @@ public class CameraKit {
public static final int METHOD_STILL = 1;
public static final int METHOD_SPEED = 2;
- public static final int PERMISSIONS_STRICT = 0;
- public static final int PERMISSIONS_LAZY = 1;
- public static final int PERMISSIONS_PICTURE = 2;
+
+ /**
+ * This means the app will be requesting Camera and Audio permissions on Marshmallow+.
+ * With this configuration, it is mandatory that the developer adds
+ *
+ * to its manifest, or the app will crash.
+ */
+ public static final int PERMISSIONS_VIDEO = 0;
+
+ /**
+ * This means the app will be requesting the Camera permissions on Marshmallow+.
+ * On older APIs, this is not important, since the Camera permission is already
+ * declared in the manifest by the library.
+ */
+ public static final int PERMISSIONS_PICTURE = 1;
public static final int VIDEO_QUALITY_480P = 0;
public static final int VIDEO_QUALITY_720P = 1;
@@ -56,7 +61,7 @@ public class CameraKit {
static final int DEFAULT_FOCUS = Constants.FOCUS_CONTINUOUS;
static final int DEFAULT_ZOOM = Constants.ZOOM_OFF;
static final int DEFAULT_METHOD = Constants.METHOD_STANDARD;
- static final int DEFAULT_PERMISSIONS = Constants.PERMISSIONS_STRICT;
+ static final int DEFAULT_PERMISSIONS = Constants.PERMISSIONS_PICTURE;
static final int DEFAULT_VIDEO_QUALITY = Constants.VIDEO_QUALITY_480P;
static final int DEFAULT_JPEG_QUALITY = 100;
diff --git a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java
index bba800e6..6bcea31c 100644
--- a/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java
+++ b/camerakit/src/main/java/com/flurgle/camerakit/CameraView.java
@@ -8,6 +8,7 @@ import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.OnLifecycleEvent;
import android.content.Context;
import android.content.ContextWrapper;
+import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.TypedArray;
import android.graphics.Rect;
@@ -18,12 +19,12 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
-import android.support.v4.hardware.display.DisplayManagerCompat;
-import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
+import android.view.WindowManager;
import android.widget.FrameLayout;
import java.io.ByteArrayOutputStream;
@@ -38,9 +39,8 @@ import static com.flurgle.camerakit.CameraKit.Constants.FLASH_OFF;
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_ON;
import static com.flurgle.camerakit.CameraKit.Constants.FLASH_TORCH;
import static com.flurgle.camerakit.CameraKit.Constants.METHOD_STANDARD;
-import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_LAZY;
import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_PICTURE;
-import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_STRICT;
+import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_VIDEO;
/**
* The CameraView implements the LifecycleObserver interface for ease of use. To take advantage of
@@ -58,46 +58,37 @@ import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_STRICT;
*/
public class CameraView extends FrameLayout implements LifecycleObserver {
+ private final static String TAG = CameraView.class.getSimpleName();
+
private static Handler sWorkerHandler;
- static {
- // Initialize a single worker thread. This can be static since only a single camera
- // reference can exist at a time.
- HandlerThread workerThread = new HandlerThread("CameraViewWorker");
- workerThread.setDaemon(true);
- workerThread.start();
- sWorkerHandler = new Handler(workerThread.getLooper());
+ private static Handler getWorkerHandler() {
+ if (sWorkerHandler == null) {
+ HandlerThread workerThread = new HandlerThread("CameraViewWorker");
+ workerThread.setDaemon(true);
+ workerThread.start();
+ sWorkerHandler = new Handler(workerThread.getLooper());
+ }
+ return sWorkerHandler;
}
- @Facing
- private int mFacing;
-
- @Flash
- private int mFlash;
-
- @Focus
- private int mFocus;
-
- @Method
- private int mMethod;
-
- @Zoom
- private int mZoom;
-
- @Permissions
- private int mPermissions;
+ private void run(Runnable runnable) {
+ getWorkerHandler().post(runnable);
+ }
- @VideoQuality
- private int mVideoQuality;
+ @Facing private int mFacing;
+ @Flash private int mFlash;
+ @Focus private int mFocus;
+ @Method private int mMethod;
+ @Zoom private int mZoom;
+ @Permissions private int mPermissions;
+ @VideoQuality private int mVideoQuality;
private int mJpegQuality;
private boolean mCropOutput;
-
private boolean mAdjustViewBounds;
private CameraListenerMiddleWare mCameraListener;
-
- private DisplayOrientationDetector mDisplayOrientationDetector;
+ private OrientationHelper mOrientationHelper;
private CameraImpl mCameraImpl;
-
private PreviewImpl mPreviewImpl;
private Lifecycle mLifecycle;
@@ -108,7 +99,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
init(context, null);
}
- @SuppressWarnings("all")
public CameraView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
@@ -117,11 +107,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
@SuppressWarnings("WrongConstant")
private void init(@NonNull Context context, @Nullable AttributeSet attrs) {
if (attrs != null) {
- TypedArray a = context.getTheme().obtainStyledAttributes(
- attrs,
- R.styleable.CameraView,
- 0, 0);
-
+ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CameraView, 0, 0);
try {
mFacing = a.getInteger(R.styleable.CameraView_ckFacing, CameraKit.Defaults.DEFAULT_FACING);
mFlash = a.getInteger(R.styleable.CameraView_ckFlash, CameraKit.Defaults.DEFAULT_FLASH);
@@ -149,15 +135,21 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
setFocus(mFocus);
setMethod(mMethod);
setZoom(mZoom);
- setPermissions(mPermissions);
+ setPermissionPolicy(mPermissions);
setVideoQuality(mVideoQuality);
if (!isInEditMode()) {
- mDisplayOrientationDetector = new DisplayOrientationDetector(context) {
+ mOrientationHelper = new OrientationHelper(context) {
@Override
- public void onDisplayOrientationChanged(int displayOrientation) {
- mCameraImpl.setDisplayOrientation(displayOrientation);
- mPreviewImpl.setDisplayOrientation(displayOrientation);
+ public void onDisplayOffsetChanged(int displayOffset) {
+ mCameraImpl.onDisplayOffset(displayOffset);
+ mPreviewImpl.onDisplayOffset(displayOffset);
+ }
+
+ @Override
+ protected void onDeviceOrientationChanged(int deviceOrientation) {
+ mCameraImpl.onDeviceOrientation(deviceOrientation);
+ mPreviewImpl.onDeviceOrientation(deviceOrientation);
}
};
@@ -167,7 +159,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
@Override
public boolean onTouch(View v, MotionEvent motionEvent) {
int action = motionEvent.getAction();
- if (motionEvent.getAction() == MotionEvent.ACTION_UP && mFocus == CameraKit.Constants.FOCUS_TAP_WITH_MARKER) {
+ if (action == MotionEvent.ACTION_UP && mFocus == CameraKit.Constants.FOCUS_TAP_WITH_MARKER) {
focusMarkerLayout.focus(motionEvent.getX(), motionEvent.getY());
}
@@ -182,55 +174,69 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
+ Log.e(TAG, "onAttachedToWindow");
if (!isInEditMode()) {
- mDisplayOrientationDetector.enable(
- ViewCompat.isAttachedToWindow(this)
- ? DisplayManagerCompat.getInstance(getContext())
- .getDisplay(Display.DEFAULT_DISPLAY)
- : null
- );
+ Log.e(TAG, "onAttachedToWindow: enabling orientation detector.");
+ WindowManager manager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
+ Display display = manager.getDefaultDisplay();
+ mOrientationHelper.enable(display);
}
}
@Override
protected void onDetachedFromWindow() {
+ Log.e(TAG, "onDetachedFromWindow");
if (!isInEditMode()) {
- mDisplayOrientationDetector.disable();
+ Log.e(TAG, "onDetachedFromWindow: disabling orientation detector.");
+ mOrientationHelper.disable();
}
super.onDetachedFromWindow();
}
+
+ /**
+ * If {@link CameraView#mAdjustViewBounds} 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()}.
+ *
+ * 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()}.
+ */
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- if (mAdjustViewBounds) {
- Size previewSize = getPreviewSize();
- if (previewSize != null) {
- if (getLayoutParams().width == LayoutParams.WRAP_CONTENT) {
- int height = MeasureSpec.getSize(heightMeasureSpec);
- float ratio = (float) height / (float) previewSize.getWidth();
- int width = (int) (previewSize.getHeight() * ratio);
- super.onMeasure(
- MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- heightMeasureSpec
- );
- return;
- } else if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
- int width = MeasureSpec.getSize(widthMeasureSpec);
- float ratio = (float) width / (float) previewSize.getHeight();
- int height = (int) (previewSize.getWidth() * ratio);
- super.onMeasure(
- widthMeasureSpec,
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
- );
- return;
- }
- } else {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- return;
- }
+ if (!mAdjustViewBounds) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ return;
+ }
+
+ Size previewSize = getPreviewSize();
+ if (previewSize == null) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ return;
}
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ if (getLayoutParams().width == LayoutParams.WRAP_CONTENT) {
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ float ratio = (float) height / (float) previewSize.getWidth();
+ int width = (int) (previewSize.getHeight() * ratio);
+ super.onMeasure(
+ MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ heightMeasureSpec
+ );
+
+ } else if (getLayoutParams().height == LayoutParams.WRAP_CONTENT) {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ float ratio = (float) width / (float) previewSize.getHeight();
+ int height = (int) (previewSize.getWidth() * ratio);
+ super.onMeasure(
+ widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
+ );
+
+ } else {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
}
public boolean isStarted() {
@@ -263,30 +269,29 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
stop();
}
+ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
+ public void onDestroy(LifecycleOwner owner) {
+ mLifecycle = owner.getLifecycle();
+ // This might be useless, but no time to think about it now.
+ sWorkerHandler = null;
+ }
+
public void start() {
if (mIsStarted || !isEnabled()) {
// Already started, do nothing.
return;
}
- mIsStarted = true;
+ checkPermissionPolicyOrThrow();
int cameraCheck = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA);
int audioCheck = ContextCompat.checkSelfPermission(getContext(), Manifest.permission.RECORD_AUDIO);
-
switch (mPermissions) {
- case PERMISSIONS_STRICT:
+ case PERMISSIONS_VIDEO:
if (cameraCheck != PackageManager.PERMISSION_GRANTED || audioCheck != PackageManager.PERMISSION_GRANTED) {
requestPermissions(true, true);
return;
}
break;
- case PERMISSIONS_LAZY:
- if (cameraCheck != PackageManager.PERMISSION_GRANTED) {
- requestPermissions(true, true);
- return;
- }
- break;
-
case PERMISSIONS_PICTURE:
if (cameraCheck != PackageManager.PERMISSION_GRANTED) {
requestPermissions(true, false);
@@ -295,7 +300,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
break;
}
- sWorkerHandler.post(new Runnable() {
+ mIsStarted = true;
+ run(new Runnable() {
@Override
public void run() {
mCameraImpl.start();
@@ -325,7 +331,7 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
public void setFacing(@Facing final int facing) {
this.mFacing = facing;
- sWorkerHandler.post(new Runnable() {
+ run(new Runnable() {
@Override
public void run() {
mCameraImpl.setFacing(facing);
@@ -363,8 +369,13 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraImpl.setZoom(mZoom);
}
- public void setPermissions(@Permissions int permissions) {
+ /**
+ * Sets permission policy.
+ * @param permissions desired policy, either picture or video.
+ */
+ public void setPermissionPolicy(@Permissions int permissions) {
this.mPermissions = permissions;
+ checkPermissionPolicyOrThrow();
}
public void setVideoQuality(@VideoQuality int videoQuality) {
@@ -431,12 +442,18 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraImpl.endVideo();
}
+ /**
+ * Returns the size used for the preview,
+ * or null if it hasn't been computed (for example if the surface is not ready).
+ */
+ @Nullable
public Size getPreviewSize() {
- return mCameraImpl != null ? mCameraImpl.getPreviewResolution() : null;
+ return mCameraImpl != null ? mCameraImpl.getPreviewSize() : null;
}
+ @Nullable
public Size getCaptureSize() {
- return mCameraImpl != null ? mCameraImpl.getCaptureResolution() : null;
+ return mCameraImpl != null ? mCameraImpl.getCaptureSize() : null;
}
private void requestPermissions(boolean requestCamera, boolean requestAudio) {
@@ -452,12 +469,10 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
List permissions = new ArrayList<>();
if (requestCamera) permissions.add(Manifest.permission.CAMERA);
if (requestAudio) permissions.add(Manifest.permission.RECORD_AUDIO);
-
if (activity != null) {
- ActivityCompat.requestPermissions(
- activity,
+ ActivityCompat.requestPermissions(activity,
permissions.toArray(new String[permissions.size()]),
- CameraKit.Constants.PERMISSION_REQUEST_CAMERA);
+ CameraKit.Constants.PERMISSION_REQUEST_CODE);
}
}
@@ -481,8 +496,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
public void onPictureTaken(byte[] jpeg) {
super.onPictureTaken(jpeg);
if (mCropOutput) {
- int width = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureResolution().getWidth() : mCameraImpl.getPreviewResolution().getWidth();
- int height = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureResolution().getHeight() : mCameraImpl.getPreviewResolution().getHeight();
+ int width = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureSize().getWidth() : mCameraImpl.getPreviewSize().getWidth();
+ int height = mMethod == METHOD_STANDARD ? mCameraImpl.getCaptureSize().getHeight() : mCameraImpl.getPreviewSize().getHeight();
AspectRatio outputRatio = AspectRatio.of(getWidth(), getHeight());
getCameraListener().onPictureTaken(new CenterCrop(jpeg, outputRatio, mJpegQuality).getJpeg());
} else {
@@ -521,4 +536,29 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
+ /**
+ * If mPermissions == PERMISSIONS_VIDEO we will ask for RECORD_AUDIO permission.
+ * If the developer did not add this to its manifest, throw and fire warnings.
+ * (Hoping this is not cought elsewhere... we should test).
+ */
+ private void checkPermissionPolicyOrThrow() {
+ if (mPermissions == PERMISSIONS_VIDEO) {
+ try {
+ PackageManager manager = getContext().getPackageManager();
+ PackageInfo info = manager.getPackageInfo(getContext().getPackageName(), PackageManager.GET_PERMISSIONS);
+ for (String requestedPermission : info.requestedPermissions) {
+ if (requestedPermission.equals(Manifest.permission.RECORD_AUDIO)) {
+ return;
+ }
+ }
+ String message = "When the permission policy is PERMISSION_VIDEO, the RECORD_AUDIO permission " +
+ "should be added to the application manifest file.";
+ Log.w(TAG, message);
+ throw new IllegalStateException(message);
+ } catch (PackageManager.NameNotFoundException e) {
+ // Not possible.
+ }
+ }
+ }
+
}
diff --git a/camerakit/src/main/types/com/flurgle/camerakit/Permissions.java b/camerakit/src/main/types/com/flurgle/camerakit/Permissions.java
index f3588f1d..6060c3b3 100644
--- a/camerakit/src/main/types/com/flurgle/camerakit/Permissions.java
+++ b/camerakit/src/main/types/com/flurgle/camerakit/Permissions.java
@@ -5,11 +5,10 @@ import android.support.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_LAZY;
import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_PICTURE;
-import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_STRICT;
+import static com.flurgle.camerakit.CameraKit.Constants.PERMISSIONS_VIDEO;
@Retention(RetentionPolicy.SOURCE)
-@IntDef({PERMISSIONS_STRICT, PERMISSIONS_LAZY, PERMISSIONS_PICTURE})
+@IntDef({PERMISSIONS_VIDEO, PERMISSIONS_PICTURE})
public @interface Permissions {
}
diff --git a/camerakit/src/main/utils/com/flurgle/camerakit/CommonAspectRatioFilter.java b/camerakit/src/main/utils/com/flurgle/camerakit/CommonAspectRatioFilter.java
index b0cc9d21..4f46c5e8 100644
--- a/camerakit/src/main/utils/com/flurgle/camerakit/CommonAspectRatioFilter.java
+++ b/camerakit/src/main/utils/com/flurgle/camerakit/CommonAspectRatioFilter.java
@@ -18,9 +18,7 @@ public class CommonAspectRatioFilter {
public TreeSet filter() {
Set previewAspectRatios = new HashSet<>();
for (Size size : mPreviewSizes) {
- if (size.getWidth() >= CameraKit.Internal.screenHeight && size.getHeight() >= CameraKit.Internal.screenWidth) {
- previewAspectRatios.add(AspectRatio.of(size.getWidth(), size.getHeight()));
- }
+ previewAspectRatios.add(AspectRatio.of(size.getWidth(), size.getHeight()));
}
Set captureAspectRatios = new HashSet<>();
diff --git a/camerakit/src/main/utils/com/flurgle/camerakit/DisplayOrientationDetector.java b/camerakit/src/main/utils/com/flurgle/camerakit/DisplayOrientationDetector.java
deleted file mode 100644
index 28caef8a..00000000
--- a/camerakit/src/main/utils/com/flurgle/camerakit/DisplayOrientationDetector.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package com.flurgle.camerakit;
-
-import android.content.Context;
-import android.util.SparseIntArray;
-import android.view.Display;
-import android.view.OrientationEventListener;
-import android.view.Surface;
-
-public abstract class DisplayOrientationDetector {
-
- private final OrientationEventListener mOrientationEventListener;
-
- static final SparseIntArray DISPLAY_ORIENTATIONS = new SparseIntArray();
- static {
- DISPLAY_ORIENTATIONS.put(Surface.ROTATION_0, 0);
- DISPLAY_ORIENTATIONS.put(Surface.ROTATION_90, 90);
- DISPLAY_ORIENTATIONS.put(Surface.ROTATION_180, 180);
- DISPLAY_ORIENTATIONS.put(Surface.ROTATION_270, 270);
- }
-
- private Display mDisplay;
-
- private int mLastKnownDisplayOrientation = 0;
-
- public DisplayOrientationDetector(Context context) {
- mOrientationEventListener = new OrientationEventListener(context) {
-
- private int mLastKnownRotation = -1;
-
- @Override
- public void onOrientationChanged(int orientation) {
- if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN || mDisplay == null) {
- return;
- }
-
- final int rotation = mDisplay.getRotation();
- if (mLastKnownRotation != rotation) {
- mLastKnownRotation = rotation;
- dispatchOnDisplayOrientationChanged(DISPLAY_ORIENTATIONS.get(rotation));
- }
- }
-
- };
- }
-
- public void enable(Display display) {
- mDisplay = display;
- mOrientationEventListener.enable();
- dispatchOnDisplayOrientationChanged(DISPLAY_ORIENTATIONS.get(display.getRotation()));
- }
-
- public void disable() {
- mOrientationEventListener.disable();
- mDisplay = null;
- }
-
- public int getLastKnownDisplayOrientation() {
- return mLastKnownDisplayOrientation;
- }
-
- void dispatchOnDisplayOrientationChanged(int displayOrientation) {
- mLastKnownDisplayOrientation = displayOrientation;
- onDisplayOrientationChanged(displayOrientation);
- }
-
- public abstract void onDisplayOrientationChanged(int displayOrientation);
-
-}
\ No newline at end of file
diff --git a/camerakit/src/main/utils/com/flurgle/camerakit/OrientationHelper.java b/camerakit/src/main/utils/com/flurgle/camerakit/OrientationHelper.java
new file mode 100644
index 00000000..b0eb969f
--- /dev/null
+++ b/camerakit/src/main/utils/com/flurgle/camerakit/OrientationHelper.java
@@ -0,0 +1,81 @@
+package com.flurgle.camerakit;
+
+import android.content.Context;
+import android.hardware.SensorManager;
+import android.media.ExifInterface;
+import android.util.SparseIntArray;
+import android.view.Display;
+import android.view.OrientationEventListener;
+import android.view.Surface;
+
+abstract class OrientationHelper {
+
+ private final OrientationEventListener mOrientationEventListener;
+
+ private static final SparseIntArray DISPLAY_ORIENTATIONS = new SparseIntArray();
+ static {
+ DISPLAY_ORIENTATIONS.put(Surface.ROTATION_0, 0);
+ DISPLAY_ORIENTATIONS.put(Surface.ROTATION_90, 90);
+ DISPLAY_ORIENTATIONS.put(Surface.ROTATION_180, 180);
+ DISPLAY_ORIENTATIONS.put(Surface.ROTATION_270, 270);
+ }
+
+ private Display mDisplay;
+
+ private int mLastKnownDisplayOffset = -1;
+ private int mLastOrientation = -1;
+
+ OrientationHelper(Context context) {
+ mOrientationEventListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) {
+
+ @Override
+ public void onOrientationChanged(int orientation) {
+ int or = 0;
+ if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
+ or = 0;
+ } else if (orientation >= 315 || orientation < 45) {
+ or = 0;
+ } else if (orientation >= 45 && orientation < 135) {
+ or = 90;
+ } else if (orientation >= 135 && orientation < 225) {
+ or = 180;
+ } else if (orientation >= 225 && orientation < 315) {
+ or = 270;
+ }
+
+ if (or != mLastOrientation) {
+ mLastOrientation = or;
+ onDeviceOrientationChanged(mLastOrientation);
+ }
+
+ // Let's see if display rotation has changed.. but how could it ever change...??
+ // This makes no sense apparently. I'll leave it for now.
+ if (mDisplay != null) {
+ final int offset = mDisplay.getRotation();
+ if (mLastKnownDisplayOffset != offset) {
+ mLastKnownDisplayOffset = offset;
+ onDisplayOffsetChanged(DISPLAY_ORIENTATIONS.get(offset));
+ }
+ }
+ }
+
+ };
+ }
+
+ void enable(Display display) {
+ mDisplay = display;
+ mOrientationEventListener.enable();
+ mLastKnownDisplayOffset = DISPLAY_ORIENTATIONS.get(display.getRotation());
+ onDisplayOffsetChanged(mLastKnownDisplayOffset);
+ }
+
+ void disable() {
+ mOrientationEventListener.disable();
+ mDisplay = null;
+ }
+
+ protected abstract void onDisplayOffsetChanged(int displayOffset);
+
+ protected abstract void onDeviceOrientationChanged(int deviceOrientation);
+
+}
\ No newline at end of file