[camera] disable auto focus when using front facing camera on Android (#3383)
* Refactured Camera and fix issue front facing camera
* Update FPS range on Android to have correct brightness
* Formatted files
* Fix version conflict
diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md
index d38016a..55c7eb1 100644
--- a/packages/camera/camera/CHANGELOG.md
+++ b/packages/camera/camera/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.6.4+3
+
+* Detect if selected camera supports auto focus and act accordingly on Android. This solves a problem where front facing cameras are not capturing the picture because auto focus is not supported.
+
## 0.6.4+2
* Set ImageStreamReader listener to null to prevent stale images when streaming images.
diff --git a/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java b/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
index b7da94a..2db097c 100644
--- a/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
+++ b/packages/camera/camera/android/src/main/java/io/flutter/plugins/camera/Camera.java
@@ -33,12 +33,14 @@
import android.os.Build.VERSION_CODES;
import android.os.Handler;
import android.os.Looper;
+import android.util.Log;
import android.util.Range;
import android.util.Rational;
import android.util.Size;
import android.view.OrientationEventListener;
import android.view.Surface;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugins.camera.PictureCaptureRequest.State;
@@ -59,6 +61,11 @@
import java.util.Map;
import java.util.concurrent.Executors;
+@FunctionalInterface
+interface ErrorCallback {
+ void onError(String errorCode, String errorMessage);
+}
+
public class Camera {
private final SurfaceTextureEntry flutterTexture;
private final CameraManager cameraManager;
@@ -73,6 +80,7 @@
private final CamcorderProfile recordingProfile;
private final DartMessenger dartMessenger;
private final CameraZoom cameraZoom;
+ private final CameraCharacteristics cameraCharacteristics;
private CameraDevice cameraDevice;
private CameraCaptureSession cameraCaptureSession;
@@ -88,6 +96,8 @@
private PictureCaptureRequest pictureCaptureRequest;
private CameraRegions cameraRegions;
private int exposureOffset;
+ private boolean useAutoFocus;
+ private Range<Integer> fpsRange;
public Camera(
final Activity activity,
@@ -122,10 +132,12 @@
};
orientationEventListener.enable();
- CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraName);
- sensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
+ cameraCharacteristics = cameraManager.getCameraCharacteristics(cameraName);
+ initFps(cameraCharacteristics);
+ sensorOrientation = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
isFrontFacing =
- characteristics.get(CameraCharacteristics.LENS_FACING) == CameraMetadata.LENS_FACING_FRONT;
+ cameraCharacteristics.get(CameraCharacteristics.LENS_FACING)
+ == CameraMetadata.LENS_FACING_FRONT;
ResolutionPreset preset = ResolutionPreset.valueOf(resolutionPreset);
recordingProfile =
CameraUtils.getBestAvailableCamcorderProfileForResolutionPreset(cameraName, preset);
@@ -133,8 +145,29 @@
previewSize = computeBestPreviewSize(cameraName, preset);
cameraZoom =
new CameraZoom(
- characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE),
- characteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM));
+ cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE),
+ cameraCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM));
+ }
+
+ private void initFps(CameraCharacteristics cameraCharacteristics) {
+ try {
+ Range<Integer>[] ranges =
+ cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
+ if (ranges != null) {
+ for (Range<Integer> range : ranges) {
+ int upper = range.getUpper();
+ Log.i("Camera", "[FPS Range Available] is:" + range);
+ if (upper >= 10) {
+ if (fpsRange == null || upper < fpsRange.getUpper()) {
+ fpsRange = range;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ Log.i("Camera", "[FPS Range] is:" + fpsRange);
}
private void prepareMediaRecorder(String outputFilePath) throws IOException {
@@ -221,6 +254,118 @@
null);
}
+ private void createCaptureSession(int templateType, Surface... surfaces)
+ throws CameraAccessException {
+ createCaptureSession(templateType, null, surfaces);
+ }
+
+ private void createCaptureSession(
+ int templateType, Runnable onSuccessCallback, Surface... surfaces)
+ throws CameraAccessException {
+ // Close any existing capture session.
+ closeCaptureSession();
+
+ // Create a new capture builder.
+ captureRequestBuilder = cameraDevice.createCaptureRequest(templateType);
+
+ // Build Flutter surface to render to
+ SurfaceTexture surfaceTexture = flutterTexture.surfaceTexture();
+ surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
+ Surface flutterSurface = new Surface(surfaceTexture);
+ captureRequestBuilder.addTarget(flutterSurface);
+
+ List<Surface> remainingSurfaces = Arrays.asList(surfaces);
+ if (templateType != CameraDevice.TEMPLATE_PREVIEW) {
+ // If it is not preview mode, add all surfaces as targets.
+ for (Surface surface : remainingSurfaces) {
+ captureRequestBuilder.addTarget(surface);
+ }
+ }
+
+ // Prepare the callback
+ CameraCaptureSession.StateCallback callback =
+ new CameraCaptureSession.StateCallback() {
+ @Override
+ public void onConfigured(@NonNull CameraCaptureSession session) {
+ if (cameraDevice == null) {
+ dartMessenger.sendCameraErrorEvent("The camera was closed during configuration.");
+ return;
+ }
+ cameraCaptureSession = session;
+
+ updateFpsRange();
+ updateAutoFocus();
+ updateFlash(flashMode);
+ updateExposure(exposureMode);
+
+ refreshPreviewCaptureSession(
+ onSuccessCallback, (code, message) -> dartMessenger.sendCameraErrorEvent(message));
+ }
+
+ @Override
+ public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
+ dartMessenger.sendCameraErrorEvent("Failed to configure camera session.");
+ }
+ };
+
+ // Start the session
+ if (VERSION.SDK_INT >= VERSION_CODES.P) {
+ // Collect all surfaces we want to render to.
+ List<OutputConfiguration> configs = new ArrayList<>();
+ configs.add(new OutputConfiguration(flutterSurface));
+ for (Surface surface : remainingSurfaces) {
+ configs.add(new OutputConfiguration(surface));
+ }
+ createCaptureSessionWithSessionConfig(configs, callback);
+ } else {
+ // Collect all surfaces we want to render to.
+ List<Surface> surfaceList = new ArrayList<>();
+ surfaceList.add(flutterSurface);
+ surfaceList.addAll(remainingSurfaces);
+ createCaptureSession(surfaceList, callback);
+ }
+ }
+
+ @TargetApi(VERSION_CODES.P)
+ private void createCaptureSessionWithSessionConfig(
+ List<OutputConfiguration> outputConfigs, CameraCaptureSession.StateCallback callback)
+ throws CameraAccessException {
+ cameraDevice.createCaptureSession(
+ new SessionConfiguration(
+ SessionConfiguration.SESSION_REGULAR,
+ outputConfigs,
+ Executors.newSingleThreadExecutor(),
+ callback));
+ }
+
+ @TargetApi(VERSION_CODES.LOLLIPOP)
+ @SuppressWarnings("deprecation")
+ private void createCaptureSession(
+ List<Surface> surfaces, CameraCaptureSession.StateCallback callback)
+ throws CameraAccessException {
+ cameraDevice.createCaptureSession(surfaces, callback, null);
+ }
+
+ private void refreshPreviewCaptureSession(
+ @Nullable Runnable onSuccessCallback, @NonNull ErrorCallback onErrorCallback) {
+ if (cameraCaptureSession == null) {
+ return;
+ }
+
+ try {
+ cameraCaptureSession.setRepeatingRequest(
+ captureRequestBuilder.build(),
+ pictureCaptureCallback,
+ new Handler(Looper.getMainLooper()));
+
+ if (onSuccessCallback != null) {
+ onSuccessCallback.run();
+ }
+ } catch (CameraAccessException | IllegalStateException | IllegalArgumentException e) {
+ onErrorCallback.onError("cameraAccess", e.getMessage());
+ }
+ }
+
private void writeToFile(ByteBuffer buffer, File file) throws IOException {
try (FileOutputStream outputStream = new FileOutputStream(file)) {
while (0 < buffer.remaining()) {
@@ -261,7 +406,11 @@
},
null);
- runPictureAutoFocus();
+ if (useAutoFocus) {
+ runPictureAutoFocus();
+ } else {
+ runPicturePreCapture();
+ }
}
private final CameraCaptureSession.CaptureCallback pictureCaptureCallback =
@@ -344,6 +493,7 @@
private void runPictureAutoFocus() {
assert (pictureCaptureRequest != null);
+
pictureCaptureRequest.setState(PictureCaptureRequest.State.focusing);
lockAutoFocus();
}
@@ -355,14 +505,13 @@
captureRequestBuilder.set(
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
- try {
- cameraCaptureSession.capture(captureRequestBuilder.build(), pictureCaptureCallback, null);
- captureRequestBuilder.set(
- CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
- CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
- } catch (CameraAccessException e) {
- pictureCaptureRequest.error("cameraAccess", e.getMessage(), null);
- }
+
+ refreshPreviewCaptureSession(
+ () ->
+ captureRequestBuilder.set(
+ CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
+ CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE),
+ (code, message) -> pictureCaptureRequest.error(code, message, null));
}
private void runPictureCapture() {
@@ -409,125 +558,25 @@
private void lockAutoFocus() {
captureRequestBuilder.set(
CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START);
- try {
- cameraCaptureSession.capture(captureRequestBuilder.build(), pictureCaptureCallback, null);
- } catch (CameraAccessException e) {
- pictureCaptureRequest.error("cameraAccess", e.getMessage(), null);
- }
+
+ refreshPreviewCaptureSession(
+ null, (code, message) -> pictureCaptureRequest.error(code, message, null));
}
private void unlockAutoFocus() {
captureRequestBuilder.set(
CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
- initPreviewCaptureBuilder();
+ updateAutoFocus();
try {
cameraCaptureSession.capture(captureRequestBuilder.build(), null, null);
} catch (CameraAccessException ignored) {
}
captureRequestBuilder.set(
CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE);
- try {
- cameraCaptureSession.setRepeatingRequest(
- captureRequestBuilder.build(), pictureCaptureCallback, null);
- } catch (CameraAccessException e) {
- pictureCaptureRequest.error("cameraAccess", e.getMessage(), null);
- }
- }
- private void createCaptureSession(int templateType, Surface... surfaces)
- throws CameraAccessException {
- createCaptureSession(templateType, null, surfaces);
- }
-
- private void createCaptureSession(
- int templateType, Runnable onSuccessCallback, Surface... surfaces)
- throws CameraAccessException {
- // Close any existing capture session.
- closeCaptureSession();
-
- // Create a new capture builder.
- captureRequestBuilder = cameraDevice.createCaptureRequest(templateType);
-
- // Build Flutter surface to render to
- SurfaceTexture surfaceTexture = flutterTexture.surfaceTexture();
- surfaceTexture.setDefaultBufferSize(previewSize.getWidth(), previewSize.getHeight());
- Surface flutterSurface = new Surface(surfaceTexture);
- captureRequestBuilder.addTarget(flutterSurface);
-
- List<Surface> remainingSurfaces = Arrays.asList(surfaces);
- if (templateType != CameraDevice.TEMPLATE_PREVIEW) {
- // If it is not preview mode, add all surfaces as targets.
- for (Surface surface : remainingSurfaces) {
- captureRequestBuilder.addTarget(surface);
- }
- }
-
- // Prepare the callback
- CameraCaptureSession.StateCallback callback =
- new CameraCaptureSession.StateCallback() {
- @Override
- public void onConfigured(@NonNull CameraCaptureSession session) {
- try {
- if (cameraDevice == null) {
- dartMessenger.sendCameraErrorEvent("The camera was closed during configuration.");
- return;
- }
- cameraCaptureSession = session;
- initPreviewCaptureBuilder();
- cameraCaptureSession.setRepeatingRequest(
- captureRequestBuilder.build(),
- pictureCaptureCallback,
- new Handler(Looper.getMainLooper()));
- if (onSuccessCallback != null) {
- onSuccessCallback.run();
- }
- } catch (CameraAccessException | IllegalStateException | IllegalArgumentException e) {
- dartMessenger.sendCameraErrorEvent(e.getMessage());
- }
- }
-
- @Override
- public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
- dartMessenger.sendCameraErrorEvent("Failed to configure camera session.");
- }
- };
-
- // Start the session
- if (VERSION.SDK_INT >= VERSION_CODES.P) {
- // Collect all surfaces we want to render to.
- List<OutputConfiguration> configs = new ArrayList<>();
- configs.add(new OutputConfiguration(flutterSurface));
- for (Surface surface : remainingSurfaces) {
- configs.add(new OutputConfiguration(surface));
- }
- createCaptureSessionWithSessionConfig(configs, callback);
- } else {
- // Collect all surfaces we want to render to.
- List<Surface> surfaceList = new ArrayList<>();
- surfaceList.add(flutterSurface);
- surfaceList.addAll(remainingSurfaces);
- createCaptureSession(surfaceList, callback);
- }
- }
-
- @TargetApi(VERSION_CODES.P)
- private void createCaptureSessionWithSessionConfig(
- List<OutputConfiguration> outputConfigs, CameraCaptureSession.StateCallback callback)
- throws CameraAccessException {
- cameraDevice.createCaptureSession(
- new SessionConfiguration(
- SessionConfiguration.SESSION_REGULAR,
- outputConfigs,
- Executors.newSingleThreadExecutor(),
- callback));
- }
-
- @TargetApi(VERSION_CODES.LOLLIPOP)
- @SuppressWarnings("deprecation")
- private void createCaptureSession(
- List<Surface> surfaces, CameraCaptureSession.StateCallback callback)
- throws CameraAccessException {
- cameraDevice.createCaptureSession(surfaces, callback, null);
+ refreshPreviewCaptureSession(
+ null,
+ (errorCode, errorMessage) -> pictureCaptureRequest.error(errorCode, errorMessage, null));
}
public void startVideoRecording(Result result) {
@@ -560,8 +609,14 @@
try {
recordingVideo = false;
- closeCaptureSession();
- mediaRecorder.stop();
+
+ try {
+ cameraCaptureSession.abortCaptures();
+ mediaRecorder.stop();
+ } catch (CameraAccessException | IllegalStateException e) {
+ // Ignore exceptions and try to continue (changes are camera session already aborted capture)
+ }
+
mediaRecorder.reset();
startPreview();
result.success(videoRecordingFile.getAbsolutePath());
@@ -630,8 +685,8 @@
// If switching directly from torch to auto or on, make sure we turn off the torch.
if (flashMode == FlashMode.torch && mode != FlashMode.torch && mode != FlashMode.off) {
- this.flashMode = FlashMode.off;
- initPreviewCaptureBuilder();
+ updateFlash(FlashMode.off);
+
this.cameraCaptureSession.setRepeatingRequest(
captureRequestBuilder.build(),
new CaptureCallback() {
@@ -647,8 +702,13 @@
}
updateFlash(mode);
- result.success(null);
- isFinished = true;
+ refreshPreviewCaptureSession(
+ () -> {
+ result.success(null);
+ isFinished = true;
+ },
+ (code, message) ->
+ result.error("setFlashModeFailed", "Could not set flash mode.", null));
}
@Override
@@ -667,26 +727,16 @@
null);
} else {
updateFlash(mode);
- result.success(null);
- }
- }
- private void updateFlash(FlashMode mode) {
- // Get flash
- flashMode = mode;
- initPreviewCaptureBuilder();
- try {
- cameraCaptureSession.setRepeatingRequest(
- captureRequestBuilder.build(), pictureCaptureCallback, null);
- } catch (CameraAccessException e) {
- pictureCaptureRequest.error("cameraAccess", e.getMessage(), null);
+ refreshPreviewCaptureSession(
+ () -> result.success(null),
+ (code, message) -> result.error("setFlashModeFailed", "Could not set flash mode.", null));
}
}
public void setExposureMode(@NonNull final Result result, ExposureMode mode)
throws CameraAccessException {
- this.exposureMode = mode;
- initPreviewCaptureBuilder();
+ updateExposure(mode);
cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null);
result.success(null);
}
@@ -713,10 +763,9 @@
// Set the metering rectangle
cameraRegions.setAutoExposureMeteringRectangleFromPoint(x, y);
// Apply it
- initPreviewCaptureBuilder();
- this.cameraCaptureSession.setRepeatingRequest(
- captureRequestBuilder.build(), pictureCaptureCallback, null);
- result.success(null);
+ updateExposure(exposureMode);
+ refreshPreviewCaptureSession(
+ () -> result.success(null), (code, message) -> result.error("CameraAccess", message, null));
}
@TargetApi(VERSION_CODES.P)
@@ -802,13 +851,97 @@
double stepSize = getExposureOffsetStepSize();
exposureOffset = (int) (offset / stepSize);
// Apply it
- initPreviewCaptureBuilder();
+ updateExposure(exposureMode);
this.cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null);
result.success(offset);
}
- private void initPreviewCaptureBuilder() {
- captureRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO);
+ public float getMaxZoomLevel() {
+ return cameraZoom.maxZoom;
+ }
+
+ public float getMinZoomLevel() {
+ return CameraZoom.DEFAULT_ZOOM_FACTOR;
+ }
+
+ public void setZoomLevel(@NonNull final Result result, float zoom) throws CameraAccessException {
+ float maxZoom = cameraZoom.maxZoom;
+ float minZoom = CameraZoom.DEFAULT_ZOOM_FACTOR;
+
+ if (zoom > maxZoom || zoom < minZoom) {
+ String errorMessage =
+ String.format(
+ Locale.ENGLISH,
+ "Zoom level out of bounds (zoom level should be between %f and %f).",
+ minZoom,
+ maxZoom);
+ result.error("ZOOM_ERROR", errorMessage, null);
+ return;
+ }
+
+ //Zoom area is calculated relative to sensor area (activeRect)
+ if (captureRequestBuilder != null) {
+ final Rect computedZoom = cameraZoom.computeZoom(zoom);
+ captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, computedZoom);
+ cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null);
+ }
+
+ result.success(null);
+ }
+
+ private void updateFpsRange() {
+ if (fpsRange == null) {
+ return;
+ }
+
+ captureRequestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, fpsRange);
+ }
+
+ private void updateAutoFocus() {
+ if (useAutoFocus) {
+ int[] modes = cameraCharacteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);
+ // Auto focus is not supported
+ if (modes == null
+ || modes.length == 0
+ || (modes.length == 1 && modes[0] == CameraCharacteristics.CONTROL_AF_MODE_OFF)) {
+ useAutoFocus = false;
+ captureRequestBuilder.set(
+ CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
+ } else {
+ captureRequestBuilder.set(
+ CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
+ }
+ } else {
+ captureRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);
+ }
+ }
+
+ private void updateExposure(ExposureMode mode) {
+ exposureMode = mode;
+
+ // Applying auto exposure
+ MeteringRectangle aeRect = cameraRegions.getAEMeteringRectangle();
+ captureRequestBuilder.set(
+ CaptureRequest.CONTROL_AE_REGIONS,
+ aeRect == null ? null : new MeteringRectangle[] {cameraRegions.getAEMeteringRectangle()});
+
+ switch (mode) {
+ case locked:
+ captureRequestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);
+ break;
+ case auto:
+ default:
+ captureRequestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, false);
+ break;
+ }
+
+ captureRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, exposureOffset);
+ }
+
+ private void updateFlash(FlashMode mode) {
+ // Get flash
+ flashMode = mode;
+
// Applying flash modes
switch (flashMode) {
case off:
@@ -833,24 +966,6 @@
captureRequestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_TORCH);
break;
}
- // Applying auto exposure
- MeteringRectangle aeRect = cameraRegions.getAEMeteringRectangle();
- captureRequestBuilder.set(
- CaptureRequest.CONTROL_AE_REGIONS,
- aeRect == null ? null : new MeteringRectangle[] {cameraRegions.getAEMeteringRectangle()});
- switch (exposureMode) {
- case locked:
- captureRequestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, true);
- break;
- case auto:
- default:
- captureRequestBuilder.set(CaptureRequest.CONTROL_AE_LOCK, false);
- break;
- }
- captureRequestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, exposureOffset);
- // Applying auto focus
- captureRequestBuilder.set(
- CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
}
public void startPreview() throws CameraAccessException {
@@ -910,39 +1025,6 @@
null);
}
- public float getMaxZoomLevel() {
- return cameraZoom.maxZoom;
- }
-
- public float getMinZoomLevel() {
- return CameraZoom.DEFAULT_ZOOM_FACTOR;
- }
-
- public void setZoomLevel(@NonNull final Result result, float zoom) throws CameraAccessException {
- float maxZoom = cameraZoom.maxZoom;
- float minZoom = CameraZoom.DEFAULT_ZOOM_FACTOR;
-
- if (zoom > maxZoom || zoom < minZoom) {
- String errorMessage =
- String.format(
- Locale.ENGLISH,
- "Zoom level out of bounds (zoom level should be between %f and %f).",
- minZoom,
- maxZoom);
- result.error("ZOOM_ERROR", errorMessage, null);
- return;
- }
-
- //Zoom area is calculated relative to sensor area (activeRect)
- if (captureRequestBuilder != null) {
- final Rect computedZoom = cameraZoom.computeZoom(zoom);
- captureRequestBuilder.set(CaptureRequest.SCALER_CROP_REGION, computedZoom);
- cameraCaptureSession.setRepeatingRequest(captureRequestBuilder.build(), null, null);
- }
-
- result.success(null);
- }
-
public void stopImageStream() throws CameraAccessException {
if (imageStreamReader != null) {
imageStreamReader.setOnImageAvailableListener(null, null);
diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml
index 02f874b..99f41fb 100644
--- a/packages/camera/camera/pubspec.yaml
+++ b/packages/camera/camera/pubspec.yaml
@@ -2,7 +2,7 @@
description: A Flutter plugin for getting information about and controlling the
camera on Android and iOS. Supports previewing the camera feed, capturing images, capturing video,
and streaming image buffers to dart.
-version: 0.6.4+2
+version: 0.6.4+3
homepage: https://github.com/flutter/plugins/tree/master/packages/camera/camera
dependencies: