diff --git a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java
index 8bf95be9..3d7207dd 100644
--- a/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java
+++ b/cameraview/src/androidTest/java/com/otaliastudios/cameraview/CameraViewTest.java
@@ -171,7 +171,10 @@ public class CameraViewTest extends BaseTest {
// Self managed
GestureParser gestures = new GestureParser(empty);
assertEquals(cameraView.getPlaySounds(), CameraView.DEFAULT_PLAY_SOUNDS);
+ assertEquals(cameraView.getAutoFocusResetDelay(), CameraView.DEFAULT_AUTOFOCUS_RESET_DELAY_MILLIS);
assertEquals(cameraView.getUseDeviceOrientation(), CameraView.DEFAULT_USE_DEVICE_ORIENTATION);
+ assertEquals(cameraView.getPictureMetering(), CameraView.DEFAULT_PICTURE_METERING);
+ assertEquals(cameraView.getPictureSnapshotMetering(), CameraView.DEFAULT_PICTURE_SNAPSHOT_METERING);
assertEquals(cameraView.getGestureAction(Gesture.TAP), gestures.getTapAction());
assertEquals(cameraView.getGestureAction(Gesture.LONG_TAP), gestures.getLongTapAction());
assertEquals(cameraView.getGestureAction(Gesture.PINCH), gestures.getPinchAction());
@@ -649,6 +652,22 @@ public class CameraViewTest extends BaseTest {
assertFalse(cameraView.getUseDeviceOrientation());
}
+ @Test
+ public void testSetPictureMetering() {
+ cameraView.setPictureMetering(true);
+ assertTrue(cameraView.getPictureMetering());
+ cameraView.setPictureMetering(false);
+ assertFalse(cameraView.getPictureMetering());
+ }
+
+ @Test
+ public void testSetPictureSnapshotMetering() {
+ cameraView.setPictureSnapshotMetering(true);
+ assertTrue(cameraView.getPictureSnapshotMetering());
+ cameraView.setPictureSnapshotMetering(false);
+ assertFalse(cameraView.getPictureSnapshotMetering());
+ }
+
@Test
public void testSetFlash() {
cameraView.set(Flash.TORCH);
diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
index adbda849..ab69fa1b 100644
--- a/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
+++ b/cameraview/src/main/java/com/otaliastudios/cameraview/CameraView.java
@@ -107,6 +107,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
final static long DEFAULT_AUTOFOCUS_RESET_DELAY_MILLIS = 3000;
final static boolean DEFAULT_PLAY_SOUNDS = true;
final static boolean DEFAULT_USE_DEVICE_ORIENTATION = true;
+ final static boolean DEFAULT_PICTURE_METERING = true;
+ final static boolean DEFAULT_PICTURE_SNAPSHOT_METERING = false;
// Self managed parameters
private boolean mPlaySounds;
@@ -182,6 +184,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
int videoBitRate = a.getInteger(R.styleable.CameraView_cameraVideoBitRate, 0);
int audioBitRate = a.getInteger(R.styleable.CameraView_cameraAudioBitRate, 0);
long autoFocusResetDelay = (long) a.getInteger(R.styleable.CameraView_cameraAutoFocusResetDelay, (int) DEFAULT_AUTOFOCUS_RESET_DELAY_MILLIS);
+ boolean pictureMetering = a.getBoolean(R.styleable.CameraView_cameraPictureMetering, DEFAULT_PICTURE_METERING);
+ boolean pictureSnapshotMetering = a.getBoolean(R.styleable.CameraView_cameraPictureSnapshotMetering, DEFAULT_PICTURE_SNAPSHOT_METERING);
// Size selectors and gestures
SizeSelectorParser sizeSelectors = new SizeSelectorParser(a);
@@ -228,6 +232,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
setAudio(controls.getAudio());
setAudioBitRate(audioBitRate);
setPictureSize(sizeSelectors.getPictureSizeSelector());
+ setPictureMetering(pictureMetering);
+ setPictureSnapshotMetering(pictureSnapshotMetering);
setVideoSize(sizeSelectors.getVideoSizeSelector());
setVideoCodec(controls.getVideoCodec());
setVideoMaxSize(videoMaxSize);
@@ -280,7 +286,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Instantiates the camera engine.
*
@@ -547,7 +552,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return false;
}
-
/**
* Clears any action mapped to the given gesture.
* @param gesture which gesture to clear
@@ -556,7 +560,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mapGesture(gesture, GestureAction.NONE);
}
-
/**
* Returns the action currently mapped to the given gesture.
*
@@ -569,13 +572,11 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mGestureMap.get(gesture);
}
-
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true; // Steal our own events.
}
-
@SuppressLint("ClickableViewAccessibility")
@Override
public boolean onTouchEvent(MotionEvent event) {
@@ -598,7 +599,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return true;
}
-
// Some gesture layout detected a gesture. It's not known at this moment:
// (1) if it was mapped to some action (we check here)
// (2) if it's supported by the camera (CameraEngine checks)
@@ -691,7 +691,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mLifecycle.addObserver(this);
}
-
/**
* Starts the camera preview, if not started already.
* This should be called onResume(), or when you are ready with permissions.
@@ -708,7 +707,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Checks that we have appropriate permissions.
* This means checking that we have audio permissions if audio = Audio.ON.
@@ -736,7 +734,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return true;
}
-
/**
* If audio is on we will ask for RECORD_AUDIO permission.
* If the developer did not add this to its manifest, throw and fire warnings.
@@ -760,7 +757,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Stops the current preview, if any was started.
* This should be called onPause().
@@ -772,7 +768,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
if (mCameraPreview != null) mCameraPreview.onPause();
}
-
/**
* Destroys this instance, releasing immediately
* the camera resource.
@@ -865,7 +860,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Controls the preview engine. Should only be called
* if this CameraView was never added to any window
@@ -959,7 +953,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getCameraOptions();
}
-
/**
* Sets exposure adjustment, in EV stops. A positive value will mean brighter picture.
*
@@ -985,7 +978,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Returns the current exposure correction value, typically 0
* at start-up.
@@ -995,7 +987,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getExposureCorrectionValue();
}
-
/**
* Sets a zoom value. This is not guaranteed to be supported by the current device,
* but you can take a look at {@link CameraOptions#isZoomSupported()}.
@@ -1012,7 +1003,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setZoom(zoom, null, false);
}
-
/**
* Returns the current zoom value, something between 0 and 1.
* @return the current zoom value
@@ -1021,7 +1011,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getZoomValue();
}
-
/**
* Controls the grids to be drawn over the current layout.
*
@@ -1036,7 +1025,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mGridLinesLayout.setGridMode(gridMode);
}
-
/**
* Gets the current grid mode.
* @return the current grid mode
@@ -1046,7 +1034,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mGridLinesLayout.getGridMode();
}
-
/**
* Controls the color of the grid lines that will be drawn
* over the current layout.
@@ -1077,7 +1064,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setHdr(hdr);
}
-
/**
* Gets the current hdr value.
* @return the current hdr value
@@ -1087,7 +1073,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getHdr();
}
-
/**
* Set location coordinates to be found later in the EXIF header
*
@@ -1103,7 +1088,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setLocation(location);
}
-
/**
* Set location values to be found later in the EXIF header
*
@@ -1113,7 +1097,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setLocation(location);
}
-
/**
* Retrieves the location previously applied with setLocation().
*
@@ -1124,7 +1107,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getLocation();
}
-
/**
* Sets desired white balance to current camera session.
*
@@ -1140,7 +1122,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setWhiteBalance(whiteBalance);
}
-
/**
* Returns the current white balance behavior.
* @return white balance value.
@@ -1150,7 +1131,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getWhiteBalance();
}
-
/**
* Sets which camera sensor should be used.
*
@@ -1163,7 +1143,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setFacing(facing);
}
-
/**
* Gets the facing camera currently being used.
* @return a facing value.
@@ -1173,7 +1152,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getFacing();
}
-
/**
* Toggles the facing value between {@link Facing#BACK}
* and {@link Facing#FRONT}.
@@ -1195,7 +1173,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getFacing();
}
-
/**
* Sets the flash mode.
*
@@ -1210,7 +1187,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setFlash(flash);
}
-
/**
* Gets the current flash mode.
* @return a flash mode
@@ -1220,7 +1196,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getFlash();
}
-
/**
* Controls the audio mode.
*
@@ -1250,7 +1225,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Gets the current audio value.
* @return the current audio value
@@ -1260,7 +1234,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getAudio();
}
-
/**
* Sets an {@link AutoFocusMarker} to be notified of autofocus start, end and fail events
* so that it can draw elements on screen.
@@ -1272,7 +1245,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mMarkerLayout.onMarker(MarkerLayout.TYPE_AUTOFOCUS, autoFocusMarker);
}
-
/**
* Sets the current delay in milliseconds to reset the focus after an autofocus process.
*
@@ -1284,7 +1256,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setAutoFocusResetDelay(delayMillis);
}
-
/**
* Returns the current delay in milliseconds to reset the focus after an autofocus process.
* @return the current autofocus reset delay in milliseconds.
@@ -1292,7 +1263,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
@SuppressWarnings("unused")
public long getAutoFocusResetDelay() { return mCameraEngine.getAutoFocusResetDelay(); }
-
/**
* Starts an autofocus process at the given coordinates, with respect
* to the view width and height.
@@ -1306,7 +1276,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.startAutoFocus(null, new PointF(x, y));
}
-
/**
* ADVANCED FEATURE - sets a size selector for the preview stream.
* The {@link SizeSelector} will be invoked with the list of available sizes, and the first
@@ -1328,7 +1297,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setPreviewStreamSizeSelector(selector);
}
-
/**
* Set the current session type to either picture or video.
*
@@ -1341,7 +1309,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setMode(mode);
}
-
/**
* Gets the current mode.
* @return the current mode
@@ -1351,7 +1318,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getMode();
}
-
/**
* Sets a capture size selector for picture mode.
* The {@link SizeSelector} will be invoked with the list of available sizes, and the first
@@ -1364,6 +1330,61 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setPictureSizeSelector(selector);
}
+ /**
+ * Whether the engine should perform a metering sequence before taking pictures requested
+ * with {@link #takePicture()}. A metering sequence includes adjusting focus, exposure
+ * and white balance to ensure a good quality of the result.
+ *
+ * When this parameter is true, the quality of the picture increases, but the latency
+ * increases as well. Defaults to true.
+ *
+ * This is a CAMERA2 only API. On CAMERA1, picture metering is always enabled.
+ *
+ * @see #setPictureSnapshotMetering(boolean)
+ * @param enable true to enable
+ */
+ public void setPictureMetering(boolean enable) {
+ mCameraEngine.setPictureMetering(enable);
+ }
+
+ /**
+ * Whether the engine should perform a metering sequence before taking pictures requested
+ * with {@link #takePicture()}. See {@link #setPictureMetering(boolean)}.
+ *
+ * @see #setPictureMetering(boolean)
+ * @return true if picture metering is enabled
+ */
+ public boolean getPictureMetering() {
+ return mCameraEngine.getPictureMetering();
+ }
+
+ /**
+ * Whether the engine should perform a metering sequence before taking pictures requested
+ * with {@link #takePictureSnapshot()}. A metering sequence includes adjusting focus,
+ * exposure and white balance to ensure a good quality of the result.
+ *
+ * When this parameter is true, the quality of the picture increases, but the latency
+ * increases as well. To keep snapshots fast, this defaults to false.
+ *
+ * This is a CAMERA2 only API. On CAMERA1, picture snapshot metering is always disabled.
+ *
+ * @see #setPictureMetering(boolean)
+ * @param enable true to enable
+ */
+ public void setPictureSnapshotMetering(boolean enable) {
+ mCameraEngine.setPictureSnapshotMetering(enable);
+ }
+
+ /**
+ * Whether the engine should perform a metering sequence before taking pictures requested
+ * with {@link #takePictureSnapshot()}. See {@link #setPictureSnapshotMetering(boolean)}.
+ *
+ * @see #setPictureSnapshotMetering(boolean)
+ * @return true if picture metering is enabled
+ */
+ public boolean getPictureSnapshotMetering() {
+ return mCameraEngine.getPictureSnapshotMetering();
+ }
/**
* Sets a capture size selector for video mode.
@@ -1425,7 +1446,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mListeners.add(cameraListener);
}
-
/**
* Remove a {@link CameraListener} that was previously registered.
*
@@ -1435,7 +1455,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mListeners.remove(cameraListener);
}
-
/**
* Clears the list of {@link CameraListener} that are registered
* to camera events.
@@ -1444,7 +1463,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mListeners.clear();
}
-
/**
* Adds a {@link FrameProcessor} instance to be notified of
* new frames in the preview stream.
@@ -1460,7 +1478,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Remove a {@link FrameProcessor} that was previously registered.
*
@@ -1475,7 +1492,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Clears the list of {@link FrameProcessor} that have been registered
* to preview frames.
@@ -1488,7 +1504,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Asks the camera to capture an image of the current scene.
* This will trigger {@link CameraListener#onPictureTaken(PictureResult)} if a listener
@@ -1504,7 +1519,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.takePicture(stub);
}
-
/**
* Asks the camera to capture a snapshot of the current preview.
* This eventually triggers {@link CameraListener#onPictureTaken(PictureResult)} if a listener
@@ -1520,7 +1534,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.takePictureSnapshot(stub);
}
-
/**
* Starts recording a video. Video will be written to the given file,
* so callers should ensure they have appropriate permissions to write to the file.
@@ -1560,7 +1573,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
});
}
-
/**
* Starts recording a video. Video will be written to the given file,
* so callers should ensure they have appropriate permissions to write to the file.
@@ -1628,10 +1640,8 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
takeVideoSnapshot(file);
}
-
// TODO: pauseVideo and resumeVideo? There is mediarecorder.pause(), but API 24...
-
/**
* Stops capturing video or video snapshots being recorded, if there was any.
* This will fire {@link CameraListener#onVideoTaken(VideoResult)}.
@@ -1699,7 +1709,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Returns the size used for pictures taken with {@link #takePicture()},
* or null if it hasn't been computed (for example if the surface is not ready),
@@ -1714,7 +1723,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getPictureSize(Reference.OUTPUT);
}
-
/**
* Returns the size used for videos taken with {@link #takeVideo(File)},
* or null if it hasn't been computed (for example if the surface is not ready),
@@ -1729,7 +1737,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getVideoSize(Reference.OUTPUT);
}
-
// If we end up here, we're in M.
@TargetApi(Build.VERSION_CODES.M)
private void requestPermissions(boolean requestCamera, boolean requestAudio) {
@@ -1751,7 +1758,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
@SuppressLint("NewApi")
private void playSound(int soundType) {
if (mPlaySounds) {
@@ -1760,7 +1766,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
}
}
-
/**
* Controls whether CameraView should play sound effects on certain
* events (picture taken, focus complete). Note that:
@@ -1774,7 +1779,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setPlaySounds(playSounds);
}
-
/**
* Gets the current sound effect behavior.
*
@@ -1821,7 +1825,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setVideoCodec(codec);
}
-
/**
* Gets the current encoder for video recordings.
* @return the current video codec
@@ -1831,7 +1834,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getVideoCodec();
}
-
/**
* Sets the maximum size in bytes for recorded video files.
* Once this size is reached, the recording will automatically stop.
@@ -1843,7 +1845,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setVideoMaxSize(videoMaxSizeInBytes);
}
-
/**
* Returns the maximum size in bytes for recorded video files, or 0
* if no size was set.
@@ -1855,7 +1856,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getVideoMaxSize();
}
-
/**
* Sets the maximum duration in milliseconds for video recordings.
* Once this duration is reached, the recording will automatically stop.
@@ -1867,7 +1867,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
mCameraEngine.setVideoMaxDuration(videoMaxDurationMillis);
}
-
/**
* Returns the maximum duration in milliseconds for video recordings, or 0
* if no limit was set.
@@ -1879,7 +1878,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.getVideoMaxDuration();
}
-
/**
* Returns true if the camera is currently recording a video
* @return boolean indicating if the camera is recording a video
@@ -1888,7 +1886,6 @@ public class CameraView extends FrameLayout implements LifecycleObserver {
return mCameraEngine.isTakingVideo();
}
-
/**
* Returns true if the camera is currently capturing a picture
* @return boolean indicating if the camera is capturing a picture
diff --git a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java
index 0cc4fa9a..27acdd47 100644
--- a/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java
+++ b/cameraview/src/main/java/com/otaliastudios/cameraview/engine/CameraEngine.java
@@ -167,6 +167,8 @@ public abstract class CameraEngine implements
@SuppressWarnings("WeakerAccess") protected float mZoomValue;
@SuppressWarnings("WeakerAccess") protected float mExposureCorrectionValue;
@SuppressWarnings("WeakerAccess") protected boolean mPlaySounds;
+ @SuppressWarnings("WeakerAccess") protected boolean mPictureMetering;
+ @SuppressWarnings("WeakerAccess") protected boolean mPictureSnapshotMetering;
// Can be private
@VisibleForTesting Handler mCrashHandler;
@@ -1008,6 +1010,22 @@ public abstract class CameraEngine implements
return mAutoFocusResetDelayMillis > 0 && mAutoFocusResetDelayMillis != Long.MAX_VALUE;
}
+ public final void setPictureMetering(boolean enable) {
+ mPictureMetering = enable;
+ }
+
+ public final boolean getPictureMetering() {
+ return mPictureMetering;
+ }
+
+ public final void setPictureSnapshotMetering(boolean enable) {
+ mPictureSnapshotMetering = enable;
+ }
+
+ public final boolean getPictureSnapshotMetering() {
+ return mPictureSnapshotMetering;
+ }
+
//endregion
//region Abstract setters and APIs
diff --git a/cameraview/src/main/res/values/attrs.xml b/cameraview/src/main/res/values/attrs.xml
index 59905eb1..f7d0c143 100644
--- a/cameraview/src/main/res/values/attrs.xml
+++ b/cameraview/src/main/res/values/attrs.xml
@@ -141,6 +141,10 @@
+
+
+
+