diff --git a/README.md b/README.md index 6997c48c..6c00663a 100644 --- a/README.md +++ b/README.md @@ -305,7 +305,7 @@ Most camera parameters can be controlled through XML attributes or linked method |[`cameraFlash`](#cameraflash)|`setFlash()`|`off` `on` `auto` `torch`|`off`| |[`cameraGrid`](#cameragrid)|`setGrid()`|`off` `draw3x3` `draw4x4` `drawPhi`|`off`| |[`cameraCropOutput`](#cameracropoutput)|`setCropOutput()`|`true` `false`|`false`| -|[`cameraJpegQuality`](#camerajpegquality)|`setJpegQuality()`|`0 <= n <= 100`|`100`| +|[`cameraJpegQuality`](#camerajpegquality)|`setJpegQuality()`|`0 < n <= 100`|`100`| |[`cameraVideoQuality`](#cameravideoquality)|`setVideoQuality()`|`lowest` `highest` `maxQvga` `max480p` `max720p` `max1080p` `max2160p`|`max480p`| |[`cameraWhiteBalance`](#camerawhitebalance)|`setWhiteBalance()`|`auto` `incandescent` `fluorescent` `daylight` `cloudy`|`auto`| |[`cameraHdr`](#camerahdr)|`setHdr()`|`off` `on`|`off`| @@ -427,7 +427,7 @@ Other APIs not mentioned above are provided, and are well documented and comment |`getSnapshotSize()`|Returns `getPreviewSize()`, since a snapshot is a preview frame.| |`getPictureSize()`|Returns the size of the output picture. The aspect ratio is consistent with `getPreviewSize()`.| -Take also a look at public methods in `CameraUtils`, `CameraOptions`, `ExtraProperties`. +Take also a look at public methods in `CameraUtils`, `CameraOptions`, `ExtraProperties`, `CameraLogger`. ## Permissions behavior @@ -464,6 +464,7 @@ This is what was done since the library was forked. I have kept the original str - *a huge number of serious bugs fixed* - *decent orientation support for both pictures and videos* +- *less dependencies* - *EXIF support* - *real tap-to-focus support* - *pinch-to-zoom support* @@ -477,30 +478,23 @@ This is what was done since the library was forked. I have kept the original str - *smart measuring and sizing behavior, replacing bugged `adjustViewBounds`* - *measure `CameraView` as center crop or center inside* - *add multiple `CameraListener`s for events* -- *gesture framework support* +- *gesture framework support, map gestures to camera controls* +- *pinch gesture support* +- *tap & long tap gesture support* - *scroll gestures support* - *MediaActionSound support* - *Hdr controls* +- *zoom and exposure correction controls* +- *Tests!* +- *`CameraLogger` APIs for logging and bug reports* +- *Better threading, start() in worker thread and callbacks in UI* These are still things that need to be done, off the top of my head: -- [x] fix CropOutput class presumably not working on rotated pictures -- [x] test video and 'frame' capture behavior, I expect some bugs there -- [x] simple APIs to draw grid lines -- [x] check focus, not sure it exposes the right part of the image -- [x] replace setCameraListener() with addCameraListener() -- [x] better threading, for example ensure callbacks are called in the ui thread -- [x] pinch to zoom support -- [x] exposure correction APIs -- [x] change demo app icon -- [x] refactor package name -- [x] new Gestures framework to map gestures to camera controls -- [x] heavily reduced dependencies - [ ] `Camera2` integration -- [x] publish to bintray - [ ] check onPause / onStop / onSaveInstanceState consistency - [ ] add a `setPreferredAspectRatio` API to choose the capture size. Preview size will adapt, and then, if let free, the CameraView will adapt as well - [ ] animate grid lines similar to stock camera app - [ ] add onRequestPermissionResults for easy permission callback - [ ] better error handling, maybe with a onError(e) method in the public listener, or have each public method return a boolean - +- [ ] decent code coverage diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraLoggerTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraLoggerTest.java new file mode 100644 index 00000000..82a72f3f --- /dev/null +++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraLoggerTest.java @@ -0,0 +1,57 @@ +package com.otaliastudios.cameraview; + + +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class CameraLoggerTest { + + @Test + public void testLoggerLevels() { + CameraLogger logger = CameraLogger.create("logger"); + + // Verbose + CameraLogger.setLogLevel(CameraLogger.LEVEL_VERBOSE); + logger.i("i"); + assertEquals(CameraLogger.lastMessage, "i"); + logger.w("w"); + assertEquals(CameraLogger.lastMessage, "w"); + logger.e("e"); + assertEquals(CameraLogger.lastMessage, "e"); + + // Warning + CameraLogger.lastMessage = null; + CameraLogger.setLogLevel(CameraLogger.LEVEL_WARNING); + logger.i("i"); + assertNull(CameraLogger.lastMessage); + logger.w("w"); + assertEquals(CameraLogger.lastMessage, "w"); + logger.e("e"); + assertEquals(CameraLogger.lastMessage, "e"); + + // Error + CameraLogger.lastMessage = null; + CameraLogger.setLogLevel(CameraLogger.LEVEL_ERROR); + logger.i("i"); + assertNull(CameraLogger.lastMessage); + logger.w("w"); + assertNull(CameraLogger.lastMessage); + logger.e("e"); + assertEquals(CameraLogger.lastMessage, "e"); + } + + @Test + public void testLoggerObjectArray() { + CameraLogger.setLogLevel(CameraLogger.LEVEL_VERBOSE); + CameraLogger logger = CameraLogger.create("logger"); + logger.i("test", "logger", 10, null); + assertEquals(CameraLogger.lastMessage, "test logger 10 null"); + } +} diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java index 7578c031..8d842275 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera1.java @@ -26,6 +26,7 @@ import java.util.List; class Camera1 extends CameraController { private static final String TAG = Camera1.class.getSimpleName(); + private static final CameraLogger LOG = CameraLogger.create(TAG); private int mCameraId; private Camera mCamera; @@ -68,7 +69,7 @@ class Camera1 extends CameraController { */ @Override public void onSurfaceAvailable() { - Log.e(TAG, "onSurfaceAvailable, size is "+mPreview.getSurfaceSize()); + LOG.i("onSurfaceAvailable, size is", mPreview.getSurfaceSize()); if (shouldSetup()) setup(); } @@ -78,7 +79,7 @@ class Camera1 extends CameraController { */ @Override public void onSurfaceChanged() { - Log.e(TAG, "onSurfaceChanged, size is "+mPreview.getSurfaceSize()); + LOG.i("onSurfaceChanged, size is", mPreview.getSurfaceSize()); if (mIsSetup) { // Compute a new camera preview size. Size newSize = computePreviewSize(); @@ -358,8 +359,8 @@ class Camera1 extends CameraController { } onSurfaceChanged(); } - Log.e(TAG, "captureSize: "+mCaptureSize); - Log.e(TAG, "previewSize: "+mPreviewSize); + LOG.i("captureSize: "+mCaptureSize); + LOG.i("previewSize: "+mPreviewSize); } } @@ -508,6 +509,8 @@ class Camera1 extends CameraController { if (mSessionType == SessionType.PICTURE) { // Choose the max size. List captureSizes = sizesFromList(params.getSupportedPictureSizes()); + Size maxSize = Collections.max(captureSizes); + LOG.i("computeCaptureSize:", "computed", maxSize, "from", captureSizes); return Collections.max(captureSizes); } else { // Choose according to developer choice in setVideoQuality. @@ -516,6 +519,7 @@ class Camera1 extends CameraController { List captureSizes = sizesFromList(params.getSupportedPictureSizes()); CamcorderProfile profile = getCamcorderProfile(mVideoQuality); AspectRatio targetRatio = AspectRatio.of(profile.videoFrameWidth, profile.videoFrameHeight); + LOG.i("computeCaptureSize:", "videoQuality:", mVideoQuality, "targetRatio:", targetRatio); return matchSize(captureSizes, targetRatio, new Size(0, 0), true); } } @@ -524,7 +528,9 @@ class Camera1 extends CameraController { Camera.Parameters params = mCamera.getParameters(); List previewSizes = sizesFromList(params.getSupportedPreviewSizes()); AspectRatio targetRatio = AspectRatio.of(mCaptureSize.getWidth(), mCaptureSize.getHeight()); - return matchSize(previewSizes, targetRatio, mPreview.getSurfaceSize(), false); + Size biggerThan = mPreview.getSurfaceSize(); + LOG.i("computePreviewSize:", "targetRatio:", targetRatio, "surface size:", biggerThan); + return matchSize(previewSizes, targetRatio, biggerThan, false); } @@ -721,8 +727,8 @@ class Camera1 extends CameraController { double theta = ((double) displayToSensor) * Math.PI / 180; double sensorClickX = viewClickX * Math.cos(theta) - viewClickY * Math.sin(theta); double sensorClickY = viewClickX * Math.sin(theta) + viewClickY * Math.cos(theta); - // Log.e(TAG, "viewClickX:"+viewClickX+", viewClickY:"+viewClickY); - // Log.e(TAG, "sensorClickX:"+sensorClickX+", sensorClickY:"+sensorClickY); + LOG.i("viewClickX:", viewClickX, "viewClickY:", viewClickY); + LOG.i("sensorClickX:", sensorClickX, "sensorClickY:", sensorClickY); // Compute the rect bounds. Rect rect1 = computeMeteringArea(sensorClickX, sensorClickY, 150d); @@ -743,7 +749,7 @@ class Camera1 extends CameraController { int bottom = (int) Math.min(centerY + delta, 1000); int left = (int) Math.max(centerX - delta, -1000); int right = (int) Math.min(centerX + delta, 1000); - // Log.e(TAG, "top:"+top+", left:"+left+", bottom:"+bottom+", right:"+right); + LOG.i("metering area:", "top:", top, "left:", left, "bottom:", bottom, "right:", right); return new Rect(left, top, right, bottom); } @@ -762,6 +768,7 @@ class Camera1 extends CameraController { for (Camera.Size size : sizes) { result.add(new Size(size.width, size.height)); } + LOG.i("sizesFromList:", result.toArray()); return result; } @@ -791,15 +798,20 @@ class Camera1 extends CameraController { } } + LOG.i("matchSize:", "found consistent:", consistent.size()); + LOG.i("matchSize:", "found big enough and consistent:", bigEnoughAndConsistent.size()); + Size result; if (biggestPossible) { if (bigEnoughAndConsistent.size() > 0) return Collections.max(bigEnoughAndConsistent); if (consistent.size() > 0) return Collections.max(consistent); - return Collections.max(sizes); + result = Collections.max(sizes); } else { if (bigEnoughAndConsistent.size() > 0) return Collections.min(bigEnoughAndConsistent); if (consistent.size() > 0) return Collections.max(consistent); - return Collections.max(sizes); + result = Collections.max(sizes); } + LOG.i("matchSize:", "returning result", result); + return result; } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java index 65158f6a..18a2d487 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/Camera2.java @@ -107,7 +107,6 @@ class Camera2 extends CameraController { try { ids = mCameraManager.getCameraIdList(); } catch (CameraAccessException e) { - Log.e("CameraKit", e.toString()); return; } diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java index b3a786bd..948c40f4 100644 --- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java +++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java @@ -44,6 +44,8 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; public class CameraView extends FrameLayout { private final static String TAG = CameraView.class.getSimpleName(); + private static final CameraLogger LOG = CameraLogger.create(TAG); + public final static int PERMISSION_REQUEST_CODE = 16; final static int DEFAULT_JPEG_QUALITY = 100; @@ -215,7 +217,7 @@ public class CameraView extends FrameLayout { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { Size previewSize = getPreviewSize(); if (previewSize == null) { - Log.e(TAG, "onMeasure, surface is not ready. Calling default behavior."); + LOG.w("onMeasure:", "surface is not ready. Calling default behavior."); super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } @@ -234,18 +236,18 @@ public class CameraView extends FrameLayout { 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" + + LOG.i("onMeasure:", "requested dimensions are", + "(" + widthValue + "[" + ms(widthMode) + "]x" + heightValue + "[" + ms(heightMode) + "])"); - Log.e(TAG, "onMeasure, previewSize is (" + previewWidth + "x" + previewHeight + ")"); + LOG.i("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 manage to 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 + ")"); + LOG.w("onMeasure:", "both are MATCH_PARENT or fixed value. We adapt.", + "This means CROP_CENTER.", "(" + widthValue + "x" + heightValue + ")"); super.onMeasure(widthMeasureSpec, heightMeasureSpec); return; } @@ -253,8 +255,8 @@ public class CameraView extends FrameLayout { // 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. " + + LOG.i("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), @@ -279,7 +281,7 @@ public class CameraView extends FrameLayout { width = widthValue; height = (int) (width * ratio); } - Log.e(TAG, "onMeasure, one dimension was free, we adapted it to fit the aspect ratio. " + + LOG.i("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)); @@ -299,8 +301,9 @@ public class CameraView extends FrameLayout { 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 + ")"); + LOG.i("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; @@ -318,7 +321,8 @@ public class CameraView extends FrameLayout { height = heightValue; width = (int) (height / ratio); } - Log.e(TAG, "onMeasure, both dimension were AT_MOST. We fit the preview aspect ratio. " + + LOG.i("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)); @@ -406,13 +410,13 @@ public class CameraView extends FrameLayout { // Pass to our own GestureLayouts CameraOptions options = mCameraController.getCameraOptions(); // Non null if (mPinchGestureLayout.onTouchEvent(event)) { - // Log.e(TAG, "pinch!"); + LOG.i("onTouchEvent", "pinch!"); onGesture(mPinchGestureLayout, options); } else if (mScrollGestureLayout.onTouchEvent(event)) { - // Log.e(TAG, "scroll!"); + LOG.i("onTouchEvent", "scroll!"); onGesture(mScrollGestureLayout, options); } else if (mTapGestureLayout.onTouchEvent(event)) { - // Log.e(TAG, "tap!"); + LOG.i("onTouchEvent", "tap!"); onGesture(mTapGestureLayout, options); } return true; @@ -545,10 +549,9 @@ public class CameraView extends FrameLayout { return; } } - String message = "When the session type is set to video, the RECORD_AUDIO permission " + - "should be added to the application manifest file."; - Log.w(TAG, message); - throw new IllegalStateException(message); + LOG.e("Permission error:", "When the session type is set to video,", + "the RECORD_AUDIO permission should be added to the app manifest file."); + throw new IllegalStateException(CameraLogger.lastMessage); } catch (PackageManager.NameNotFoundException e) { // Not possible. } @@ -1217,6 +1220,7 @@ public class CameraView extends FrameLayout { // Outer listeners private ArrayList mListeners = new ArrayList<>(2); + private CameraLogger mLogger = CameraLogger.create(CameraCallbacks.class.getSimpleName()); // Orientation TODO: move this logic into OrientationHelper private Integer mDisplayOffset; @@ -1226,6 +1230,7 @@ public class CameraView extends FrameLayout { public void dispatchOnCameraOpened(final CameraOptions options) { + mLogger.i("dispatchOnCameraOpened", options); mUiHandler.post(new Runnable() { @Override public void run() { @@ -1238,6 +1243,7 @@ public class CameraView extends FrameLayout { public void dispatchOnCameraClosed() { + mLogger.i("dispatchOnCameraClosed"); mUiHandler.post(new Runnable() { @Override public void run() { @@ -1250,6 +1256,7 @@ public class CameraView extends FrameLayout { public void onCameraPreviewSizeChanged() { + mLogger.i("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, @@ -1281,6 +1288,7 @@ public class CameraView extends FrameLayout { * because it was taken with the front camera. */ public void processImage(final byte[] jpeg, final boolean consistentWithView, final boolean flipHorizontally) { + mLogger.i("processImage"); mWorkerHandler.post(new Runnable() { @Override public void run() { @@ -1291,8 +1299,8 @@ public class CameraView extends FrameLayout { int w = consistentWithView ? getWidth() : getHeight(); int h = consistentWithView ? getHeight() : getWidth(); AspectRatio targetRatio = AspectRatio.of(w, h); - // Log.e(TAG, "is Consistent? " + consistentWithView); - // Log.e(TAG, "viewWidth? " + getWidth() + ", viewHeight? " + getHeight()); + mLogger.i("processImage", "is consistent?", consistentWithView); + mLogger.i("processImage", "viewWidth?", getWidth(), "viewHeight?", getHeight()); jpeg2 = CropHelper.cropToJpeg(jpeg, targetRatio, mJpegQuality); } dispatchOnPictureTaken(jpeg2); @@ -1302,6 +1310,7 @@ public class CameraView extends FrameLayout { public void processSnapshot(final YuvImage yuv, final boolean consistentWithView, boolean flipHorizontally) { + mLogger.i("processSnapshot"); mWorkerHandler.post(new Runnable() { @Override public void run() { @@ -1310,6 +1319,8 @@ public class CameraView extends FrameLayout { int w = consistentWithView ? getWidth() : getHeight(); int h = consistentWithView ? getHeight() : getWidth(); AspectRatio targetRatio = AspectRatio.of(w, h); + mLogger.i("processSnapshot", "is consistent?", consistentWithView); + mLogger.i("processSnapshot", "viewWidth?", getWidth(), "viewHeight?", getHeight()); jpeg = CropHelper.cropToJpeg(yuv, targetRatio, mJpegQuality); } else { ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -1323,6 +1334,7 @@ public class CameraView extends FrameLayout { private void dispatchOnPictureTaken(byte[] jpeg) { + mLogger.i("dispatchOnPictureTaken"); final byte[] data = jpeg; mUiHandler.post(new Runnable() { @Override @@ -1336,6 +1348,7 @@ public class CameraView extends FrameLayout { public void dispatchOnVideoTaken(final File video) { + mLogger.i("dispatchOnVideoTaken", video); mUiHandler.post(new Runnable() { @Override public void run() { @@ -1348,6 +1361,7 @@ public class CameraView extends FrameLayout { public void dispatchOnFocusStart(@Nullable final Gesture gesture, final PointF point) { + mLogger.i("dispatchOnFocusStart", gesture, point); mUiHandler.post(new Runnable() { @Override public void run() { @@ -1365,6 +1379,7 @@ public class CameraView extends FrameLayout { public void dispatchOnFocusEnd(@Nullable final Gesture gesture, final boolean success, final PointF point) { + mLogger.i("dispatchOnFocusEnd", gesture, success, point); mUiHandler.post(new Runnable() { @Override public void run() { @@ -1386,6 +1401,7 @@ public class CameraView extends FrameLayout { @Override public void onDisplayOffsetChanged(int displayOffset) { + mLogger.i("onDisplayOffsetChanged", displayOffset); mCameraController.onDisplayOffset(displayOffset); mDisplayOffset = displayOffset; if (mDeviceOrientation != null) { @@ -1396,6 +1412,7 @@ public class CameraView extends FrameLayout { @Override public void onDeviceOrientationChanged(int deviceOrientation) { + mLogger.i("onDeviceOrientationChanged", deviceOrientation); mCameraController.onDeviceOrientation(deviceOrientation); mDeviceOrientation = deviceOrientation; if (mDisplayOffset != null) { @@ -1406,6 +1423,7 @@ public class CameraView extends FrameLayout { private void dispatchOnOrientationChanged(final int value) { + mLogger.i("dispatchOnOrientationChanged", value); mUiHandler.post(new Runnable() { @Override public void run() { @@ -1418,6 +1436,7 @@ public class CameraView extends FrameLayout { public void dispatchOnZoomChanged(final float newValue, final PointF[] fingers) { + mLogger.i("dispatchOnZoomChanged", newValue); mUiHandler.post(new Runnable() { @Override public void run() { @@ -1432,6 +1451,7 @@ public class CameraView extends FrameLayout { public void dispatchOnExposureCorrectionChanged(final float newValue, final float[] bounds, final PointF[] fingers) { + mLogger.i("dispatchOnExposureCorrectionChanged", newValue); mUiHandler.post(new Runnable() { @Override public void run() { @@ -1444,16 +1464,19 @@ public class CameraView extends FrameLayout { private void addListener(@NonNull CameraListener cameraListener) { + mLogger.i("addListener"); mListeners.add(cameraListener); } private void removeListener(@NonNull CameraListener cameraListener) { + mLogger.i("removeListener"); mListeners.remove(cameraListener); } private void clearListeners() { + mLogger.i("clearListeners"); mListeners.clear(); } } diff --git a/cameraview/src/main/utils/com/otaliastudios/cameraview/CameraLogger.java b/cameraview/src/main/utils/com/otaliastudios/cameraview/CameraLogger.java new file mode 100644 index 00000000..e724c502 --- /dev/null +++ b/cameraview/src/main/utils/com/otaliastudios/cameraview/CameraLogger.java @@ -0,0 +1,92 @@ +package com.otaliastudios.cameraview; + +import android.support.annotation.IntDef; +import android.util.Log; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Utility class that can log traces and info. + */ +public final class CameraLogger { + + public final static int LEVEL_VERBOSE = 0; + public final static int LEVEL_WARNING = 1; + public final static int LEVEL_ERROR = 2; + + @IntDef({LEVEL_VERBOSE, LEVEL_WARNING, LEVEL_ERROR}) + @Retention(RetentionPolicy.SOURCE) + @interface LogLevel {} + + private static int level = LEVEL_ERROR; + + public static void setLogLevel(int logLevel) { + level = logLevel; + } + + static String lastMessage; + static String lastTag; + + static CameraLogger create(String tag) { + return new CameraLogger(tag); + } + + private String mTag; + + private CameraLogger(String tag) { + mTag = tag; + } + + public void i(String message) { + if (should(LEVEL_VERBOSE)) { + Log.i(mTag, message); + lastMessage = message; + lastTag = mTag; + } + } + + public void w(String message) { + if (should(LEVEL_WARNING)) { + Log.w(mTag, message); + lastMessage = message; + lastTag = mTag; + } + } + + public void e(String message) { + if (should(LEVEL_ERROR)) { + Log.w(mTag, message); + lastMessage = message; + lastTag = mTag; + } + } + + private boolean should(int messageLevel) { + return level <= messageLevel; + } + + private String string(int messageLevel, Object... ofData) { + String message = ""; + if (should(messageLevel)) { + for (Object o : ofData) { + message += String.valueOf(o); + message += " "; + } + } + return message.trim(); + } + + public void i(Object... data) { + i(string(LEVEL_VERBOSE, data)); + } + + public void w(Object... data) { + w(string(LEVEL_WARNING, data)); + } + + public void e(Object... data) { + e(string(LEVEL_ERROR, data)); + } +} + diff --git a/cameraview/src/main/views/com/otaliastudios/cameraview/ScrollGestureLayout.java b/cameraview/src/main/views/com/otaliastudios/cameraview/ScrollGestureLayout.java index c221150b..09cb84f9 100644 --- a/cameraview/src/main/views/com/otaliastudios/cameraview/ScrollGestureLayout.java +++ b/cameraview/src/main/views/com/otaliastudios/cameraview/ScrollGestureLayout.java @@ -14,6 +14,8 @@ import android.widget.ImageView; class ScrollGestureLayout extends GestureLayout { + private static final String TAG = ScrollGestureLayout.class.getSimpleName(); + private static final CameraLogger LOG = CameraLogger.create(TAG); private GestureDetector mDetector; private boolean mNotify; @@ -33,7 +35,7 @@ class ScrollGestureLayout extends GestureLayout { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { boolean horizontal; - // Log.e("ScrollGestureLayout", "onScroll, distanceX="+distanceX+", distanceY="+distanceY); + LOG.i("onScroll:", "distanceX="+distanceX, "distanceY="+distanceY); if (e1.getX() != mPoints[0].x || e1.getY() != mPoints[0].y) { // First step. We choose now if it's a vertical or horizontal scroll, and // stick to it for the whole gesture. @@ -71,7 +73,7 @@ class ScrollGestureLayout extends GestureLayout { mDetector.onTouchEvent(event); // Keep notifying CameraView as long as the gesture goes. - // if (mNotify) Log.e("ScrollGestureLayout", "notifying a gesture "+mType.name()); + if (mNotify) LOG.i("Notifying a gesture of type", mType.name()); return mNotify; } @@ -91,7 +93,7 @@ class ScrollGestureLayout extends GestureLayout { float newValue = currValue + delta; if (newValue < minValue) newValue = minValue; if (newValue > maxValue) newValue = maxValue; - // Log.e("ScrollGestureLayout", "curr="+currValue+", min="+minValue+", max="+maxValue+", out="+newValue); + LOG.i("curr="+currValue, "min="+minValue, "max="+maxValue, "out="+newValue); return newValue; } diff --git a/demo/src/main/java/com/otaliastudios/cameraview/demo/MainActivity.java b/demo/src/main/java/com/otaliastudios/cameraview/demo/MainActivity.java index dfb9f6a3..8c3cee08 100644 --- a/demo/src/main/java/com/otaliastudios/cameraview/demo/MainActivity.java +++ b/demo/src/main/java/com/otaliastudios/cameraview/demo/MainActivity.java @@ -15,6 +15,7 @@ import android.widget.TextView; import android.widget.Toast; import com.otaliastudios.cameraview.CameraListener; +import com.otaliastudios.cameraview.CameraLogger; import com.otaliastudios.cameraview.CameraView; import com.otaliastudios.cameraview.Grid; import com.otaliastudios.cameraview.SessionType; @@ -83,6 +84,7 @@ public class MainActivity extends AppCompatActivity implements View.OnLayoutChan super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); + CameraLogger.setLogLevel(CameraLogger.LEVEL_VERBOSE); parent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override