mirror of
https://github.com/flutter/packages.git
synced 2025-07-01 15:23:25 +08:00
[camerax] Implements setExposureMode
(#6110)
Implements `setExposureMode`. Fixes https://github.com/flutter/flutter/issues/120468. ~To be landed after (1) https://github.com/flutter/packages/pull/6059 then (2) https://github.com/flutter/packages/pull/6109.~ Done :)
This commit is contained in:
@ -1,3 +1,7 @@
|
|||||||
|
## 0.5.0+36
|
||||||
|
|
||||||
|
* Implements `setExposureMode`.
|
||||||
|
|
||||||
## 0.5.0+35
|
## 0.5.0+35
|
||||||
|
|
||||||
* Modifies `CameraInitializedEvent` that is sent when the camera is initialized to indicate that the initial focus
|
* Modifies `CameraInitializedEvent` that is sent when the camera is initialized to indicate that the initial focus
|
||||||
|
@ -30,10 +30,6 @@ dependencies:
|
|||||||
and thus, the plugin will fall back to 480p if configured with a
|
and thus, the plugin will fall back to 480p if configured with a
|
||||||
`ResolutionPreset`.
|
`ResolutionPreset`.
|
||||||
|
|
||||||
### Exposure mode configuration \[[Issue #120468][120468]\]
|
|
||||||
|
|
||||||
`setExposureMode`is unimplemented.
|
|
||||||
|
|
||||||
### Focus mode configuration \[[Issue #120467][120467]\]
|
### Focus mode configuration \[[Issue #120467][120467]\]
|
||||||
|
|
||||||
`setFocusMode` is unimplemented.
|
`setFocusMode` is unimplemented.
|
||||||
|
@ -29,6 +29,9 @@ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, Activity
|
|||||||
@VisibleForTesting @Nullable public SystemServicesHostApiImpl systemServicesHostApiImpl;
|
@VisibleForTesting @Nullable public SystemServicesHostApiImpl systemServicesHostApiImpl;
|
||||||
@VisibleForTesting @Nullable public MeteringPointHostApiImpl meteringPointHostApiImpl;
|
@VisibleForTesting @Nullable public MeteringPointHostApiImpl meteringPointHostApiImpl;
|
||||||
|
|
||||||
|
@VisibleForTesting @Nullable
|
||||||
|
public Camera2CameraControlHostApiImpl camera2CameraControlHostApiImpl;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public @Nullable DeviceOrientationManagerHostApiImpl deviceOrientationManagerHostApiImpl;
|
public @Nullable DeviceOrientationManagerHostApiImpl deviceOrientationManagerHostApiImpl;
|
||||||
|
|
||||||
@ -120,6 +123,11 @@ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, Activity
|
|||||||
cameraControlHostApiImpl =
|
cameraControlHostApiImpl =
|
||||||
new CameraControlHostApiImpl(binaryMessenger, instanceManager, context);
|
new CameraControlHostApiImpl(binaryMessenger, instanceManager, context);
|
||||||
GeneratedCameraXLibrary.CameraControlHostApi.setup(binaryMessenger, cameraControlHostApiImpl);
|
GeneratedCameraXLibrary.CameraControlHostApi.setup(binaryMessenger, cameraControlHostApiImpl);
|
||||||
|
camera2CameraControlHostApiImpl = new Camera2CameraControlHostApiImpl(instanceManager, context);
|
||||||
|
GeneratedCameraXLibrary.Camera2CameraControlHostApi.setup(
|
||||||
|
binaryMessenger, camera2CameraControlHostApiImpl);
|
||||||
|
GeneratedCameraXLibrary.CaptureRequestOptionsHostApi.setup(
|
||||||
|
binaryMessenger, new CaptureRequestOptionsHostApiImpl(instanceManager));
|
||||||
GeneratedCameraXLibrary.FocusMeteringActionHostApi.setup(
|
GeneratedCameraXLibrary.FocusMeteringActionHostApi.setup(
|
||||||
binaryMessenger, new FocusMeteringActionHostApiImpl(instanceManager));
|
binaryMessenger, new FocusMeteringActionHostApiImpl(instanceManager));
|
||||||
GeneratedCameraXLibrary.FocusMeteringResultHostApi.setup(
|
GeneratedCameraXLibrary.FocusMeteringResultHostApi.setup(
|
||||||
@ -217,6 +225,9 @@ public final class CameraAndroidCameraxPlugin implements FlutterPlugin, Activity
|
|||||||
if (cameraControlHostApiImpl != null) {
|
if (cameraControlHostApiImpl != null) {
|
||||||
cameraControlHostApiImpl.setContext(context);
|
cameraControlHostApiImpl.setContext(context);
|
||||||
}
|
}
|
||||||
|
if (camera2CameraControlHostApiImpl != null) {
|
||||||
|
camera2CameraControlHostApiImpl.setContext(context);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets {@code LifecycleOwner} that is used to control the lifecycle of the camera by CameraX. */
|
/** Sets {@code LifecycleOwner} that is used to control the lifecycle of the camera by CameraX. */
|
||||||
|
@ -110,8 +110,8 @@ public class CaptureRequestOptionsHostApiImpl implements CaptureRequestOptionsHo
|
|||||||
Map<CaptureRequestKeySupportedType, Object> decodedOptions =
|
Map<CaptureRequestKeySupportedType, Object> decodedOptions =
|
||||||
new HashMap<CaptureRequestKeySupportedType, Object>();
|
new HashMap<CaptureRequestKeySupportedType, Object>();
|
||||||
for (Map.Entry<Long, Object> option : options.entrySet()) {
|
for (Map.Entry<Long, Object> option : options.entrySet()) {
|
||||||
decodedOptions.put(
|
Integer index = ((Number) option.getKey()).intValue();
|
||||||
CaptureRequestKeySupportedType.values()[option.getKey().intValue()], option.getValue());
|
decodedOptions.put(CaptureRequestKeySupportedType.values()[index], option.getValue());
|
||||||
}
|
}
|
||||||
instanceManager.addDartCreatedInstance(proxy.create(decodedOptions), identifier);
|
instanceManager.addDartCreatedInstance(proxy.create(decodedOptions), identifier);
|
||||||
}
|
}
|
||||||
|
@ -169,6 +169,8 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
mock(ImageAnalysisHostApiImpl.class);
|
mock(ImageAnalysisHostApiImpl.class);
|
||||||
final CameraControlHostApiImpl mockCameraControlHostApiImpl =
|
final CameraControlHostApiImpl mockCameraControlHostApiImpl =
|
||||||
mock(CameraControlHostApiImpl.class);
|
mock(CameraControlHostApiImpl.class);
|
||||||
|
final Camera2CameraControlHostApiImpl mockCamera2CameraControlHostApiImpl =
|
||||||
|
mock(Camera2CameraControlHostApiImpl.class);
|
||||||
|
|
||||||
when(flutterPluginBinding.getApplicationContext()).thenReturn(mockContext);
|
when(flutterPluginBinding.getApplicationContext()).thenReturn(mockContext);
|
||||||
|
|
||||||
@ -180,6 +182,7 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
plugin.imageAnalysisHostApiImpl = mockImageAnalysisHostApiImpl;
|
plugin.imageAnalysisHostApiImpl = mockImageAnalysisHostApiImpl;
|
||||||
plugin.cameraControlHostApiImpl = mockCameraControlHostApiImpl;
|
plugin.cameraControlHostApiImpl = mockCameraControlHostApiImpl;
|
||||||
plugin.liveDataHostApiImpl = mock(LiveDataHostApiImpl.class);
|
plugin.liveDataHostApiImpl = mock(LiveDataHostApiImpl.class);
|
||||||
|
plugin.camera2CameraControlHostApiImpl = mockCamera2CameraControlHostApiImpl;
|
||||||
|
|
||||||
plugin.onAttachedToEngine(flutterPluginBinding);
|
plugin.onAttachedToEngine(flutterPluginBinding);
|
||||||
plugin.onDetachedFromActivityForConfigChanges();
|
plugin.onDetachedFromActivityForConfigChanges();
|
||||||
@ -191,6 +194,7 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
verify(mockImageCaptureHostApiImpl).setContext(mockContext);
|
verify(mockImageCaptureHostApiImpl).setContext(mockContext);
|
||||||
verify(mockImageAnalysisHostApiImpl).setContext(mockContext);
|
verify(mockImageAnalysisHostApiImpl).setContext(mockContext);
|
||||||
verify(mockCameraControlHostApiImpl).setContext(mockContext);
|
verify(mockCameraControlHostApiImpl).setContext(mockContext);
|
||||||
|
verify(mockCamera2CameraControlHostApiImpl).setContext(mockContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -259,6 +263,8 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
mock(CameraControlHostApiImpl.class);
|
mock(CameraControlHostApiImpl.class);
|
||||||
final DeviceOrientationManagerHostApiImpl mockDeviceOrientationManagerHostApiImpl =
|
final DeviceOrientationManagerHostApiImpl mockDeviceOrientationManagerHostApiImpl =
|
||||||
mock(DeviceOrientationManagerHostApiImpl.class);
|
mock(DeviceOrientationManagerHostApiImpl.class);
|
||||||
|
final Camera2CameraControlHostApiImpl mockCamera2CameraControlHostApiImpl =
|
||||||
|
mock(Camera2CameraControlHostApiImpl.class);
|
||||||
final MeteringPointHostApiImpl mockMeteringPointHostApiImpl =
|
final MeteringPointHostApiImpl mockMeteringPointHostApiImpl =
|
||||||
mock(MeteringPointHostApiImpl.class);
|
mock(MeteringPointHostApiImpl.class);
|
||||||
final ArgumentCaptor<PermissionsRegistry> permissionsRegistryCaptor =
|
final ArgumentCaptor<PermissionsRegistry> permissionsRegistryCaptor =
|
||||||
@ -277,6 +283,7 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
plugin.deviceOrientationManagerHostApiImpl = mockDeviceOrientationManagerHostApiImpl;
|
plugin.deviceOrientationManagerHostApiImpl = mockDeviceOrientationManagerHostApiImpl;
|
||||||
plugin.meteringPointHostApiImpl = mockMeteringPointHostApiImpl;
|
plugin.meteringPointHostApiImpl = mockMeteringPointHostApiImpl;
|
||||||
plugin.liveDataHostApiImpl = mock(LiveDataHostApiImpl.class);
|
plugin.liveDataHostApiImpl = mock(LiveDataHostApiImpl.class);
|
||||||
|
plugin.camera2CameraControlHostApiImpl = mockCamera2CameraControlHostApiImpl;
|
||||||
|
|
||||||
plugin.onAttachedToEngine(flutterPluginBinding);
|
plugin.onAttachedToEngine(flutterPluginBinding);
|
||||||
plugin.onReattachedToActivityForConfigChanges(activityPluginBinding);
|
plugin.onReattachedToActivityForConfigChanges(activityPluginBinding);
|
||||||
@ -294,6 +301,7 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
verify(mockImageCaptureHostApiImpl).setContext(mockActivity);
|
verify(mockImageCaptureHostApiImpl).setContext(mockActivity);
|
||||||
verify(mockImageAnalysisHostApiImpl).setContext(mockActivity);
|
verify(mockImageAnalysisHostApiImpl).setContext(mockActivity);
|
||||||
verify(mockCameraControlHostApiImpl).setContext(mockActivity);
|
verify(mockCameraControlHostApiImpl).setContext(mockActivity);
|
||||||
|
verify(mockCamera2CameraControlHostApiImpl).setContext(mockActivity);
|
||||||
|
|
||||||
// Check permissions registry reference is set.
|
// Check permissions registry reference is set.
|
||||||
verify(mockSystemServicesHostApiImpl)
|
verify(mockSystemServicesHostApiImpl)
|
||||||
@ -347,6 +355,8 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
final ImageCaptureHostApiImpl mockImageCaptureHostApiImpl = mock(ImageCaptureHostApiImpl.class);
|
final ImageCaptureHostApiImpl mockImageCaptureHostApiImpl = mock(ImageCaptureHostApiImpl.class);
|
||||||
final CameraControlHostApiImpl mockCameraControlHostApiImpl =
|
final CameraControlHostApiImpl mockCameraControlHostApiImpl =
|
||||||
mock(CameraControlHostApiImpl.class);
|
mock(CameraControlHostApiImpl.class);
|
||||||
|
final Camera2CameraControlHostApiImpl mockCamera2CameraControlHostApiImpl =
|
||||||
|
mock(Camera2CameraControlHostApiImpl.class);
|
||||||
final ArgumentCaptor<PermissionsRegistry> permissionsRegistryCaptor =
|
final ArgumentCaptor<PermissionsRegistry> permissionsRegistryCaptor =
|
||||||
ArgumentCaptor.forClass(PermissionsRegistry.class);
|
ArgumentCaptor.forClass(PermissionsRegistry.class);
|
||||||
|
|
||||||
@ -360,6 +370,7 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
plugin.imageAnalysisHostApiImpl = mockImageAnalysisHostApiImpl;
|
plugin.imageAnalysisHostApiImpl = mockImageAnalysisHostApiImpl;
|
||||||
plugin.cameraControlHostApiImpl = mockCameraControlHostApiImpl;
|
plugin.cameraControlHostApiImpl = mockCameraControlHostApiImpl;
|
||||||
plugin.liveDataHostApiImpl = mock(LiveDataHostApiImpl.class);
|
plugin.liveDataHostApiImpl = mock(LiveDataHostApiImpl.class);
|
||||||
|
plugin.camera2CameraControlHostApiImpl = mockCamera2CameraControlHostApiImpl;
|
||||||
|
|
||||||
plugin.onAttachedToEngine(flutterPluginBinding);
|
plugin.onAttachedToEngine(flutterPluginBinding);
|
||||||
plugin.onDetachedFromActivity();
|
plugin.onDetachedFromActivity();
|
||||||
@ -371,5 +382,6 @@ public class CameraAndroidCameraxPluginTest {
|
|||||||
verify(mockImageCaptureHostApiImpl).setContext(mockContext);
|
verify(mockImageCaptureHostApiImpl).setContext(mockContext);
|
||||||
verify(mockImageAnalysisHostApiImpl).setContext(mockContext);
|
verify(mockImageAnalysisHostApiImpl).setContext(mockContext);
|
||||||
verify(mockCameraControlHostApiImpl).setContext(mockContext);
|
verify(mockCameraControlHostApiImpl).setContext(mockContext);
|
||||||
|
verify(mockCamera2CameraControlHostApiImpl).setContext(mockContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,8 +393,10 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
|
|||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
TextButton(
|
TextButton(
|
||||||
style: styleAuto,
|
style: styleAuto,
|
||||||
onPressed:
|
onPressed: controller != null
|
||||||
() {}, // TODO(camsim99): Add functionality back here.
|
? () =>
|
||||||
|
onSetExposureModeButtonPressed(ExposureMode.auto)
|
||||||
|
: null,
|
||||||
onLongPress: () {
|
onLongPress: () {
|
||||||
if (controller != null) {
|
if (controller != null) {
|
||||||
CameraPlatform.instance
|
CameraPlatform.instance
|
||||||
@ -406,8 +408,10 @@ class _CameraExampleHomeState extends State<CameraExampleHome>
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
style: styleLocked,
|
style: styleLocked,
|
||||||
onPressed:
|
onPressed: controller != null
|
||||||
() {}, // TODO(camsim99): Add functionality back here.
|
? () =>
|
||||||
|
onSetExposureModeButtonPressed(ExposureMode.locked)
|
||||||
|
: null,
|
||||||
child: const Text('LOCKED'),
|
child: const Text('LOCKED'),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
|
@ -14,12 +14,14 @@ import 'package:stream_transform/stream_transform.dart';
|
|||||||
|
|
||||||
import 'analyzer.dart';
|
import 'analyzer.dart';
|
||||||
import 'camera.dart';
|
import 'camera.dart';
|
||||||
|
import 'camera2_camera_control.dart';
|
||||||
import 'camera_control.dart';
|
import 'camera_control.dart';
|
||||||
import 'camera_info.dart';
|
import 'camera_info.dart';
|
||||||
import 'camera_selector.dart';
|
import 'camera_selector.dart';
|
||||||
import 'camera_state.dart';
|
import 'camera_state.dart';
|
||||||
import 'camerax_library.g.dart';
|
import 'camerax_library.g.dart';
|
||||||
import 'camerax_proxy.dart';
|
import 'camerax_proxy.dart';
|
||||||
|
import 'capture_request_options.dart';
|
||||||
import 'device_orientation_manager.dart';
|
import 'device_orientation_manager.dart';
|
||||||
import 'exposure_state.dart';
|
import 'exposure_state.dart';
|
||||||
import 'fallback_strategy.dart';
|
import 'fallback_strategy.dart';
|
||||||
@ -545,6 +547,27 @@ class AndroidCameraCameraX extends CameraPlatform {
|
|||||||
point: point, meteringMode: FocusMeteringAction.flagAf);
|
point: point, meteringMode: FocusMeteringAction.flagAf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the exposure mode for taking pictures.
|
||||||
|
///
|
||||||
|
/// Setting [ExposureMode.locked] will lock current exposure point until it
|
||||||
|
/// is unset by setting [ExposureMode.auto].
|
||||||
|
///
|
||||||
|
/// [cameraId] is not used.
|
||||||
|
@override
|
||||||
|
Future<void> setExposureMode(int cameraId, ExposureMode mode) async {
|
||||||
|
final Camera2CameraControl camera2Control =
|
||||||
|
proxy.getCamera2CameraControl(cameraControl);
|
||||||
|
final bool lockExposureMode = mode == ExposureMode.locked;
|
||||||
|
|
||||||
|
final CaptureRequestOptions captureRequestOptions = proxy
|
||||||
|
.createCaptureRequestOptions(<(
|
||||||
|
CaptureRequestKeySupportedType,
|
||||||
|
Object?
|
||||||
|
)>[(CaptureRequestKeySupportedType.controlAeLock, lockExposureMode)]);
|
||||||
|
|
||||||
|
await camera2Control.addCaptureRequestOptions(captureRequestOptions);
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the maximum supported zoom level for the selected camera.
|
/// Gets the maximum supported zoom level for the selected camera.
|
||||||
///
|
///
|
||||||
/// [cameraId] not used.
|
/// [cameraId] not used.
|
||||||
|
@ -5,10 +5,13 @@
|
|||||||
import 'dart:ui' show Size;
|
import 'dart:ui' show Size;
|
||||||
|
|
||||||
import 'analyzer.dart';
|
import 'analyzer.dart';
|
||||||
|
import 'camera2_camera_control.dart';
|
||||||
|
import 'camera_control.dart';
|
||||||
import 'camera_info.dart';
|
import 'camera_info.dart';
|
||||||
import 'camera_selector.dart';
|
import 'camera_selector.dart';
|
||||||
import 'camera_state.dart';
|
import 'camera_state.dart';
|
||||||
import 'camerax_library.g.dart';
|
import 'camerax_library.g.dart';
|
||||||
|
import 'capture_request_options.dart';
|
||||||
import 'device_orientation_manager.dart';
|
import 'device_orientation_manager.dart';
|
||||||
import 'fallback_strategy.dart';
|
import 'fallback_strategy.dart';
|
||||||
import 'focus_metering_action.dart';
|
import 'focus_metering_action.dart';
|
||||||
@ -52,6 +55,8 @@ class CameraXProxy {
|
|||||||
_startListeningForDeviceOrientationChange,
|
_startListeningForDeviceOrientationChange,
|
||||||
this.setPreviewSurfaceProvider = _setPreviewSurfaceProvider,
|
this.setPreviewSurfaceProvider = _setPreviewSurfaceProvider,
|
||||||
this.getDefaultDisplayRotation = _getDefaultDisplayRotation,
|
this.getDefaultDisplayRotation = _getDefaultDisplayRotation,
|
||||||
|
this.getCamera2CameraControl = _getCamera2CameraControl,
|
||||||
|
this.createCaptureRequestOptions = _createCaptureRequestOptions,
|
||||||
this.createMeteringPoint = _createMeteringPoint,
|
this.createMeteringPoint = _createMeteringPoint,
|
||||||
this.createFocusMeteringAction = _createFocusMeteringAction,
|
this.createFocusMeteringAction = _createFocusMeteringAction,
|
||||||
});
|
});
|
||||||
@ -142,6 +147,15 @@ class CameraXProxy {
|
|||||||
/// rotation constants.
|
/// rotation constants.
|
||||||
Future<int> Function() getDefaultDisplayRotation;
|
Future<int> Function() getDefaultDisplayRotation;
|
||||||
|
|
||||||
|
/// Get [Camera2CameraControl] instance from [cameraControl].
|
||||||
|
Camera2CameraControl Function(CameraControl cameraControl)
|
||||||
|
getCamera2CameraControl;
|
||||||
|
|
||||||
|
/// Create [CapureRequestOptions] with specified options.
|
||||||
|
CaptureRequestOptions Function(
|
||||||
|
List<(CaptureRequestKeySupportedType, Object?)> options)
|
||||||
|
createCaptureRequestOptions;
|
||||||
|
|
||||||
/// Returns a [MeteringPoint] with the specified coordinates based on
|
/// Returns a [MeteringPoint] with the specified coordinates based on
|
||||||
/// [cameraInfo].
|
/// [cameraInfo].
|
||||||
MeteringPoint Function(double x, double y, CameraInfo cameraInfo)
|
MeteringPoint Function(double x, double y, CameraInfo cameraInfo)
|
||||||
@ -255,6 +269,16 @@ class CameraXProxy {
|
|||||||
return DeviceOrientationManager.getDefaultDisplayRotation();
|
return DeviceOrientationManager.getDefaultDisplayRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Camera2CameraControl _getCamera2CameraControl(
|
||||||
|
CameraControl cameraControl) {
|
||||||
|
return Camera2CameraControl(cameraControl: cameraControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static CaptureRequestOptions _createCaptureRequestOptions(
|
||||||
|
List<(CaptureRequestKeySupportedType, Object?)> options) {
|
||||||
|
return CaptureRequestOptions(requestedOptions: options);
|
||||||
|
}
|
||||||
|
|
||||||
static MeteringPoint _createMeteringPoint(
|
static MeteringPoint _createMeteringPoint(
|
||||||
double x, double y, CameraInfo cameraInfo) {
|
double x, double y, CameraInfo cameraInfo) {
|
||||||
return MeteringPoint(x: x, y: y, cameraInfo: cameraInfo);
|
return MeteringPoint(x: x, y: y, cameraInfo: cameraInfo);
|
||||||
|
@ -2,7 +2,7 @@ name: camera_android_camerax
|
|||||||
description: Android implementation of the camera plugin using the CameraX library.
|
description: Android implementation of the camera plugin using the CameraX library.
|
||||||
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
|
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_android_camerax
|
||||||
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
|
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
|
||||||
version: 0.5.0+35
|
version: 0.5.0+36
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.1.0
|
sdk: ^3.1.0
|
||||||
|
@ -9,6 +9,7 @@ import 'package:async/async.dart';
|
|||||||
import 'package:camera_android_camerax/camera_android_camerax.dart';
|
import 'package:camera_android_camerax/camera_android_camerax.dart';
|
||||||
import 'package:camera_android_camerax/src/analyzer.dart';
|
import 'package:camera_android_camerax/src/analyzer.dart';
|
||||||
import 'package:camera_android_camerax/src/camera.dart';
|
import 'package:camera_android_camerax/src/camera.dart';
|
||||||
|
import 'package:camera_android_camerax/src/camera2_camera_control.dart';
|
||||||
import 'package:camera_android_camerax/src/camera_control.dart';
|
import 'package:camera_android_camerax/src/camera_control.dart';
|
||||||
import 'package:camera_android_camerax/src/camera_info.dart';
|
import 'package:camera_android_camerax/src/camera_info.dart';
|
||||||
import 'package:camera_android_camerax/src/camera_selector.dart';
|
import 'package:camera_android_camerax/src/camera_selector.dart';
|
||||||
@ -16,6 +17,7 @@ import 'package:camera_android_camerax/src/camera_state.dart';
|
|||||||
import 'package:camera_android_camerax/src/camera_state_error.dart';
|
import 'package:camera_android_camerax/src/camera_state_error.dart';
|
||||||
import 'package:camera_android_camerax/src/camerax_library.g.dart';
|
import 'package:camera_android_camerax/src/camerax_library.g.dart';
|
||||||
import 'package:camera_android_camerax/src/camerax_proxy.dart';
|
import 'package:camera_android_camerax/src/camerax_proxy.dart';
|
||||||
|
import 'package:camera_android_camerax/src/capture_request_options.dart';
|
||||||
import 'package:camera_android_camerax/src/device_orientation_manager.dart';
|
import 'package:camera_android_camerax/src/device_orientation_manager.dart';
|
||||||
import 'package:camera_android_camerax/src/exposure_state.dart';
|
import 'package:camera_android_camerax/src/exposure_state.dart';
|
||||||
import 'package:camera_android_camerax/src/fallback_strategy.dart';
|
import 'package:camera_android_camerax/src/fallback_strategy.dart';
|
||||||
@ -78,6 +80,7 @@ import 'test_camerax_library.g.dart';
|
|||||||
MockSpec<TestInstanceManagerHostApi>(),
|
MockSpec<TestInstanceManagerHostApi>(),
|
||||||
MockSpec<TestSystemServicesHostApi>(),
|
MockSpec<TestSystemServicesHostApi>(),
|
||||||
MockSpec<ZoomState>(),
|
MockSpec<ZoomState>(),
|
||||||
|
MockSpec<Camera2CameraControl>(),
|
||||||
])
|
])
|
||||||
@GenerateMocks(<Type>[], customMocks: <MockSpec<Object>>[
|
@GenerateMocks(<Type>[], customMocks: <MockSpec<Object>>[
|
||||||
MockSpec<LiveData<CameraState>>(as: #MockLiveCameraState),
|
MockSpec<LiveData<CameraState>>(as: #MockLiveCameraState),
|
||||||
@ -2010,6 +2013,59 @@ void main() {
|
|||||||
expect(camera.captureOrientationLocked, isFalse);
|
expect(camera.captureOrientationLocked, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('setExposureMode sets expected controlAeLock value via Camera2 interop',
|
||||||
|
() async {
|
||||||
|
final AndroidCameraCameraX camera = AndroidCameraCameraX();
|
||||||
|
const int cameraId = 78;
|
||||||
|
final MockCameraControl mockCameraControl = MockCameraControl();
|
||||||
|
final MockCamera2CameraControl mockCamera2CameraControl =
|
||||||
|
MockCamera2CameraControl();
|
||||||
|
|
||||||
|
// Set directly for test versus calling createCamera.
|
||||||
|
camera.camera = MockCamera();
|
||||||
|
camera.cameraControl = mockCameraControl;
|
||||||
|
|
||||||
|
// Tell plugin to create detached Camera2CameraControl and
|
||||||
|
// CaptureRequestOptions instances for testing.
|
||||||
|
camera.proxy = CameraXProxy(
|
||||||
|
getCamera2CameraControl: (CameraControl cameraControl) =>
|
||||||
|
cameraControl == mockCameraControl
|
||||||
|
? mockCamera2CameraControl
|
||||||
|
: Camera2CameraControl.detached(cameraControl: cameraControl),
|
||||||
|
createCaptureRequestOptions:
|
||||||
|
(List<(CaptureRequestKeySupportedType, Object?)> options) =>
|
||||||
|
CaptureRequestOptions.detached(requestedOptions: options),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Test auto mode.
|
||||||
|
await camera.setExposureMode(cameraId, ExposureMode.auto);
|
||||||
|
|
||||||
|
VerificationResult verificationResult =
|
||||||
|
verify(mockCamera2CameraControl.addCaptureRequestOptions(captureAny));
|
||||||
|
CaptureRequestOptions capturedCaptureRequestOptions =
|
||||||
|
verificationResult.captured.single as CaptureRequestOptions;
|
||||||
|
List<(CaptureRequestKeySupportedType, Object?)> requestedOptions =
|
||||||
|
capturedCaptureRequestOptions.requestedOptions;
|
||||||
|
expect(requestedOptions.length, equals(1));
|
||||||
|
expect(requestedOptions.first.$1,
|
||||||
|
equals(CaptureRequestKeySupportedType.controlAeLock));
|
||||||
|
expect(requestedOptions.first.$2, equals(false));
|
||||||
|
|
||||||
|
// Test locked mode.
|
||||||
|
clearInteractions(mockCamera2CameraControl);
|
||||||
|
await camera.setExposureMode(cameraId, ExposureMode.locked);
|
||||||
|
|
||||||
|
verificationResult =
|
||||||
|
verify(mockCamera2CameraControl.addCaptureRequestOptions(captureAny));
|
||||||
|
capturedCaptureRequestOptions =
|
||||||
|
verificationResult.captured.single as CaptureRequestOptions;
|
||||||
|
requestedOptions = capturedCaptureRequestOptions.requestedOptions;
|
||||||
|
expect(requestedOptions.length, equals(1));
|
||||||
|
expect(requestedOptions.first.$1,
|
||||||
|
equals(CaptureRequestKeySupportedType.controlAeLock));
|
||||||
|
expect(requestedOptions.first.$2, equals(true));
|
||||||
|
});
|
||||||
|
|
||||||
test(
|
test(
|
||||||
'setExposurePoint clears current auto-exposure metering point as expected',
|
'setExposurePoint clears current auto-exposure metering point as expected',
|
||||||
() async {
|
() async {
|
||||||
|
@ -8,11 +8,14 @@ import 'dart:typed_data' as _i29;
|
|||||||
|
|
||||||
import 'package:camera_android_camerax/src/analyzer.dart' as _i15;
|
import 'package:camera_android_camerax/src/analyzer.dart' as _i15;
|
||||||
import 'package:camera_android_camerax/src/camera.dart' as _i9;
|
import 'package:camera_android_camerax/src/camera.dart' as _i9;
|
||||||
|
import 'package:camera_android_camerax/src/camera2_camera_control.dart' as _i38;
|
||||||
import 'package:camera_android_camerax/src/camera_control.dart' as _i3;
|
import 'package:camera_android_camerax/src/camera_control.dart' as _i3;
|
||||||
import 'package:camera_android_camerax/src/camera_info.dart' as _i2;
|
import 'package:camera_android_camerax/src/camera_info.dart' as _i2;
|
||||||
import 'package:camera_android_camerax/src/camera_selector.dart' as _i22;
|
import 'package:camera_android_camerax/src/camera_selector.dart' as _i22;
|
||||||
import 'package:camera_android_camerax/src/camera_state.dart' as _i18;
|
import 'package:camera_android_camerax/src/camera_state.dart' as _i18;
|
||||||
import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i7;
|
import 'package:camera_android_camerax/src/camerax_library.g.dart' as _i7;
|
||||||
|
import 'package:camera_android_camerax/src/capture_request_options.dart'
|
||||||
|
as _i39;
|
||||||
import 'package:camera_android_camerax/src/exposure_state.dart' as _i5;
|
import 'package:camera_android_camerax/src/exposure_state.dart' as _i5;
|
||||||
import 'package:camera_android_camerax/src/fallback_strategy.dart' as _i23;
|
import 'package:camera_android_camerax/src/fallback_strategy.dart' as _i23;
|
||||||
import 'package:camera_android_camerax/src/focus_metering_action.dart' as _i21;
|
import 'package:camera_android_camerax/src/focus_metering_action.dart' as _i21;
|
||||||
@ -1317,6 +1320,38 @@ class MockZoomState extends _i1.Mock implements _i19.ZoomState {
|
|||||||
) as double);
|
) as double);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A class which mocks [Camera2CameraControl].
|
||||||
|
///
|
||||||
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
// ignore: must_be_immutable
|
||||||
|
class MockCamera2CameraControl extends _i1.Mock
|
||||||
|
implements _i38.Camera2CameraControl {
|
||||||
|
@override
|
||||||
|
_i3.CameraControl get cameraControl => (super.noSuchMethod(
|
||||||
|
Invocation.getter(#cameraControl),
|
||||||
|
returnValue: _FakeCameraControl_1(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#cameraControl),
|
||||||
|
),
|
||||||
|
returnValueForMissingStub: _FakeCameraControl_1(
|
||||||
|
this,
|
||||||
|
Invocation.getter(#cameraControl),
|
||||||
|
),
|
||||||
|
) as _i3.CameraControl);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_i16.Future<void> addCaptureRequestOptions(
|
||||||
|
_i39.CaptureRequestOptions? captureRequestOptions) =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.method(
|
||||||
|
#addCaptureRequestOptions,
|
||||||
|
[captureRequestOptions],
|
||||||
|
),
|
||||||
|
returnValue: _i16.Future<void>.value(),
|
||||||
|
returnValueForMissingStub: _i16.Future<void>.value(),
|
||||||
|
) as _i16.Future<void>);
|
||||||
|
}
|
||||||
|
|
||||||
/// A class which mocks [LiveData].
|
/// A class which mocks [LiveData].
|
||||||
///
|
///
|
||||||
/// See the documentation for Mockito's code generation for more information.
|
/// See the documentation for Mockito's code generation for more information.
|
||||||
|
Reference in New Issue
Block a user