From 8c636159d17397c8e3bda5a01a1158f4f09659bc Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 29 Jul 2023 13:08:38 -0300 Subject: [PATCH 01/71] add heic support image iOS --- packages/camera/camera/CHANGELOG.md | 4 + packages/camera/camera/pubspec.yaml | 2 +- .../camera/camera_avfoundation/CHANGELOG.md | 4 + .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 4 +- .../ios/Classes/CameraPlugin.m | 15 +- .../camera_avfoundation/ios/Classes/FLTCam.h | 8 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 20 +- .../ios/Classes/FLTCam_Test.h | 3 + .../lib/src/avfoundation_camera.dart | 111 ++--- .../camera/camera_avfoundation/pubspec.yaml | 2 +- .../test/avfoundation_camera_test.dart | 374 ++++++---------- .../camera_platform_interface/CHANGELOG.md | 4 + .../lib/src/events/camera_event.dart | 38 +- .../method_channel/method_channel_camera.dart | 108 ++--- .../lib/src/types/image_format.dart | 35 ++ .../lib/src/types/types.dart | 1 + .../camera_platform_interface/pubspec.yaml | 2 +- .../test/events/camera_event_test.dart | 160 ++++--- .../method_channel_camera_test.dart | 409 +++++++----------- 19 files changed, 568 insertions(+), 736 deletions(-) create mode 100644 packages/camera/camera_platform_interface/lib/src/types/image_format.dart diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 206048ad592..b820ce5fbb8 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.10.6 + +* Add support to HEIC format to iOS + ## 0.10.5+2 * Fixes unawaited_futures violations. diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index f4ffc8fa101..24bd0cbfba3 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -23,7 +23,7 @@ flutter: dependencies: camera_android: ^0.10.7 camera_avfoundation: ^0.9.13 - camera_platform_interface: ^2.5.0 + camera_platform_interface: ^2.5.2 camera_web: ^0.3.1 flutter: sdk: flutter diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 2133c7935c0..29cb18f4b42 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -2,6 +2,10 @@ * Fixes unawaited_futures violations. +## 0.9.14 + +* Add support to HEIC format + ## 0.9.13+2 * Removes obsolete null checks on non-nullable values. diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 8a7c34cc273..5f43ac4434e 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -49,7 +49,7 @@ - (void)testCaptureToFile_mustReportErrorToResultIfSavePhotoDelegateCompletionsW // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult]; + [cam captureToFile:mockResult imageFormat:ImageFormatHEIC]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -89,7 +89,7 @@ - (void)testCaptureToFile_mustReportPathToResultIfSavePhotoDelegateCompletionsWi // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult]; + [cam captureToFile:mockResult imageFormat:ImageFormatHEIC]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index 874f37b6c4f..2e7cd9c94cc 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -183,9 +183,18 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call [self sendDeviceOrientation:[UIDevice currentDevice].orientation]; [_camera start]; [result sendSuccess]; - } else if ([@"takePicture" isEqualToString:call.method]) { - [_camera captureToFile:result]; - } else if ([@"dispose" isEqualToString:call.method]) { + }else if ([@"takePicture" isEqualToString:call.method]) { + NSString *formatString = call.arguments[@"imageExtension"]; + + ImageFormat imageFormat = ImageFormatJPEG; + if ([formatString isEqualToString:@"heic"]) { + imageFormat = ImageFormatHEIC; + } + + + [_camera captureToFile:result imageFormat:imageFormat]; + } + else if ([@"dispose" isEqualToString:call.method]) { [_registry unregisterTexture:cameraId]; [_camera close]; [result sendSuccess]; diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index fbf4ef4882c..d702d1ad3ca 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -14,6 +14,11 @@ NS_ASSUME_NONNULL_BEGIN +typedef NS_ENUM(NSInteger, ImageFormat) { + ImageFormatJPEG, + ImageFormatHEIC, +}; + /** * A class that manages camera's state and performs camera operations. */ @@ -30,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN @property(assign, nonatomic) FLTFlashMode flashMode; // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; +@property(readonly, nonatomic) ImageFormat imageFormat; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. @@ -47,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)start; - (void)stop; - (void)setDeviceOrientation:(UIDeviceOrientation)orientation; -- (void)captureToFile:(FLTThreadSafeFlutterResult *)result; +- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageFormat:(ImageFormat)imageFormat; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; /** diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 31bffc91794..8a9056b42f5 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -244,18 +244,34 @@ - (void)updateOrientation:(UIDeviceOrientation)orientation } } -- (void)captureToFile:(FLTThreadSafeFlutterResult *)result { +- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageFormat:(ImageFormat)imageFormat { AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; + NSString *extension; if (_resolutionPreset == FLTResolutionPresetMax) { [settings setHighResolutionPhotoEnabled:YES]; } + + if (self.imageFormat == ImageFormatHEIC) { + if (@available(iOS 11.0, *)) { + if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { + settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{ AVVideoCodecKey : AVVideoCodecTypeHEVC }]; + extension = @"heic"; + } else { + settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{ AVVideoCodecKey : AVVideoCodecTypeJPEG }]; + extension = @"jpg"; + } + } else { + extension = @"jpg"; + } + } + AVCaptureFlashMode avFlashMode = FLTGetAVCaptureFlashModeForFLTFlashMode(_flashMode); if (avFlashMode != -1) { [settings setFlashMode:avFlashMode]; } NSError *error; - NSString *path = [self getTemporaryFilePathWithExtension:@"jpg" + NSString *path = [self getTemporaryFilePathWithExtension:extension subfolder:@"pictures" prefix:@"CAP_" error:error]; diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h index acc64846cb2..272fafaad62 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h @@ -30,6 +30,9 @@ /// True when images from the camera are being streamed. @property(assign, nonatomic) BOOL isStreamingImages; +/// The output format image capturing. +@property(assign, nonatomic) ImageFormat imageFormat; + /// A dictionary to retain all in-progress FLTSavePhotoDelegates. The key of the dictionary is the /// AVCapturePhotoSettings's uniqueID for each photo capture operation, and the value is the /// FLTSavePhotoDelegate that handles the result of each photo capture operation. Note that photo diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 33f550b3211..585789d669a 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,8 +14,7 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = - MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -29,8 +28,7 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = - 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -40,16 +38,14 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = - _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -65,14 +61,13 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -81,8 +76,7 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -98,12 +92,9 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -119,10 +110,8 @@ class AVFoundationCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel( - 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -199,8 +188,7 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream - .whereType(); + return _deviceEventStreamController.stream.whereType(); } @override @@ -210,10 +198,7 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -226,10 +211,10 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future takePicture(int cameraId) async { + Future takePicture(int cameraId, {ImageFormat imageFormat = ImageFormat.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId}, + {'cameraId': cameraId, 'imageFormat': _serializeImageFormat(imageFormat)}, ); if (path == null) { @@ -243,14 +228,11 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -295,22 +277,18 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { - _frameStreamController = - _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController( - {Function()? onListen}) { + StreamController _createStreamController({Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -329,17 +307,14 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -351,13 +326,11 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -366,8 +339,7 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -435,8 +407,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -512,8 +483,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -573,13 +543,23 @@ class AVFoundationCamera extends CameraPlatform { return 'max'; } + /// Returns the format of the image as a String. + String _serializeImageFormat(ImageFormat format) { + switch (format) { + case ImageFormat.jpeg: + return 'jpeg'; + case ImageFormat.heic: + return 'heic'; + } + } + /// Converts messages received from the native platform into device events. Future _handleDeviceMethodCall(MethodCall call) async { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -603,6 +583,7 @@ class AVFoundationCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, + deserializeImageFormat(arguments['imageFormat']! as String), )); break; case 'resolution_changed': @@ -623,9 +604,7 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index f6137d59f68..b72a7d60eca 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_avfoundation description: iOS implementation of the camera plugin. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.13+2 +version: 0.9.14 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 17b06cddc1a..8deaa3590c7 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -32,37 +32,31 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(const MethodCall( - 'orientation_changed', - {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AVFoundationCamera camera = AVFoundationCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -70,18 +64,13 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -103,16 +92,13 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -134,10 +120,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -161,10 +145,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -176,15 +157,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -205,6 +185,7 @@ void main() { true, FocusMode.auto, true, + ImageFormat.jpeg, )); await initializeFuture; @@ -224,13 +205,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( @@ -250,6 +230,7 @@ void main() { true, FocusMode.auto, true, + ImageFormat.jpeg, )); await initializeFuture; @@ -298,16 +279,15 @@ void main() { true, FocusMode.auto, true, + ImageFormat.jpeg, )); await initializeFuture; }); test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -318,9 +298,9 @@ void main() { true, FocusMode.auto, true, + ImageFormat.jpeg, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -331,24 +311,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -362,19 +335,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -387,20 +355,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -413,22 +375,17 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -472,28 +429,20 @@ void main() { true, FocusMode.auto, true, + ImageFormat.jpeg, ), ); await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange // This deliberately uses 'dynamic' since that's what actual platform // channel results will be, so using typed mock data could mask type // handling bugs in the code under test. final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -509,21 +458,17 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -537,19 +482,16 @@ void main() { camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should take a picture and return an XFile instance', () async { + test('Should take a picture and return an XFile instance with jpeg format', () async { // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -558,11 +500,30 @@ void main() { expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, + 'imageFormat': 'jpeg', }), ]); expect(file.path, '/test/path.jpg'); }); + test('Should take a picture and return an XFile instance with heic format', () async { + // Arrange + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.heic'}); + + // Act + final XFile file = await camera.takePicture(cameraId, imageFormat: ImageFormat.heic); + + // Assert + expect(channel.log, [ + isMethodCall('takePicture', arguments: { + 'cameraId': cameraId, + 'imageFormat': 'heic', + }), + ]); + expect(file.path, '/test/path.heic'); + }); + test('Should prepare for video recording', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( @@ -599,8 +560,7 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -623,9 +583,7 @@ void main() { ]); }); - test( - 'Should pass enableStream if callback is passed when starting recording a video', - () async { + test('Should pass enableStream if callback is passed when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -633,8 +591,7 @@ void main() { ); // Act - await camera.startVideoCapturing(VideoCaptureOptions(cameraId, - streamCallback: (CameraImageData imageData) {})); + await camera.startVideoCapturing(VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {})); // Assert expect(channel.log, [ @@ -707,20 +664,17 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = CameraDescription( - name: 'Test2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 0); + const CameraDescription camera2Description = + CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -739,18 +693,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -767,12 +713,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -789,18 +731,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -812,8 +746,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -832,8 +765,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -896,12 +828,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -918,18 +846,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -942,13 +862,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final AVFoundationCamera camera = AVFoundationCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -1002,13 +919,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -1025,8 +940,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1037,15 +951,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1061,8 +972,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1078,8 +988,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1095,8 +1004,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1111,9 +1019,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1134,9 +1041,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index 7b21165d864..3ad48c1ff3a 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 2.5.2 + +* Add support to HEIC format on take picture (only iOS). + ## 2.5.1 * Removes obsolete null checks on non-nullable values. diff --git a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart index 1c76c341d9b..f6433a57e63 100644 --- a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart +++ b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart @@ -34,10 +34,7 @@ abstract class CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || - other is CameraEvent && - runtimeType == other.runtimeType && - cameraId == other.cameraId; + identical(this, other) || other is CameraEvent && runtimeType == other.runtimeType && cameraId == other.cameraId; @override int get hashCode => cameraId.hashCode; @@ -58,6 +55,7 @@ class CameraInitializedEvent extends CameraEvent { this.exposurePointSupported, this.focusMode, this.focusPointSupported, + this.imageFormat, ); /// Converts the supplied [Map] to an instance of the [CameraInitializedEvent] @@ -66,10 +64,10 @@ class CameraInitializedEvent extends CameraEvent { : previewWidth = json['previewWidth']! as double, previewHeight = json['previewHeight']! as double, exposureMode = deserializeExposureMode(json['exposureMode']! as String), - exposurePointSupported = - (json['exposurePointSupported'] as bool?) ?? false, + exposurePointSupported = (json['exposurePointSupported'] as bool?) ?? false, focusMode = deserializeFocusMode(json['focusMode']! as String), focusPointSupported = (json['focusPointSupported'] as bool?) ?? false, + imageFormat = deserializeImageFormat(json['imageFormat']! as String), super(json['cameraId']! as int); /// The width of the preview in pixels. @@ -90,6 +88,9 @@ class CameraInitializedEvent extends CameraEvent { /// Whether setting focus points is supported. final bool focusPointSupported; + /// The default image format + final ImageFormat imageFormat; + /// Converts the [CameraInitializedEvent] instance into a [Map] instance that /// can be serialized to JSON. Map toJson() => { @@ -100,6 +101,7 @@ class CameraInitializedEvent extends CameraEvent { 'exposurePointSupported': exposurePointSupported, 'focusMode': serializeFocusMode(focusMode), 'focusPointSupported': focusPointSupported, + 'imageFormat': serializeImageFormat(imageFormat), }; @override @@ -113,7 +115,8 @@ class CameraInitializedEvent extends CameraEvent { exposureMode == other.exposureMode && exposurePointSupported == other.exposurePointSupported && focusMode == other.focusMode && - focusPointSupported == other.focusPointSupported; + focusPointSupported == other.focusPointSupported && + imageFormat == other.imageFormat; @override int get hashCode => Object.hash( @@ -124,6 +127,7 @@ class CameraInitializedEvent extends CameraEvent { exposurePointSupported, focusMode, focusPointSupported, + imageFormat, ); } @@ -182,8 +186,7 @@ class CameraClosingEvent extends CameraEvent { /// Converts the supplied [Map] to an instance of the [CameraClosingEvent] /// class. - CameraClosingEvent.fromJson(Map json) - : super(json['cameraId']! as int); + CameraClosingEvent.fromJson(Map json) : super(json['cameraId']! as int); /// Converts the [CameraClosingEvent] instance into a [Map] instance that can /// be serialized to JSON. @@ -193,10 +196,7 @@ class CameraClosingEvent extends CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || - super == other && - other is CameraClosingEvent && - runtimeType == other.runtimeType; + identical(this, other) || super == other && other is CameraClosingEvent && runtimeType == other.runtimeType; @override // This is here even though it just calls super to make it less likely that @@ -254,9 +254,8 @@ class VideoRecordedEvent extends CameraEvent { /// class. VideoRecordedEvent.fromJson(Map json) : file = XFile(json['path']! as String), - maxVideoDuration = json['maxVideoDuration'] != null - ? Duration(milliseconds: json['maxVideoDuration'] as int) - : null, + maxVideoDuration = + json['maxVideoDuration'] != null ? Duration(milliseconds: json['maxVideoDuration'] as int) : null, super(json['cameraId']! as int); /// XFile of the recorded video. @@ -267,11 +266,8 @@ class VideoRecordedEvent extends CameraEvent { /// Converts the [VideoRecordedEvent] instance into a [Map] instance that can be /// serialized to JSON. - Map toJson() => { - 'cameraId': cameraId, - 'path': file.path, - 'maxVideoDuration': maxVideoDuration?.inMilliseconds - }; + Map toJson() => + {'cameraId': cameraId, 'path': file.path, 'maxVideoDuration': maxVideoDuration?.inMilliseconds}; @override bool operator ==(Object other) => diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 14d20fc817b..390dd451f54 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,10 +20,8 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler( - (MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -36,8 +34,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -47,8 +44,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = - StreamController.broadcast(); + final StreamController deviceEventStreamController = StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -57,14 +53,13 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -73,8 +68,7 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -90,12 +84,9 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -111,10 +102,8 @@ class MethodChannelCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -191,8 +180,7 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream - .whereType(); + return deviceEventStreamController.stream.whereType(); } @override @@ -202,10 +190,7 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -218,10 +203,10 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future takePicture(int cameraId) async { + Future takePicture(int cameraId, {ImageFormat imageFormat = ImageFormat.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId}, + {'cameraId': cameraId, 'imageFormat': _serializeImageFormat(imageFormat)}, ); if (path == null) { @@ -235,14 +220,11 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -286,21 +268,18 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController( - {Function()? onListen}) { + StreamController _installStreamController({Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -320,10 +299,8 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -331,8 +308,7 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -344,13 +320,11 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -359,8 +333,7 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -428,8 +401,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -505,8 +477,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -552,6 +523,16 @@ class MethodChannelCamera extends CameraPlatform { } } + /// Returns the image format as a String. + String _serializeImageFormat(ImageFormat format) { + switch (format) { + case ImageFormat.jpeg: + return 'jpeg'; + case ImageFormat.heic: + return 'heic'; + } + } + /// Converts messages received from the native platform into device events. /// /// This is only exposed for test purposes. It shouldn't be used by clients of @@ -560,8 +541,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -585,6 +566,7 @@ class MethodChannelCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, + deserializeImageFormat(arguments['imageFormat']! as String), )); break; case 'resolution_changed': @@ -605,9 +587,7 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_format.dart b/packages/camera/camera_platform_interface/lib/src/types/image_format.dart new file mode 100644 index 00000000000..8ac17cbab86 --- /dev/null +++ b/packages/camera/camera_platform_interface/lib/src/types/image_format.dart @@ -0,0 +1,35 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// The format in which images should be returned from the camera. +/// Will works only on iOS and only iOS 11+. +enum ImageFormat { + /// The default format for the device. + jpeg, + + /// The efficient format for iOS devices. + heic, +} + +/// Returns the image format as a String. +String serializeImageFormat(ImageFormat imageFormat) { + switch (imageFormat) { + case ImageFormat.jpeg: + return 'jpeg'; + case ImageFormat.heic: + return 'heic'; + } +} + +/// Returns the image format as a String. +ImageFormat deserializeImageFormat(String str) { + switch (str) { + case 'jpeg': + return ImageFormat.jpeg; + case 'heic': + return ImageFormat.heic; + default: + throw ArgumentError('"$str" is not a valid image format.'); + } +} diff --git a/packages/camera/camera_platform_interface/lib/src/types/types.dart b/packages/camera/camera_platform_interface/lib/src/types/types.dart index a8a4f8ca5dc..26bda10e97f 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/types.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/types.dart @@ -8,6 +8,7 @@ export 'camera_image_data.dart'; export 'exposure_mode.dart'; export 'flash_mode.dart'; export 'focus_mode.dart'; +export 'image_format.dart'; export 'image_format_group.dart'; export 'resolution_preset.dart'; export 'video_capture_options.dart'; diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml index 3dc49cec038..77f0798999d 100644 --- a/packages/camera/camera_platform_interface/pubspec.yaml +++ b/packages/camera/camera_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.5.1 +version: 2.5.2 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 074f203bea2..5ea72994529 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -20,18 +20,19 @@ void main() { expect(event.focusMode, FocusMode.auto); expect(event.exposurePointSupported, true); expect(event.focusPointSupported, true); + expect(event.imageFormat, ImageFormat.jpeg); }); test('fromJson should initialize all properties', () { - final CameraInitializedEvent event = - CameraInitializedEvent.fromJson(const { + final CameraInitializedEvent event = CameraInitializedEvent.fromJson(const { 'cameraId': 1, 'previewWidth': 1024.0, 'previewHeight': 640.0, 'exposureMode': 'auto', 'exposurePointSupported': true, 'focusMode': 'auto', - 'focusPointSupported': true + 'focusPointSupported': true, + 'imageFormat': 'jpeg', }); expect(event.cameraId, 1); @@ -44,12 +45,12 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraInitializedEvent event = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.heic); final Map jsonMap = event.toJson(); - expect(jsonMap.length, 7); + expect(jsonMap.length, 8); expect(jsonMap['cameraId'], 1); expect(jsonMap['previewWidth'], 1024); expect(jsonMap['previewHeight'], 640); @@ -57,92 +58,103 @@ void main() { expect(jsonMap['exposurePointSupported'], true); expect(jsonMap['focusMode'], 'auto'); expect(jsonMap['focusPointSupported'], true); + expect(jsonMap['imageFormat'], 'heic'); }); test('equals should return true if objects are the same', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); - test('equals should return false if exposurePointSupported is different', - () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); + test('equals should return false if exposurePointSupported is different', () { + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false, ImageFormat.jpeg); + + expect(firstEvent == secondEvent, false); + }); + + test('equals should return true if imageFormat is different', () { + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.heic); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); final int expectedHashCode = Object.hash( - event.cameraId.hashCode, - event.previewWidth, - event.previewHeight, - event.exposureMode, - event.exposurePointSupported, - event.focusMode, - event.focusPointSupported); + event.cameraId.hashCode, + event.previewWidth, + event.previewHeight, + event.exposureMode, + event.exposurePointSupported, + event.focusMode, + event.focusPointSupported, + event.imageFormat, + ); expect(event.hashCode, expectedHashCode); }); @@ -150,8 +162,7 @@ void main() { group('CameraResolutionChangesEvent tests', () { test('Constructor should initialize all properties', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); expect(event.cameraId, 1); expect(event.captureWidth, 1024); @@ -159,8 +170,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraResolutionChangedEvent event = - CameraResolutionChangedEvent.fromJson(const { + final CameraResolutionChangedEvent event = CameraResolutionChangedEvent.fromJson(const { 'cameraId': 1, 'captureWidth': 1024.0, 'captureHeight': 640.0, @@ -172,8 +182,7 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); final Map jsonMap = event.toJson(); @@ -184,44 +193,35 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 640); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(2, 1024, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(2, 1024, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureWidth is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 2048, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 2048, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureHeight is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 1024, 980); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 980); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.captureWidth, @@ -240,8 +240,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraClosingEvent event = - CameraClosingEvent.fromJson(const { + final CameraClosingEvent event = CameraClosingEvent.fromJson(const { 'cameraId': 1, }); @@ -288,8 +287,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraErrorEvent event = CameraErrorEvent.fromJson( - const {'cameraId': 1, 'description': 'Error'}); + final CameraErrorEvent event = + CameraErrorEvent.fromJson(const {'cameraId': 1, 'description': 'Error'}); expect(event.cameraId, 1); expect(event.description, 'Error'); @@ -328,8 +327,7 @@ void main() { test('hashCode should match hashCode of all properties', () { const CameraErrorEvent event = CameraErrorEvent(1, 'Error'); - final int expectedHashCode = - Object.hash(event.cameraId.hashCode, event.description); + final int expectedHashCode = Object.hash(event.cameraId.hashCode, event.description); expect(event.hashCode, expectedHashCode); }); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index 1fd6445e746..f1187c08cda 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -22,22 +22,18 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -45,28 +41,20 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test( - 'Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -81,26 +69,20 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test( - 'Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -115,10 +97,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -142,10 +122,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having((CameraException e) => e.code, 'code', - 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,15 +134,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -186,6 +162,7 @@ void main() { true, FocusMode.auto, true, + ImageFormat.heic, )); await initializeFuture; @@ -205,13 +182,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( @@ -231,6 +207,7 @@ void main() { true, FocusMode.auto, true, + ImageFormat.heic, )); await initializeFuture; @@ -279,16 +256,15 @@ void main() { true, FocusMode.auto, true, + ImageFormat.heic, )); await initializeFuture; }); test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -299,9 +275,9 @@ void main() { true, FocusMode.auto, true, + ImageFormat.heic, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -312,24 +288,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -343,19 +312,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -368,20 +332,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -394,20 +352,15 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); // Assert expect(await streamQueue.next, event); @@ -450,25 +403,17 @@ void main() { true, FocusMode.auto, true, + ImageFormat.heic, ), ); await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -484,49 +429,40 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'availableCameras': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'availableCameras': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); // Act expect( camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should take a picture and return an XFile instance', () async { + test('Should take a picture and return an XFile instance with jpg extension', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: {'takePicture': '/test/path.jpg'}); + channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -535,11 +471,30 @@ void main() { expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, + 'imageFormat': 'jpeg', }), ]); expect(file.path, '/test/path.jpg'); }); + test('Should take a picture and return an XFile instance with heic extension', () async { + // Arrange + final MethodChannelMock channel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.heic'}); + + // Act + final XFile file = await camera.takePicture(cameraId, imageFormat: ImageFormat.heic); + + // Assert + expect(channel.log, [ + isMethodCall('takePicture', arguments: { + 'cameraId': cameraId, + 'imageFormat': 'heic', + }), + ]); + expect(file.path, '/test/path.heic'); + }); + test('Should prepare for video recording', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( @@ -584,23 +539,18 @@ void main() { ); // Act - const CameraDescription cameraDescription = CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0); + const CameraDescription cameraDescription = + CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0); await camera.setDescriptionWhileRecording(cameraDescription); // Assert expect(channel.log, [ isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': cameraDescription.name - }), + arguments: {'cameraName': cameraDescription.name}), ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -693,22 +643,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'off' - }), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -725,14 +663,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -749,18 +681,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -772,8 +696,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -792,8 +715,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -812,16 +734,14 @@ void main() { ); // Act - final double stepSize = - await camera.getExposureOffsetStepSize(cameraId); + final double stepSize = await camera.getExposureOffsetStepSize(cameraId); // Assert expect(stepSize, 0.25); expect(channel.log, [ - isMethodCall('getExposureOffsetStepSize', - arguments: { - 'cameraId': cameraId, - }), + isMethodCall('getExposureOffsetStepSize', arguments: { + 'cameraId': cameraId, + }), ]); }); @@ -833,8 +753,7 @@ void main() { ); // Act - final double actualOffset = - await camera.setExposureOffset(cameraId, 0.5); + final double actualOffset = await camera.setExposureOffset(cameraId, 0.5); // Assert expect(actualOffset, 0.6); @@ -859,14 +778,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -883,18 +796,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -907,13 +812,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final MethodChannelCamera camera = MethodChannelCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -967,13 +869,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -990,8 +890,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1002,15 +901,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1026,8 +922,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1043,8 +938,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1060,8 +954,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1076,9 +969,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1099,9 +991,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert From 78a86ec1a40299d7e8009078c1e4654373aed998 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 29 Jul 2023 14:11:40 -0300 Subject: [PATCH 02/71] format files --- .../camera_avfoundation/ios/Classes/FLTCam.h | 3 + .../lib/src/avfoundation_camera.dart | 104 +++-- .../test/avfoundation_camera_test.dart | 362 ++++++++++------ .../lib/src/events/camera_event.dart | 28 +- .../method_channel/method_channel_camera.dart | 101 +++-- .../test/events/camera_event_test.dart | 164 +++++--- .../method_channel_camera_test.dart | 397 ++++++++++++------ 7 files changed, 775 insertions(+), 384 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index d702d1ad3ca..e26a8aa2f2d 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -14,6 +14,9 @@ NS_ASSUME_NONNULL_BEGIN +/** + * Represents image format. Mirrors ImageFormat in camera.dart. + */ typedef NS_ENUM(NSInteger, ImageFormat) { ImageFormatJPEG, ImageFormatHEIC, diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 585789d669a..900532d6c60 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,7 +14,8 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = + MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -28,7 +29,8 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = + 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -38,14 +40,16 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = + _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -61,13 +65,14 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -76,7 +81,8 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -92,9 +98,12 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -110,8 +119,10 @@ class AVFoundationCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel( + 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -188,7 +199,8 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream.whereType(); + return _deviceEventStreamController.stream + .whereType(); } @override @@ -198,7 +210,10 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -211,10 +226,14 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, {ImageFormat imageFormat = ImageFormat.jpeg}) async { + Future takePicture(int cameraId, + {ImageFormat imageFormat = ImageFormat.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId, 'imageFormat': _serializeImageFormat(imageFormat)}, + { + 'cameraId': cameraId, + 'imageFormat': _serializeImageFormat(imageFormat) + }, ); if (path == null) { @@ -228,11 +247,14 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -277,18 +299,22 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { - _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { + _frameStreamController = + _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController({Function()? onListen}) { + StreamController _createStreamController( + {Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -307,14 +333,17 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -326,11 +355,13 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -339,7 +370,8 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -407,7 +439,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -483,7 +516,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -558,8 +592,8 @@ class AVFoundationCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -604,7 +638,9 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 8deaa3590c7..9d7912b9435 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -32,31 +32,37 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(const MethodCall( + 'orientation_changed', + {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AVFoundationCamera camera = AVFoundationCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -64,13 +70,18 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -92,13 +103,16 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -120,8 +134,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -145,7 +161,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,14 +176,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -205,12 +225,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( @@ -286,8 +307,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -300,7 +323,8 @@ void main() { true, ImageFormat.jpeg, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -311,17 +335,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -335,14 +366,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -355,14 +391,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -375,17 +417,22 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -435,14 +482,23 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange // This deliberately uses 'dynamic' since that's what actual platform // channel results will be, so using typed mock data could mask type // handling bugs in the code under test. final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -458,17 +514,21 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -482,16 +542,20 @@ void main() { camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should take a picture and return an XFile instance with jpeg format', () async { + test('Should take a picture and return an XFile instance with jpeg format', + () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -506,13 +570,16 @@ void main() { expect(file.path, '/test/path.jpg'); }); - test('Should take a picture and return an XFile instance with heic format', () async { + test('Should take a picture and return an XFile instance with heic format', + () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.heic'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.heic'}); // Act - final XFile file = await camera.takePicture(cameraId, imageFormat: ImageFormat.heic); + final XFile file = + await camera.takePicture(cameraId, imageFormat: ImageFormat.heic); // Assert expect(channel.log, [ @@ -560,7 +627,8 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -583,7 +651,9 @@ void main() { ]); }); - test('Should pass enableStream if callback is passed when starting recording a video', () async { + test( + 'Should pass enableStream if callback is passed when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -591,7 +661,8 @@ void main() { ); // Act - await camera.startVideoCapturing(VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {})); + await camera.startVideoCapturing(VideoCaptureOptions(cameraId, + streamCallback: (CameraImageData imageData) {})); // Assert expect(channel.log, [ @@ -664,17 +735,20 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = - CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); + const CameraDescription camera2Description = CameraDescription( + name: 'Test2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', + arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -693,10 +767,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -713,8 +795,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -731,10 +817,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -746,7 +840,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -765,7 +860,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -828,8 +924,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -846,10 +946,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -862,10 +970,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final AVFoundationCamera camera = AVFoundationCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -919,11 +1030,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -940,7 +1053,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -951,12 +1065,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -972,7 +1089,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -988,7 +1106,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -1004,7 +1123,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -1019,8 +1139,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1041,8 +1162,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart index f6433a57e63..1df34fcc18b 100644 --- a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart +++ b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart @@ -34,7 +34,10 @@ abstract class CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || other is CameraEvent && runtimeType == other.runtimeType && cameraId == other.cameraId; + identical(this, other) || + other is CameraEvent && + runtimeType == other.runtimeType && + cameraId == other.cameraId; @override int get hashCode => cameraId.hashCode; @@ -64,7 +67,8 @@ class CameraInitializedEvent extends CameraEvent { : previewWidth = json['previewWidth']! as double, previewHeight = json['previewHeight']! as double, exposureMode = deserializeExposureMode(json['exposureMode']! as String), - exposurePointSupported = (json['exposurePointSupported'] as bool?) ?? false, + exposurePointSupported = + (json['exposurePointSupported'] as bool?) ?? false, focusMode = deserializeFocusMode(json['focusMode']! as String), focusPointSupported = (json['focusPointSupported'] as bool?) ?? false, imageFormat = deserializeImageFormat(json['imageFormat']! as String), @@ -186,7 +190,8 @@ class CameraClosingEvent extends CameraEvent { /// Converts the supplied [Map] to an instance of the [CameraClosingEvent] /// class. - CameraClosingEvent.fromJson(Map json) : super(json['cameraId']! as int); + CameraClosingEvent.fromJson(Map json) + : super(json['cameraId']! as int); /// Converts the [CameraClosingEvent] instance into a [Map] instance that can /// be serialized to JSON. @@ -196,7 +201,10 @@ class CameraClosingEvent extends CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || super == other && other is CameraClosingEvent && runtimeType == other.runtimeType; + identical(this, other) || + super == other && + other is CameraClosingEvent && + runtimeType == other.runtimeType; @override // This is here even though it just calls super to make it less likely that @@ -254,8 +262,9 @@ class VideoRecordedEvent extends CameraEvent { /// class. VideoRecordedEvent.fromJson(Map json) : file = XFile(json['path']! as String), - maxVideoDuration = - json['maxVideoDuration'] != null ? Duration(milliseconds: json['maxVideoDuration'] as int) : null, + maxVideoDuration = json['maxVideoDuration'] != null + ? Duration(milliseconds: json['maxVideoDuration'] as int) + : null, super(json['cameraId']! as int); /// XFile of the recorded video. @@ -266,8 +275,11 @@ class VideoRecordedEvent extends CameraEvent { /// Converts the [VideoRecordedEvent] instance into a [Map] instance that can be /// serialized to JSON. - Map toJson() => - {'cameraId': cameraId, 'path': file.path, 'maxVideoDuration': maxVideoDuration?.inMilliseconds}; + Map toJson() => { + 'cameraId': cameraId, + 'path': file.path, + 'maxVideoDuration': maxVideoDuration?.inMilliseconds + }; @override bool operator ==(Object other) => diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 390dd451f54..c9928c0f3c1 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,8 +20,10 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler( + (MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -34,7 +36,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -44,7 +47,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = StreamController.broadcast(); + final StreamController deviceEventStreamController = + StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -53,13 +57,14 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -68,7 +73,8 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -84,9 +90,12 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -102,8 +111,10 @@ class MethodChannelCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -180,7 +191,8 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream.whereType(); + return deviceEventStreamController.stream + .whereType(); } @override @@ -190,7 +202,10 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -203,10 +218,14 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, {ImageFormat imageFormat = ImageFormat.jpeg}) async { + Future takePicture(int cameraId, + {ImageFormat imageFormat = ImageFormat.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId, 'imageFormat': _serializeImageFormat(imageFormat)}, + { + 'cameraId': cameraId, + 'imageFormat': _serializeImageFormat(imageFormat) + }, ); if (path == null) { @@ -220,11 +239,14 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -268,18 +290,21 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController({Function()? onListen}) { + StreamController _installStreamController( + {Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -299,8 +324,10 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -308,7 +335,8 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -320,11 +348,13 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -333,7 +363,8 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -401,7 +432,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -477,7 +509,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -541,8 +574,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -587,7 +620,9 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 5ea72994529..0126b89939f 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, + ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -24,7 +24,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraInitializedEvent event = CameraInitializedEvent.fromJson(const { + final CameraInitializedEvent event = + CameraInitializedEvent.fromJson(const { 'cameraId': 1, 'previewWidth': 1024.0, 'previewHeight': 640.0, @@ -45,8 +46,8 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.heic); + const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, + ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.heic); final Map jsonMap = event.toJson(); @@ -62,89 +63,118 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent(2, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent(1, 2048, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent(1, 1024, + 980, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.locked, + true, + FocusMode.auto, + true, + ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); - test('equals should return false if exposurePointSupported is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true, ImageFormat.jpeg); + test('equals should return false if exposurePointSupported is different', + () { + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + false, + FocusMode.auto, + true, + ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.locked, + true, + ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + false, + ImageFormat.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return true if imageFormat is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.heic); + const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent(1, 1024, + 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.heic); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, + ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.previewWidth, @@ -162,7 +192,8 @@ void main() { group('CameraResolutionChangesEvent tests', () { test('Constructor should initialize all properties', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); expect(event.cameraId, 1); expect(event.captureWidth, 1024); @@ -170,7 +201,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraResolutionChangedEvent event = CameraResolutionChangedEvent.fromJson(const { + final CameraResolutionChangedEvent event = + CameraResolutionChangedEvent.fromJson(const { 'cameraId': 1, 'captureWidth': 1024.0, 'captureHeight': 640.0, @@ -182,7 +214,8 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); final Map jsonMap = event.toJson(); @@ -193,35 +226,44 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 1024, 640); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(2, 1024, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(2, 1024, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureWidth is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 2048, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 2048, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureHeight is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 980); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 1024, 980); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.captureWidth, @@ -240,7 +282,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraClosingEvent event = CameraClosingEvent.fromJson(const { + final CameraClosingEvent event = + CameraClosingEvent.fromJson(const { 'cameraId': 1, }); @@ -287,8 +330,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraErrorEvent event = - CameraErrorEvent.fromJson(const {'cameraId': 1, 'description': 'Error'}); + final CameraErrorEvent event = CameraErrorEvent.fromJson( + const {'cameraId': 1, 'description': 'Error'}); expect(event.cameraId, 1); expect(event.description, 'Error'); @@ -327,7 +370,8 @@ void main() { test('hashCode should match hashCode of all properties', () { const CameraErrorEvent event = CameraErrorEvent(1, 'Error'); - final int expectedHashCode = Object.hash(event.cameraId.hashCode, event.description); + final int expectedHashCode = + Object.hash(event.cameraId.hashCode, event.description); expect(event.hashCode, expectedHashCode); }); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index f1187c08cda..adbf220e3da 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -22,18 +22,22 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -41,20 +45,28 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test( + 'Should throw CameraException when create throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -69,20 +81,26 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test( + 'Should throw CameraException when create throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -97,8 +115,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -122,7 +142,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having((CameraException e) => e.code, 'code', + 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -134,14 +157,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -182,12 +206,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( @@ -263,8 +288,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -277,7 +304,8 @@ void main() { true, ImageFormat.heic, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -288,17 +316,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -312,14 +347,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -332,14 +372,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -352,15 +398,20 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); // Assert expect(await streamQueue.next, event); @@ -409,11 +460,20 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -429,40 +489,51 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'availableCameras': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'availableCameras': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); // Act expect( camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should take a picture and return an XFile instance with jpg extension', () async { + test( + 'Should take a picture and return an XFile instance with jpg extension', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.jpg'}); + channelName: 'plugins.flutter.io/camera', + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -477,13 +548,17 @@ void main() { expect(file.path, '/test/path.jpg'); }); - test('Should take a picture and return an XFile instance with heic extension', () async { + test( + 'Should take a picture and return an XFile instance with heic extension', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.heic'}); + channelName: 'plugins.flutter.io/camera', + methods: {'takePicture': '/test/path.heic'}); // Act - final XFile file = await camera.takePicture(cameraId, imageFormat: ImageFormat.heic); + final XFile file = + await camera.takePicture(cameraId, imageFormat: ImageFormat.heic); // Assert expect(channel.log, [ @@ -539,18 +614,23 @@ void main() { ); // Act - const CameraDescription cameraDescription = - CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0); + const CameraDescription cameraDescription = CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0); await camera.setDescriptionWhileRecording(cameraDescription); // Assert expect(channel.log, [ isMethodCall('setDescriptionWhileRecording', - arguments: {'cameraName': cameraDescription.name}), + arguments: { + 'cameraName': cameraDescription.name + }), ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -643,10 +723,22 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'off' + }), ]); }); @@ -663,8 +755,14 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -681,10 +779,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -696,7 +802,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -715,7 +822,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -734,14 +842,16 @@ void main() { ); // Act - final double stepSize = await camera.getExposureOffsetStepSize(cameraId); + final double stepSize = + await camera.getExposureOffsetStepSize(cameraId); // Assert expect(stepSize, 0.25); expect(channel.log, [ - isMethodCall('getExposureOffsetStepSize', arguments: { - 'cameraId': cameraId, - }), + isMethodCall('getExposureOffsetStepSize', + arguments: { + 'cameraId': cameraId, + }), ]); }); @@ -753,7 +863,8 @@ void main() { ); // Act - final double actualOffset = await camera.setExposureOffset(cameraId, 0.5); + final double actualOffset = + await camera.setExposureOffset(cameraId, 0.5); // Assert expect(actualOffset, 0.6); @@ -778,8 +889,14 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -796,10 +913,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -812,10 +937,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final MethodChannelCamera camera = MethodChannelCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -869,11 +997,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -890,7 +1020,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -901,12 +1032,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -922,7 +1056,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -938,7 +1073,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -954,7 +1090,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -969,8 +1106,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -991,8 +1129,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert From 88c72287955741ade04a1d4a3ec4b1a3d5add3d3 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 29 Jul 2023 17:01:42 -0300 Subject: [PATCH 03/71] update version camera_platform_interface --- packages/camera/camera_android/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml index 68e539e3919..095026841d8 100644 --- a/packages/camera/camera_android/pubspec.yaml +++ b/packages/camera/camera_android/pubspec.yaml @@ -19,7 +19,7 @@ flutter: dartPluginClass: AndroidCamera dependencies: - camera_platform_interface: ^2.5.0 + camera_platform_interface: ^2.5.2 flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.2 From a90a81bf82d3982b2d3899c1985f5cc5f6d7869a Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 29 Jul 2023 17:10:02 -0300 Subject: [PATCH 04/71] fix version --- packages/camera/camera/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 24bd0cbfba3..7cf3d3842e4 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing Dart. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.10.5+2 +version: 0.10.6 environment: sdk: ">=2.18.0 <4.0.0" From a98c0470ba31cc74b8585c793ad9b4338ddb8e05 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 29 Jul 2023 17:51:21 -0300 Subject: [PATCH 05/71] new test --- .../camera/camera_avfoundation/pubspec.yaml | 2 +- .../test/types/image_format_test.dart | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 packages/camera/camera_platform_interface/test/types/image_format_test.dart diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index b72a7d60eca..f627a03ebc2 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -17,7 +17,7 @@ flutter: dartPluginClass: AVFoundationCamera dependencies: - camera_platform_interface: ^2.4.0 + camera_platform_interface: ^2.5.2 flutter: sdk: flutter stream_transform: ^2.0.0 diff --git a/packages/camera/camera_platform_interface/test/types/image_format_test.dart b/packages/camera/camera_platform_interface/test/types/image_format_test.dart new file mode 100644 index 00000000000..e71940ee789 --- /dev/null +++ b/packages/camera/camera_platform_interface/test/types/image_format_test.dart @@ -0,0 +1,22 @@ +import 'package:camera_platform_interface/src/types/types.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$ImageFormat tests', () { + test('ImageFormat extension returns correct values', () { + expect(ImageFormat.jpeg.name, 'jpeg'); + expect(ImageFormat.heic.name, 'heic'); + }); + + test('ImageFormat serialization', () { + expect(serializeImageFormat(ImageFormat.jpeg), 'jpeg'); + expect(serializeImageFormat(ImageFormat.heic), 'heic'); + }); + + test('ImageFormat deserialization', () { + expect(deserializeImageFormat('jpeg'), ImageFormat.jpeg); + expect(deserializeImageFormat('heic'), ImageFormat.heic); + expect(() => deserializeImageFormat('invalid'), throwsArgumentError); + }); + }); +} From 19b6ee2c716d1dacc3ded8a0eb41efb738bf2c21 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 29 Jul 2023 17:52:34 -0300 Subject: [PATCH 06/71] update example --- packages/camera/camera_avfoundation/example/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/example/pubspec.yaml b/packages/camera/camera_avfoundation/example/pubspec.yaml index b1b16165517..957dfeacca3 100644 --- a/packages/camera/camera_avfoundation/example/pubspec.yaml +++ b/packages/camera/camera_avfoundation/example/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - camera_platform_interface: ^2.4.0 + camera_platform_interface: ^2.5.2 flutter: sdk: flutter path_provider: ^2.0.0 From 44b7f4339df26c4eb4deca7914e837edeeb68349 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 30 Jul 2023 11:35:58 -0300 Subject: [PATCH 07/71] refactor and adjusts code --- packages/camera/camera/lib/camera.dart | 3 +- .../camera/lib/src/camera_controller.dart | 135 ++-- packages/camera/camera/pubspec.yaml | 2 +- packages/camera/camera/test/camera_test.dart | 734 +++++------------- .../lib/src/android_camera.dart | 108 ++- .../test/android_camera_test.dart | 354 +++------ .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 4 +- .../ios/Classes/CameraPlugin.m | 6 +- .../camera_avfoundation/ios/Classes/FLTCam.h | 13 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 4 +- .../lib/src/avfoundation_camera.dart | 114 +-- .../camera/camera_avfoundation/pubspec.yaml | 3 +- .../test/avfoundation_camera_test.dart | 376 +++------ .../lib/src/events/camera_event.dart | 42 +- .../method_channel/method_channel_camera.dart | 113 +-- .../platform_interface/camera_platform.dart | 17 +- .../lib/src/types/image_extension.dart | 35 + .../lib/src/types/image_format.dart | 35 - .../lib/src/types/types.dart | 2 +- .../test/events/camera_event_test.dart | 170 ++-- .../method_channel_camera_test.dart | 411 ++++------ .../test/types/image_extension_test.dart | 22 + .../test/types/image_format_test.dart | 22 - 23 files changed, 912 insertions(+), 1813 deletions(-) create mode 100644 packages/camera/camera_platform_interface/lib/src/types/image_extension.dart delete mode 100644 packages/camera/camera_platform_interface/lib/src/types/image_format.dart create mode 100644 packages/camera/camera_platform_interface/test/types/image_extension_test.dart delete mode 100644 packages/camera/camera_platform_interface/test/types/image_format_test.dart diff --git a/packages/camera/camera/lib/camera.dart b/packages/camera/camera/lib/camera.dart index 900c2633a5d..624ab3e826e 100644 --- a/packages/camera/camera/lib/camera.dart +++ b/packages/camera/camera/lib/camera.dart @@ -12,7 +12,8 @@ export 'package:camera_platform_interface/camera_platform_interface.dart' FocusMode, ResolutionPreset, XFile, - ImageFormatGroup; + ImageFormatGroup, + ImageExtension; export 'src/camera_controller.dart'; export 'src/camera_image.dart'; diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index c907980b268..b7d7403ea10 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -183,21 +183,16 @@ class CameraValue { flashMode: flashMode ?? this.flashMode, exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, - exposurePointSupported: - exposurePointSupported ?? this.exposurePointSupported, + exposurePointSupported: exposurePointSupported ?? this.exposurePointSupported, focusPointSupported: focusPointSupported ?? this.focusPointSupported, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: lockedCaptureOrientation == null - ? this.lockedCaptureOrientation - : lockedCaptureOrientation.orNull, - recordingOrientation: recordingOrientation == null - ? this.recordingOrientation - : recordingOrientation.orNull, + lockedCaptureOrientation: + lockedCaptureOrientation == null ? this.lockedCaptureOrientation : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null ? this.recordingOrientation : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, description: description ?? this.description, - previewPauseOrientation: previewPauseOrientation == null - ? this.previewPauseOrientation - : previewPauseOrientation.orNull, + previewPauseOrientation: + previewPauseOrientation == null ? this.previewPauseOrientation : previewPauseOrientation.orNull, ); } @@ -237,6 +232,7 @@ class CameraController extends ValueNotifier { this.resolutionPreset, { this.enableAudio = true, this.imageFormatGroup, + this.imageExtension = ImageExtension.jpeg, }) : super(CameraValue.uninitialized(description)); /// The properties of the camera device controlled by this controller. @@ -258,6 +254,10 @@ class CameraController extends ValueNotifier { /// When null the imageFormat will fallback to the platforms default. final ImageFormatGroup? imageFormatGroup; + /// The image extension used for the camera. + /// For now only [iOS] supports this. + final ImageExtension imageExtension; + /// The id of a camera that hasn't been initialized. @visibleForTesting static const int kUninitializedCameraId = -1; @@ -266,8 +266,7 @@ class CameraController extends ValueNotifier { bool _isDisposed = false; StreamSubscription? _imageStreamSubscription; FutureOr? _initCalled; - StreamSubscription? - _deviceOrientationSubscription; + StreamSubscription? _deviceOrientationSubscription; /// Checks whether [CameraController.dispose] has completed successfully. /// @@ -295,12 +294,10 @@ class CameraController extends ValueNotifier { ); } try { - final Completer initializeCompleter = - Completer(); + final Completer initializeCompleter = Completer(); - _deviceOrientationSubscription = CameraPlatform.instance - .onDeviceOrientationChanged() - .listen((DeviceOrientationChangedEvent event) { + _deviceOrientationSubscription = + CameraPlatform.instance.onDeviceOrientationChanged().listen((DeviceOrientationChangedEvent event) { value = value.copyWith( deviceOrientation: event.orientation, ); @@ -312,10 +309,7 @@ class CameraController extends ValueNotifier { enableAudio: enableAudio, ); - _unawaited(CameraPlatform.instance - .onCameraInitialized(_cameraId) - .first - .then((CameraInitializedEvent event) { + _unawaited(CameraPlatform.instance.onCameraInitialized(_cameraId).first.then((CameraInitializedEvent event) { initializeCompleter.complete(event); })); @@ -327,19 +321,16 @@ class CameraController extends ValueNotifier { value = value.copyWith( isInitialized: true, description: description, - previewSize: await initializeCompleter.future - .then((CameraInitializedEvent event) => Size( - event.previewWidth, - event.previewHeight, - )), - exposureMode: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.exposureMode), - focusMode: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.focusMode), - exposurePointSupported: await initializeCompleter.future.then( - (CameraInitializedEvent event) => event.exposurePointSupported), - focusPointSupported: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.focusPointSupported), + previewSize: await initializeCompleter.future.then((CameraInitializedEvent event) => Size( + event.previewWidth, + event.previewHeight, + )), + exposureMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposureMode), + focusMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusMode), + exposurePointSupported: + await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposurePointSupported), + focusPointSupported: + await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusPointSupported), ); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -372,8 +363,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: Optional.of( - value.lockedCaptureOrientation ?? value.deviceOrientation)); + previewPauseOrientation: + Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -386,9 +377,8 @@ class CameraController extends ValueNotifier { } try { await CameraPlatform.instance.resumePreview(_cameraId); - value = value.copyWith( - isPreviewPaused: false, - previewPauseOrientation: const Optional.absent()); + value = + value.copyWith(isPreviewPaused: false, previewPauseOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -419,7 +409,7 @@ class CameraController extends ValueNotifier { } try { value = value.copyWith(isTakingPicture: true); - final XFile file = await CameraPlatform.instance.takePicture(_cameraId); + final XFile file = await CameraPlatform.instance.takePicture(_cameraId, imageExtension: imageExtension); value = value.copyWith(isTakingPicture: false); return file; } on PlatformException catch (e) { @@ -446,8 +436,7 @@ class CameraController extends ValueNotifier { /// // TODO(bmparr): Add settings for resolution and fps. Future startImageStream(onLatestImageAvailable onAvailable) async { - assert(defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('startImageStream'); if (value.isRecordingVideo) { throw CameraException( @@ -463,9 +452,8 @@ class CameraController extends ValueNotifier { } try { - _imageStreamSubscription = CameraPlatform.instance - .onStreamedFrameAvailable(_cameraId) - .listen((CameraImageData imageData) { + _imageStreamSubscription = + CameraPlatform.instance.onStreamedFrameAvailable(_cameraId).listen((CameraImageData imageData) { onAvailable(CameraImage.fromPlatformInterface(imageData)); }); value = value.copyWith(isStreamingImages: true); @@ -482,8 +470,7 @@ class CameraController extends ValueNotifier { /// The `stopImageStream` method is only available on Android and iOS (other /// platforms won't be supported in current setup). Future stopImageStream() async { - assert(defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('stopImageStream'); if (!value.isStreamingImages) { throw CameraException( @@ -508,8 +495,7 @@ class CameraController extends ValueNotifier { /// /// The video is returned as a [XFile] after calling [stopVideoRecording]. /// Throws a [CameraException] if the capture fails. - Future startVideoRecording( - {onLatestImageAvailable? onAvailable}) async { + Future startVideoRecording({onLatestImageAvailable? onAvailable}) async { _throwIfNotInitialized('startVideoRecording'); if (value.isRecordingVideo) { throw CameraException( @@ -526,13 +512,12 @@ class CameraController extends ValueNotifier { } try { - await CameraPlatform.instance.startVideoCapturing( - VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); + await CameraPlatform.instance.startVideoCapturing(VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, - recordingOrientation: Optional.of( - value.lockedCaptureOrientation ?? value.deviceOrientation), + recordingOrientation: + Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation), isStreamingImages: onAvailable != null); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -556,8 +541,7 @@ class CameraController extends ValueNotifier { } try { - final XFile file = - await CameraPlatform.instance.stopVideoRecording(_cameraId); + final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); value = value.copyWith( isRecordingVideo: false, recordingOrientation: const Optional.absent(), @@ -675,10 +659,8 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the exposure point to it's default /// value. Future setExposurePoint(Offset? point) async { - if (point != null && - (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError( - 'The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); } try { @@ -742,8 +724,7 @@ class CameraController extends ValueNotifier { Future setExposureOffset(double offset) async { _throwIfNotInitialized('setExposureOffset'); // Check if offset is in range - final List range = await Future.wait( - >[getMinExposureOffset(), getMaxExposureOffset()]); + final List range = await Future.wait(>[getMinExposureOffset(), getMaxExposureOffset()]); if (offset < range[0] || offset > range[1]) { throw CameraException( 'exposureOffsetOutOfBounds', @@ -776,11 +757,9 @@ class CameraController extends ValueNotifier { /// If [orientation] is omitted, the current device orientation is used. Future lockCaptureOrientation([DeviceOrientation? orientation]) async { try { - await CameraPlatform.instance.lockCaptureOrientation( - _cameraId, orientation ?? value.deviceOrientation); + await CameraPlatform.instance.lockCaptureOrientation(_cameraId, orientation ?? value.deviceOrientation); value = value.copyWith( - lockedCaptureOrientation: Optional.of( - orientation ?? value.deviceOrientation)); + lockedCaptureOrientation: Optional.of(orientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -800,8 +779,7 @@ class CameraController extends ValueNotifier { Future unlockCaptureOrientation() async { try { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith( - lockedCaptureOrientation: const Optional.absent()); + value = value.copyWith(lockedCaptureOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -812,10 +790,8 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the focus point to it's default /// value. Future setFocusPoint(Offset? point) async { - if (point != null && - (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError( - 'The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); } try { await CameraPlatform.instance.setFocusPoint( @@ -946,9 +922,7 @@ class Optional extends IterableBase { /// /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. Optional transform(S Function(T value) transformer) { - return _value == null - ? Optional.absent() - : Optional.of(transformer(_value as T)); + return _value == null ? Optional.absent() : Optional.of(transformer(_value as T)); } /// Transforms the Optional value. @@ -957,14 +931,11 @@ class Optional extends IterableBase { /// /// Returns [absent()] if the transformer returns `null`. Optional transformNullable(S? Function(T value) transformer) { - return _value == null - ? Optional.absent() - : Optional.fromNullable(transformer(_value as T)); + return _value == null ? Optional.absent() : Optional.fromNullable(transformer(_value as T)); } @override - Iterator get iterator => - isPresent ? [_value as T].iterator : Iterable.empty().iterator; + Iterator get iterator => isPresent ? [_value as T].iterator : Iterable.empty().iterator; /// Delegates to the underlying [value] hashCode. @override @@ -976,8 +947,6 @@ class Optional extends IterableBase { @override String toString() { - return _value == null - ? 'Optional { absent }' - : 'Optional { value: $_value }'; + return _value == null ? 'Optional { absent }' : 'Optional { value: $_value }'; } } diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 7cf3d3842e4..677b61b93e7 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -22,7 +22,7 @@ flutter: dependencies: camera_android: ^0.10.7 - camera_avfoundation: ^0.9.13 + camera_avfoundation: ^0.9.14 camera_platform_interface: ^2.5.2 camera_web: ^0.3.1 flutter: diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index ab8354f7ba0..16ce61820f9 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -15,20 +15,13 @@ import 'package:mockito/mockito.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; List get mockAvailableCameras => [ - const CameraDescription( - name: 'camBack', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), - const CameraDescription( - name: 'camFront', - lensDirection: CameraLensDirection.front, - sensorOrientation: 180), + const CameraDescription(name: 'camBack', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription(name: 'camFront', lensDirection: CameraLensDirection.front, sensorOrientation: 180), ]; int get mockInitializeCamera => 13; -CameraInitializedEvent get mockOnCameraInitializedEvent => - const CameraInitializedEvent( +CameraInitializedEvent get mockOnCameraInitializedEvent => const CameraInitializedEvent( 13, 75, 75, @@ -36,6 +29,7 @@ CameraInitializedEvent get mockOnCameraInitializedEvent => true, FocusMode.auto, true, + ImageExtension.jpeg, ); DeviceOrientationChangedEvent get mockOnDeviceOrientationChangedEvent => @@ -43,8 +37,7 @@ DeviceOrientationChangedEvent get mockOnDeviceOrientationChangedEvent => CameraClosingEvent get mockOnCameraClosingEvent => const CameraClosingEvent(13); -CameraErrorEvent get mockOnCameraErrorEvent => - const CameraErrorEvent(13, 'closing'); +CameraErrorEvent get mockOnCameraErrorEvent => const CameraErrorEvent(13, 'closing'); XFile mockTakePicture = XFile('foo/bar.png'); @@ -56,8 +49,7 @@ void main() { WidgetsFlutterBinding.ensureInitialized(); group('camera', () { - test('debugCheckIsDisposed should not throw assertion error when disposed', - () { + test('debugCheckIsDisposed should not throw assertion error when disposed', () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -69,8 +61,7 @@ void main() { expect(controller.debugCheckIsDisposed, returnsNormally); }); - test('debugCheckIsDisposed should throw assertion error when not disposed', - () { + test('debugCheckIsDisposed should throw assertion error when not disposed', () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -99,10 +90,7 @@ void main() { test('Can be initialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -113,10 +101,7 @@ void main() { test('can be disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -131,10 +116,7 @@ void main() { test('initialize() throws CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -155,13 +137,9 @@ void main() { ))); }); - test('initialize() throws $CameraException on $PlatformException ', - () async { + test('initialize() throws $CameraException on $PlatformException ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); mockPlatformException = true; @@ -179,25 +157,17 @@ void main() { test('initialize() sets imageFormat', () async { debugDefaultTargetPlatformOverride = TargetPlatform.android; final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max, imageFormatGroup: ImageFormatGroup.yuv420, ); await cameraController.initialize(); - verify(CameraPlatform.instance - .initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)) - .called(1); + verify(CameraPlatform.instance.initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)).called(1); }); test('prepareForVideoRecording() calls $CameraPlatform ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -208,10 +178,7 @@ void main() { test('takePicture() throws $CameraException when uninitialized ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( cameraController.takePicture(), @@ -231,18 +198,13 @@ void main() { ); }); - test('takePicture() throws $CameraException when takePicture is true', - () async { + test('takePicture() throws $CameraException when takePicture is true', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isTakingPicture: true); + cameraController.value = cameraController.value.copyWith(isTakingPicture: true); expect( cameraController.takePicture(), throwsA(isA().having( @@ -254,10 +216,7 @@ void main() { test('takePicture() returns $XFile', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); final XFile xFile = await cameraController.takePicture(); @@ -265,13 +224,9 @@ void main() { expect(xFile.path, mockTakePicture.path); }); - test('takePicture() throws $CameraException on $PlatformException', - () async { + test('takePicture() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -286,13 +241,9 @@ void main() { mockPlatformException = false; }); - test('startVideoRecording() throws $CameraException when uninitialized', - () async { + test('startVideoRecording() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -312,19 +263,14 @@ void main() { ), ); }); - test('startVideoRecording() throws $CameraException when recording videos', - () async { + test('startVideoRecording() throws $CameraException when recording videos', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isRecordingVideo: true); + cameraController.value = cameraController.value.copyWith(isRecordingVideo: true); expect( cameraController.startVideoRecording(), @@ -335,13 +281,9 @@ void main() { ))); }); - test('getMaxZoomLevel() throws $CameraException when uninitialized', - () async { + test('getMaxZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -364,10 +306,7 @@ void main() { test('getMaxZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -391,29 +330,20 @@ void main() { ); }); - test( - 'getMaxZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('getMaxZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) - .thenThrow(CameraException( + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMaxZoomLevel, - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -422,27 +352,19 @@ void main() { test('getMaxZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) - .thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMaxZoomLevel(); expect(maxZoomLevel, 42.0); }); - test('getMinZoomLevel() throws $CameraException when uninitialized', - () async { + test('getMinZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -465,10 +387,7 @@ void main() { test('getMinZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -492,29 +411,20 @@ void main() { ); }); - test( - 'getMinZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('getMinZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) - .thenThrow(CameraException( + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMinZoomLevel, - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -523,15 +433,11 @@ void main() { test('getMinZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) - .thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMinZoomLevel(); expect(maxZoomLevel, 42.0); @@ -539,10 +445,7 @@ void main() { test('setZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -565,10 +468,7 @@ void main() { test('setZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -592,29 +492,20 @@ void main() { ); }); - test( - 'setZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('setZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) - .thenThrow(CameraException( + when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( () => cameraController.setZoomLevel(42), - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -623,52 +514,35 @@ void main() { reset(CameraPlatform.instance); }); - test( - 'setZoomLevel() completes and calls method channel with correct value.', - () async { + test('setZoomLevel() completes and calls method channel with correct value.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setZoomLevel(42.0); - verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) - .called(1); + verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).called(1); }); test('setFlashMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setFlashMode(FlashMode.always); - verify(CameraPlatform.instance - .setFlashMode(cameraController.cameraId, FlashMode.always)) - .called(1); + verify(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).called(1); }); - test('setFlashMode() throws $CameraException on $PlatformException', - () async { + test('setFlashMode() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .setFlashMode(cameraController.cameraId, FlashMode.always)) - .thenThrow( + when(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -686,33 +560,22 @@ void main() { test('setExposureMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposureMode(ExposureMode.auto); - verify(CameraPlatform.instance - .setExposureMode(cameraController.cameraId, ExposureMode.auto)) - .called(1); + verify(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).called(1); }); - test('setExposureMode() throws $CameraException on $PlatformException', - () async { + test('setExposureMode() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .setExposureMode(cameraController.cameraId, ExposureMode.auto)) - .thenThrow( + when(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -730,32 +593,23 @@ void main() { test('setExposurePoint() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposurePoint(const Offset(0.5, 0.5)); - verify(CameraPlatform.instance.setExposurePoint( - cameraController.cameraId, const Point(0.5, 0.5))) + verify(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) .called(1); }); - test('setExposurePoint() throws $CameraException on $PlatformException', - () async { + test('setExposurePoint() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposurePoint( - cameraController.cameraId, const Point(0.5, 0.5))) + when(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -774,37 +628,25 @@ void main() { test('getMinExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getMinExposureOffset(); - verify(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).called(1); }); - test('getMinExposureOffset() throws $CameraException on $PlatformException', - () async { + test('getMinExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -822,37 +664,25 @@ void main() { test('getMaxExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(1.0)); await cameraController.getMaxExposureOffset(); - verify(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).called(1); }); - test('getMaxExposureOffset() throws $CameraException on $PlatformException', - () async { + test('getMaxExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -870,38 +700,25 @@ void main() { test('getExposureOffsetStepSize() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getExposureOffsetStepSize(); - verify(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).called(1); }); - test( - 'getExposureOffsetStepSize() throws $CameraException on $PlatformException', - () async { + test('getExposureOffsetStepSize() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -919,53 +736,28 @@ void main() { test('setExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenAnswer((_) async => 1.0); await cameraController.setExposureOffset(1.0); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).called(1); }); - test('setExposureOffset() throws $CameraException on $PlatformException', - () async { + test('setExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .thenThrow( + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -981,34 +773,17 @@ void main() { ))); }); - test( - 'setExposureOffset() throws $CameraException when offset is out of bounds', - () async { + test('setExposureOffset() throws $CameraException when offset is out of bounds', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 2.0)) - .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).thenAnswer((_) async => 0.0); expect( cameraController.setExposureOffset(3.0), @@ -1029,56 +804,27 @@ void main() { await cameraController.setExposureOffset(-1.0); await cameraController.setExposureOffset(2.0); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .called(1); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.0)) - .called(1); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 2.0)) - .called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).called(1); }); test('setExposureOffset() rounds offset to nearest step', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.2); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 1.2); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 0.4); - - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.2)) - .thenAnswer((_) async => -1.2); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.8)) - .thenAnswer((_) async => -0.8); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.4)) - .thenAnswer((_) async => -0.4); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.4)) - .thenAnswer((_) async => 0.4); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.8)) - .thenAnswer((_) async => 0.8); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.2)) - .thenAnswer((_) async => 1.2); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.2); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 1.2); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 0.4); + + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.2)).thenAnswer((_) async => -1.2); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).thenAnswer((_) async => -0.8); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).thenAnswer((_) async => -0.4); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).thenAnswer((_) async => 0.4); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).thenAnswer((_) async => 0.8); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.2)).thenAnswer((_) async => 1.2); await cameraController.setExposureOffset(1.2); await cameraController.setExposureOffset(-1.2); @@ -1097,97 +843,62 @@ void main() { await cameraController.setExposureOffset(-0.6); await cameraController.setExposureOffset(-0.7); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.8)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.8)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.4)) - .called(4); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.4)) - .called(4); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).called(4); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).called(4); }); test('pausePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value - .copyWith(deviceOrientation: DeviceOrientation.portraitUp); + cameraController.value = cameraController.value.copyWith(deviceOrientation: DeviceOrientation.portraitUp); await cameraController.pausePreview(); - verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)).called(1); expect(cameraController.value.isPreviewPaused, equals(true)); - expect(cameraController.value.previewPauseOrientation, - DeviceOrientation.portraitUp); + expect(cameraController.value.previewPauseOrientation, DeviceOrientation.portraitUp); }); - test('pausePreview() does not call $CameraPlatform when already paused', - () async { + test('pausePreview() does not call $CameraPlatform when already paused', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); await cameraController.pausePreview(); - verifyNever( - CameraPlatform.instance.pausePreview(cameraController.cameraId)); + verifyNever(CameraPlatform.instance.pausePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(true)); }); - test( - 'pausePreview() sets previewPauseOrientation according to locked orientation', - () async { + test('pausePreview() sets previewPauseOrientation according to locked orientation', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); cameraController.value = cameraController.value.copyWith( isPreviewPaused: false, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: - Optional.of(DeviceOrientation.landscapeRight)); + lockedCaptureOrientation: Optional.of(DeviceOrientation.landscapeRight)); await cameraController.pausePreview(); - expect(cameraController.value.deviceOrientation, - equals(DeviceOrientation.portraitUp)); - expect(cameraController.value.previewPauseOrientation, - equals(DeviceOrientation.landscapeRight)); + expect(cameraController.value.deviceOrientation, equals(DeviceOrientation.portraitUp)); + expect(cameraController.value.previewPauseOrientation, equals(DeviceOrientation.landscapeRight)); }); - test('pausePreview() throws $CameraException on $PlatformException', - () async { + test('pausePreview() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.pausePreview(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.pausePreview(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1205,54 +916,37 @@ void main() { test('resumePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); await cameraController.resumePreview(); - verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)).called(1); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() does not call $CameraPlatform when not paused', - () async { + test('resumePreview() does not call $CameraPlatform when not paused', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: false); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: false); await cameraController.resumePreview(); - verifyNever( - CameraPlatform.instance.resumePreview(cameraController.cameraId)); + verifyNever(CameraPlatform.instance.resumePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() throws $CameraException on $PlatformException', - () async { + test('resumePreview() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); - when(CameraPlatform.instance.resumePreview(cameraController.cameraId)) - .thenThrow( + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + when(CameraPlatform.instance.resumePreview(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1270,41 +964,28 @@ void main() { test('lockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.lockCaptureOrientation(); - expect(cameraController.value.lockedCaptureOrientation, - equals(DeviceOrientation.portraitUp)); - await cameraController - .lockCaptureOrientation(DeviceOrientation.landscapeRight); - expect(cameraController.value.lockedCaptureOrientation, - equals(DeviceOrientation.landscapeRight)); - - verify(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.portraitUp)) + expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.portraitUp)); + await cameraController.lockCaptureOrientation(DeviceOrientation.landscapeRight); + expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.landscapeRight)); + + verify(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) .called(1); - verify(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.landscapeRight)) + verify(CameraPlatform.instance + .lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.landscapeRight)) .called(1); }); - test( - 'lockCaptureOrientation() throws $CameraException on $PlatformException', - () async { + test('lockCaptureOrientation() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.portraitUp)) + when(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -1323,34 +1004,22 @@ void main() { test('unlockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.unlockCaptureOrientation(); expect(cameraController.value.lockedCaptureOrientation, equals(null)); - verify(CameraPlatform.instance - .unlockCaptureOrientation(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).called(1); }); - test( - 'unlockCaptureOrientation() throws $CameraException on $PlatformException', - () async { + test('unlockCaptureOrientation() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .unlockCaptureOrientation(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1368,9 +1037,7 @@ void main() { }); } -class MockCameraPlatform extends Mock - with MockPlatformInterfaceMixin - implements CameraPlatform { +class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements CameraPlatform { @override Future initializeCamera( int? cameraId, { @@ -1390,8 +1057,7 @@ class MockCameraPlatform extends Mock } @override - Future> availableCameras() => - Future>.value(mockAvailableCameras); + Future> availableCameras() => Future>.value(mockAvailableCameras); @override Future createCamera( @@ -1412,52 +1078,46 @@ class MockCameraPlatform extends Mock Stream.value(mockOnCameraClosingEvent); @override - Stream onCameraError(int cameraId) => - Stream.value(mockOnCameraErrorEvent); + Stream onCameraError(int cameraId) => Stream.value(mockOnCameraErrorEvent); @override Stream onDeviceOrientationChanged() => - Stream.value( - mockOnDeviceOrientationChangedEvent); + Stream.value(mockOnDeviceOrientationChangedEvent); @override - Future takePicture(int cameraId) => mockPlatformException - ? throw PlatformException(code: 'foo', message: 'bar') - : Future.value(mockTakePicture); + Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) => + mockPlatformException + ? throw PlatformException(code: 'foo', message: 'bar') + : Future.value(mockTakePicture); @override Future prepareForVideoRecording() async => super.noSuchMethod(Invocation.method(#prepareForVideoRecording, null)); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) => + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) => Future.value(mockVideoRecordingXFile); @override Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } @override - Future lockCaptureOrientation( - int? cameraId, DeviceOrientation? orientation) async => - super.noSuchMethod(Invocation.method( - #lockCaptureOrientation, [cameraId, orientation])); + Future lockCaptureOrientation(int? cameraId, DeviceOrientation? orientation) async => + super.noSuchMethod(Invocation.method(#lockCaptureOrientation, [cameraId, orientation])); @override Future unlockCaptureOrientation(int? cameraId) async => - super.noSuchMethod( - Invocation.method(#unlockCaptureOrientation, [cameraId])); + super.noSuchMethod(Invocation.method(#unlockCaptureOrientation, [cameraId])); @override Future pausePreview(int? cameraId) async => super.noSuchMethod(Invocation.method(#pausePreview, [cameraId])); @override - Future resumePreview(int? cameraId) async => super - .noSuchMethod(Invocation.method(#resumePreview, [cameraId])); + Future resumePreview(int? cameraId) async => + super.noSuchMethod(Invocation.method(#resumePreview, [cameraId])); @override Future getMaxZoomLevel(int? cameraId) async => super.noSuchMethod( @@ -1473,48 +1133,40 @@ class MockCameraPlatform extends Mock @override Future setZoomLevel(int? cameraId, double? zoom) async => - super.noSuchMethod( - Invocation.method(#setZoomLevel, [cameraId, zoom])); + super.noSuchMethod(Invocation.method(#setZoomLevel, [cameraId, zoom])); @override Future setFlashMode(int? cameraId, FlashMode? mode) async => - super.noSuchMethod( - Invocation.method(#setFlashMode, [cameraId, mode])); + super.noSuchMethod(Invocation.method(#setFlashMode, [cameraId, mode])); @override Future setExposureMode(int? cameraId, ExposureMode? mode) async => - super.noSuchMethod( - Invocation.method(#setExposureMode, [cameraId, mode])); + super.noSuchMethod(Invocation.method(#setExposureMode, [cameraId, mode])); @override Future setExposurePoint(int? cameraId, Point? point) async => - super.noSuchMethod( - Invocation.method(#setExposurePoint, [cameraId, point])); + super.noSuchMethod(Invocation.method(#setExposurePoint, [cameraId, point])); @override - Future getMinExposureOffset(int? cameraId) async => - super.noSuchMethod( + Future getMinExposureOffset(int? cameraId) async => super.noSuchMethod( Invocation.method(#getMinExposureOffset, [cameraId]), returnValue: Future.value(0.0), ) as Future; @override - Future getMaxExposureOffset(int? cameraId) async => - super.noSuchMethod( + Future getMaxExposureOffset(int? cameraId) async => super.noSuchMethod( Invocation.method(#getMaxExposureOffset, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future getExposureOffsetStepSize(int? cameraId) async => - super.noSuchMethod( + Future getExposureOffsetStepSize(int? cameraId) async => super.noSuchMethod( Invocation.method(#getExposureOffsetStepSize, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future setExposureOffset(int? cameraId, double? offset) async => - super.noSuchMethod( + Future setExposureOffset(int? cameraId, double? offset) async => super.noSuchMethod( Invocation.method(#setExposureOffset, [cameraId, offset]), returnValue: Future.value(1.0), ) as Future; diff --git a/packages/camera/camera_android/lib/src/android_camera.dart b/packages/camera/camera_android/lib/src/android_camera.dart index eca1003247c..8b8267d79e0 100644 --- a/packages/camera/camera_android/lib/src/android_camera.dart +++ b/packages/camera/camera_android/lib/src/android_camera.dart @@ -14,8 +14,7 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = - MethodChannel('plugins.flutter.io/camera_android'); +const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_android'); /// The Android implementation of [CameraPlatform] that uses method channels. class AndroidCamera extends CameraPlatform { @@ -29,8 +28,7 @@ class AndroidCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = - 'plugins.flutter.io/camera_android/fromPlatform'; + static const String deviceEventChannelName = 'plugins.flutter.io/camera_android/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -40,16 +38,14 @@ class AndroidCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = - _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -65,14 +61,13 @@ class AndroidCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -81,8 +76,7 @@ class AndroidCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -98,12 +92,9 @@ class AndroidCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -119,10 +110,8 @@ class AndroidCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = - MethodChannel('plugins.flutter.io/camera_android/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_android/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -199,8 +188,7 @@ class AndroidCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream - .whereType(); + return _deviceEventStreamController.stream.whereType(); } @override @@ -210,10 +198,7 @@ class AndroidCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -226,10 +211,10 @@ class AndroidCamera extends CameraPlatform { } @override - Future takePicture(int cameraId) async { + Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId}, + {'cameraId': cameraId, 'imageExtension': _serializeImageExtension(imageExtension)}, ); if (path == null) { @@ -243,14 +228,11 @@ class AndroidCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -294,21 +276,18 @@ class AndroidCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController( - {Function()? onListen}) { + StreamController _installStreamController({Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -328,12 +307,9 @@ class AndroidCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera_android/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_android/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -345,13 +321,11 @@ class AndroidCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -360,8 +334,7 @@ class AndroidCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -429,8 +402,7 @@ class AndroidCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -506,8 +478,7 @@ class AndroidCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -567,13 +538,23 @@ class AndroidCamera extends CameraPlatform { return 'max'; } + /// Returns the format of the image as a String. + String _serializeImageExtension(ImageExtension imageExtension) { + switch (imageExtension) { + case ImageExtension.jpeg: + return 'jpeg'; + case ImageExtension.heic: + return 'heic'; + } + } + /// Converts messages received from the native platform into device events. Future _handleDeviceMethodCall(MethodCall call) async { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -597,6 +578,7 @@ class AndroidCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, + deserializeImageExtension(arguments['imageExtension']! as String), )); break; case 'resolution_changed': @@ -617,9 +599,7 @@ class AndroidCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_android/test/android_camera_test.dart b/packages/camera/camera_android/test/android_camera_test.dart index 8c811403304..88df959c7a6 100644 --- a/packages/camera/camera_android/test/android_camera_test.dart +++ b/packages/camera/camera_android/test/android_camera_test.dart @@ -32,37 +32,31 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(const MethodCall( - 'orientation_changed', - {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AndroidCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AndroidCamera camera = AndroidCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -70,18 +64,13 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -103,16 +92,13 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -134,10 +120,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -161,10 +145,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -176,15 +157,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -205,6 +185,7 @@ void main() { true, FocusMode.auto, true, + ImageExtension.jpeg, )); await initializeFuture; @@ -224,13 +205,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( @@ -250,6 +230,7 @@ void main() { true, FocusMode.auto, true, + ImageExtension.jpeg, )); await initializeFuture; @@ -298,16 +279,15 @@ void main() { true, FocusMode.auto, true, + ImageExtension.jpeg, )); await initializeFuture; }); test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -318,9 +298,9 @@ void main() { true, FocusMode.auto, true, + ImageExtension.jpeg, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -331,24 +311,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -362,19 +335,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -387,20 +355,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -413,22 +375,17 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( + AndroidCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -472,25 +429,17 @@ void main() { true, FocusMode.auto, true, + ImageExtension.jpeg, ), ); await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -506,21 +455,17 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -534,19 +479,16 @@ void main() { camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -555,6 +497,7 @@ void main() { expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, + 'imageExtension': 'jpeg', }), ]); expect(file.path, '/test/path.jpg'); @@ -596,8 +539,7 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -620,9 +562,7 @@ void main() { ]); }); - test( - 'Should pass enableStream if callback is passed when starting recording a video', - () async { + test('Should pass enableStream if callback is passed when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -631,8 +571,7 @@ void main() { // Act await camera.startVideoCapturing( - VideoCaptureOptions(cameraId, - streamCallback: (CameraImageData imageData) {}), + VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {}), ); // Assert @@ -706,20 +645,17 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = CameraDescription( - name: 'Test2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 0); + const CameraDescription camera2Description = + CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -738,18 +674,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -766,12 +694,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -788,18 +712,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -811,8 +727,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -831,8 +746,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -895,12 +809,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -917,18 +827,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -941,13 +843,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final AndroidCamera camera = AndroidCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -1001,13 +900,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -1024,8 +921,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1036,15 +932,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1060,8 +953,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1077,8 +969,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1094,8 +985,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1110,9 +1000,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1133,9 +1022,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 5f43ac4434e..1856f110b9e 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -49,7 +49,7 @@ - (void)testCaptureToFile_mustReportErrorToResultIfSavePhotoDelegateCompletionsW // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult imageFormat:ImageFormatHEIC]; + [cam captureToFile:mockResult imageExtenion:ImageExtensionHEIC]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -89,7 +89,7 @@ - (void)testCaptureToFile_mustReportPathToResultIfSavePhotoDelegateCompletionsWi // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult imageFormat:ImageFormatHEIC]; + [cam captureToFile:mockResult imageExtenion:ImageExtensionHEIC]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index 2e7cd9c94cc..d1472325a4a 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -186,13 +186,13 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call }else if ([@"takePicture" isEqualToString:call.method]) { NSString *formatString = call.arguments[@"imageExtension"]; - ImageFormat imageFormat = ImageFormatJPEG; + imageExtension imageExtension = ImageExtensionJPEG; if ([formatString isEqualToString:@"heic"]) { - imageFormat = ImageFormatHEIC; + imageExtension = ImageExtensionHEIC; } - [_camera captureToFile:result imageFormat:imageFormat]; + [_camera captureToFile:result imageExtension:imageExtension]; } else if ([@"dispose" isEqualToString:call.method]) { [_registry unregisterTexture:cameraId]; diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index e26a8aa2f2d..30563276744 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -15,11 +15,11 @@ NS_ASSUME_NONNULL_BEGIN /** - * Represents image format. Mirrors ImageFormat in camera.dart. + * Represents image format. Mirrors ImageExtension in camera.dart. */ -typedef NS_ENUM(NSInteger, ImageFormat) { - ImageFormatJPEG, - ImageFormatHEIC, +typedef NS_ENUM(NSInteger, ImageExtension) { + ImageExtensionJPEG, + ImageExtensionHEIC, }; /** @@ -38,7 +38,7 @@ typedef NS_ENUM(NSInteger, ImageFormat) { @property(assign, nonatomic) FLTFlashMode flashMode; // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; -@property(readonly, nonatomic) ImageFormat imageFormat; +@property(readonly, nonatomic) ImageExtension imageExtension; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. @@ -56,7 +56,8 @@ typedef NS_ENUM(NSInteger, ImageFormat) { - (void)start; - (void)stop; - (void)setDeviceOrientation:(UIDeviceOrientation)orientation; -- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageFormat:(ImageFormat)imageFormat; +- (void)captureToFile:(FLTThreadSafeFlutterResult *)result + ImageExtension:(ImageExtension)imageExtension; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; /** diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 8a9056b42f5..1f973566d0a 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -244,14 +244,14 @@ - (void)updateOrientation:(UIDeviceOrientation)orientation } } -- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageFormat:(ImageFormat)imageFormat { +- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageExtension:(imageExtension)imageExtension { AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; NSString *extension; if (_resolutionPreset == FLTResolutionPresetMax) { [settings setHighResolutionPhotoEnabled:YES]; } - if (self.imageFormat == ImageFormatHEIC) { + if (self.imageExtension == ImageExtensionHEIC) { if (@available(iOS 11.0, *)) { if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{ AVVideoCodecKey : AVVideoCodecTypeHEVC }]; diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 900532d6c60..eea473a8888 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,8 +14,7 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = - MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -29,8 +28,7 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = - 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -40,16 +38,14 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = - _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -65,14 +61,13 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -81,8 +76,7 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -98,12 +92,9 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -119,10 +110,8 @@ class AVFoundationCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel( - 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -199,8 +188,7 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream - .whereType(); + return _deviceEventStreamController.stream.whereType(); } @override @@ -210,10 +198,7 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -226,14 +211,10 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, - {ImageFormat imageFormat = ImageFormat.jpeg}) async { + Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - { - 'cameraId': cameraId, - 'imageFormat': _serializeImageFormat(imageFormat) - }, + {'cameraId': cameraId, 'imageExtension': _serializeImageExtension(imageExtension)}, ); if (path == null) { @@ -247,14 +228,11 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -299,22 +277,18 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { - _frameStreamController = - _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController( - {Function()? onListen}) { + StreamController _createStreamController({Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -333,17 +307,14 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -355,13 +326,11 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -370,8 +339,7 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -439,8 +407,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -516,8 +483,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -578,11 +544,11 @@ class AVFoundationCamera extends CameraPlatform { } /// Returns the format of the image as a String. - String _serializeImageFormat(ImageFormat format) { - switch (format) { - case ImageFormat.jpeg: + String _serializeImageExtension(ImageExtension imageExtension) { + switch (imageExtension) { + case ImageExtension.jpeg: return 'jpeg'; - case ImageFormat.heic: + case ImageExtension.heic: return 'heic'; } } @@ -592,8 +558,8 @@ class AVFoundationCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -617,7 +583,7 @@ class AVFoundationCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, - deserializeImageFormat(arguments['imageFormat']! as String), + deserializeImageExtension(arguments['imageExtension']! as String), )); break; case 'resolution_changed': @@ -638,9 +604,7 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index f627a03ebc2..a0296cb28c0 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -17,7 +17,8 @@ flutter: dartPluginClass: AVFoundationCamera dependencies: - camera_platform_interface: ^2.5.2 + camera_platform_interface: + path: ../camera_platform_interface flutter: sdk: flutter stream_transform: ^2.0.0 diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 9d7912b9435..588c38b05bb 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -32,37 +32,31 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(const MethodCall( - 'orientation_changed', - {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AVFoundationCamera camera = AVFoundationCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -70,18 +64,13 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -103,16 +92,13 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -134,10 +120,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -161,10 +145,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -176,15 +157,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -205,7 +185,7 @@ void main() { true, FocusMode.auto, true, - ImageFormat.jpeg, + ImageExtension.jpeg, )); await initializeFuture; @@ -225,13 +205,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( @@ -251,7 +230,7 @@ void main() { true, FocusMode.auto, true, - ImageFormat.jpeg, + ImageExtension.jpeg, )); await initializeFuture; @@ -300,17 +279,15 @@ void main() { true, FocusMode.auto, true, - ImageFormat.jpeg, + ImageExtension.jpeg, )); await initializeFuture; }); test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -321,10 +298,9 @@ void main() { true, FocusMode.auto, true, - ImageFormat.jpeg, + ImageExtension.jpeg, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -335,24 +311,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -366,19 +335,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -391,20 +355,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -417,22 +375,17 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -476,29 +429,20 @@ void main() { true, FocusMode.auto, true, - ImageFormat.jpeg, + ImageExtension.jpeg, ), ); await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange // This deliberately uses 'dynamic' since that's what actual platform // channel results will be, so using typed mock data could mask type // handling bugs in the code under test. final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -514,21 +458,17 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -542,20 +482,16 @@ void main() { camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should take a picture and return an XFile instance with jpeg format', - () async { + test('Should take a picture and return an XFile instance with jpeg format', () async { // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -564,28 +500,25 @@ void main() { expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, - 'imageFormat': 'jpeg', + 'imageExtension': 'jpeg', }), ]); expect(file.path, '/test/path.jpg'); }); - test('Should take a picture and return an XFile instance with heic format', - () async { + test('Should take a picture and return an XFile instance with heic format', () async { // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.heic'}); + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.heic'}); // Act - final XFile file = - await camera.takePicture(cameraId, imageFormat: ImageFormat.heic); + final XFile file = await camera.takePicture(cameraId, imageExtension: ImageExtension.heic); // Assert expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, - 'imageFormat': 'heic', + 'imageExtension': 'heic', }), ]); expect(file.path, '/test/path.heic'); @@ -627,8 +560,7 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -651,9 +583,7 @@ void main() { ]); }); - test( - 'Should pass enableStream if callback is passed when starting recording a video', - () async { + test('Should pass enableStream if callback is passed when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -661,8 +591,7 @@ void main() { ); // Act - await camera.startVideoCapturing(VideoCaptureOptions(cameraId, - streamCallback: (CameraImageData imageData) {})); + await camera.startVideoCapturing(VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {})); // Assert expect(channel.log, [ @@ -735,20 +664,17 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = CameraDescription( - name: 'Test2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 0); + const CameraDescription camera2Description = + CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -767,18 +693,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -795,12 +713,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -817,18 +731,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -840,8 +746,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -860,8 +765,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -924,12 +828,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -946,18 +846,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -970,13 +862,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final AVFoundationCamera camera = AVFoundationCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -1030,13 +919,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -1053,8 +940,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1065,15 +951,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1089,8 +972,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1106,8 +988,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1123,8 +1004,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1139,9 +1019,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1162,9 +1041,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart index 1df34fcc18b..ab52bf8cdfe 100644 --- a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart +++ b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart @@ -34,10 +34,7 @@ abstract class CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || - other is CameraEvent && - runtimeType == other.runtimeType && - cameraId == other.cameraId; + identical(this, other) || other is CameraEvent && runtimeType == other.runtimeType && cameraId == other.cameraId; @override int get hashCode => cameraId.hashCode; @@ -58,7 +55,7 @@ class CameraInitializedEvent extends CameraEvent { this.exposurePointSupported, this.focusMode, this.focusPointSupported, - this.imageFormat, + this.imageExtension, ); /// Converts the supplied [Map] to an instance of the [CameraInitializedEvent] @@ -67,11 +64,10 @@ class CameraInitializedEvent extends CameraEvent { : previewWidth = json['previewWidth']! as double, previewHeight = json['previewHeight']! as double, exposureMode = deserializeExposureMode(json['exposureMode']! as String), - exposurePointSupported = - (json['exposurePointSupported'] as bool?) ?? false, + exposurePointSupported = (json['exposurePointSupported'] as bool?) ?? false, focusMode = deserializeFocusMode(json['focusMode']! as String), focusPointSupported = (json['focusPointSupported'] as bool?) ?? false, - imageFormat = deserializeImageFormat(json['imageFormat']! as String), + imageExtension = deserializeImageExtension(json['imageExtension']! as String), super(json['cameraId']! as int); /// The width of the preview in pixels. @@ -92,8 +88,8 @@ class CameraInitializedEvent extends CameraEvent { /// Whether setting focus points is supported. final bool focusPointSupported; - /// The default image format - final ImageFormat imageFormat; + /// The default image extension + final ImageExtension imageExtension; /// Converts the [CameraInitializedEvent] instance into a [Map] instance that /// can be serialized to JSON. @@ -105,7 +101,7 @@ class CameraInitializedEvent extends CameraEvent { 'exposurePointSupported': exposurePointSupported, 'focusMode': serializeFocusMode(focusMode), 'focusPointSupported': focusPointSupported, - 'imageFormat': serializeImageFormat(imageFormat), + 'imageExtension': serializeImageExtension(imageExtension), }; @override @@ -120,7 +116,7 @@ class CameraInitializedEvent extends CameraEvent { exposurePointSupported == other.exposurePointSupported && focusMode == other.focusMode && focusPointSupported == other.focusPointSupported && - imageFormat == other.imageFormat; + imageExtension == other.imageExtension; @override int get hashCode => Object.hash( @@ -131,7 +127,7 @@ class CameraInitializedEvent extends CameraEvent { exposurePointSupported, focusMode, focusPointSupported, - imageFormat, + imageExtension, ); } @@ -190,8 +186,7 @@ class CameraClosingEvent extends CameraEvent { /// Converts the supplied [Map] to an instance of the [CameraClosingEvent] /// class. - CameraClosingEvent.fromJson(Map json) - : super(json['cameraId']! as int); + CameraClosingEvent.fromJson(Map json) : super(json['cameraId']! as int); /// Converts the [CameraClosingEvent] instance into a [Map] instance that can /// be serialized to JSON. @@ -201,10 +196,7 @@ class CameraClosingEvent extends CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || - super == other && - other is CameraClosingEvent && - runtimeType == other.runtimeType; + identical(this, other) || super == other && other is CameraClosingEvent && runtimeType == other.runtimeType; @override // This is here even though it just calls super to make it less likely that @@ -262,9 +254,8 @@ class VideoRecordedEvent extends CameraEvent { /// class. VideoRecordedEvent.fromJson(Map json) : file = XFile(json['path']! as String), - maxVideoDuration = json['maxVideoDuration'] != null - ? Duration(milliseconds: json['maxVideoDuration'] as int) - : null, + maxVideoDuration = + json['maxVideoDuration'] != null ? Duration(milliseconds: json['maxVideoDuration'] as int) : null, super(json['cameraId']! as int); /// XFile of the recorded video. @@ -275,11 +266,8 @@ class VideoRecordedEvent extends CameraEvent { /// Converts the [VideoRecordedEvent] instance into a [Map] instance that can be /// serialized to JSON. - Map toJson() => { - 'cameraId': cameraId, - 'path': file.path, - 'maxVideoDuration': maxVideoDuration?.inMilliseconds - }; + Map toJson() => + {'cameraId': cameraId, 'path': file.path, 'maxVideoDuration': maxVideoDuration?.inMilliseconds}; @override bool operator ==(Object other) => diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index c9928c0f3c1..02e659ba7b0 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,10 +20,8 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler( - (MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -36,8 +34,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -47,8 +44,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = - StreamController.broadcast(); + final StreamController deviceEventStreamController = StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -57,14 +53,13 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -73,8 +68,7 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -90,12 +84,9 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -111,10 +102,8 @@ class MethodChannelCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -191,8 +180,7 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream - .whereType(); + return deviceEventStreamController.stream.whereType(); } @override @@ -202,10 +190,7 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -218,14 +203,10 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, - {ImageFormat imageFormat = ImageFormat.jpeg}) async { + Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - { - 'cameraId': cameraId, - 'imageFormat': _serializeImageFormat(imageFormat) - }, + {'cameraId': cameraId, 'imageFormat': _serializeImageExtension(imageExtension)}, ); if (path == null) { @@ -239,14 +220,11 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -290,21 +268,18 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController( - {Function()? onListen}) { + StreamController _installStreamController({Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -324,10 +299,8 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -335,8 +308,7 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -348,13 +320,11 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -363,8 +333,7 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -432,8 +401,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -509,8 +477,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -556,12 +523,12 @@ class MethodChannelCamera extends CameraPlatform { } } - /// Returns the image format as a String. - String _serializeImageFormat(ImageFormat format) { - switch (format) { - case ImageFormat.jpeg: + /// Returns the image extension as a String. + String _serializeImageExtension(ImageExtension imageExtension) { + switch (imageExtension) { + case ImageExtension.jpeg: return 'jpeg'; - case ImageFormat.heic: + case ImageExtension.heic: return 'heic'; } } @@ -574,8 +541,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -599,7 +566,7 @@ class MethodChannelCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, - deserializeImageFormat(arguments['imageFormat']! as String), + deserializeImageExtension(arguments['imageExtension']! as String), )); break; case 'resolution_changed': @@ -620,9 +587,7 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index b43629d4e0c..be24eb41eec 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -99,13 +99,11 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError( - 'onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation( - int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -115,7 +113,7 @@ abstract class CameraPlatform extends PlatformInterface { } /// Captures an image and returns the file where it was saved. - Future takePicture(int cameraId) { + Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) { throw UnimplementedError('takePicture() is not implemented.'); } @@ -142,8 +140,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -171,8 +168,7 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -271,8 +267,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError( - 'setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart b/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart new file mode 100644 index 00000000000..80ff38241cc --- /dev/null +++ b/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart @@ -0,0 +1,35 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/// The format in which images should be returned from the camera. +/// Will works only on iOS and only iOS 11+. +enum ImageExtension { + /// The default extension for the current platform. + jpeg, + + /// The efficient extension for iOS. + heic, +} + +/// Returns the image extension as a String. +String serializeImageExtension(ImageExtension imageExtension) { + switch (imageExtension) { + case ImageExtension.jpeg: + return 'jpeg'; + case ImageExtension.heic: + return 'heic'; + } +} + +/// Returns the image extension as a String. +ImageExtension deserializeImageExtension(String str) { + switch (str) { + case 'jpeg': + return ImageExtension.jpeg; + case 'heic': + return ImageExtension.heic; + default: + throw ArgumentError('"$str" is not a valid image extension.'); + } +} diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_format.dart b/packages/camera/camera_platform_interface/lib/src/types/image_format.dart deleted file mode 100644 index 8ac17cbab86..00000000000 --- a/packages/camera/camera_platform_interface/lib/src/types/image_format.dart +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/// The format in which images should be returned from the camera. -/// Will works only on iOS and only iOS 11+. -enum ImageFormat { - /// The default format for the device. - jpeg, - - /// The efficient format for iOS devices. - heic, -} - -/// Returns the image format as a String. -String serializeImageFormat(ImageFormat imageFormat) { - switch (imageFormat) { - case ImageFormat.jpeg: - return 'jpeg'; - case ImageFormat.heic: - return 'heic'; - } -} - -/// Returns the image format as a String. -ImageFormat deserializeImageFormat(String str) { - switch (str) { - case 'jpeg': - return ImageFormat.jpeg; - case 'heic': - return ImageFormat.heic; - default: - throw ArgumentError('"$str" is not a valid image format.'); - } -} diff --git a/packages/camera/camera_platform_interface/lib/src/types/types.dart b/packages/camera/camera_platform_interface/lib/src/types/types.dart index 26bda10e97f..d52e0a83db1 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/types.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/types.dart @@ -8,7 +8,7 @@ export 'camera_image_data.dart'; export 'exposure_mode.dart'; export 'flash_mode.dart'; export 'focus_mode.dart'; -export 'image_format.dart'; +export 'image_extension.dart'; export 'image_format_group.dart'; export 'resolution_preset.dart'; export 'video_capture_options.dart'; diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 0126b89939f..779f2580dca 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, - ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -20,12 +20,11 @@ void main() { expect(event.focusMode, FocusMode.auto); expect(event.exposurePointSupported, true); expect(event.focusPointSupported, true); - expect(event.imageFormat, ImageFormat.jpeg); + expect(event.imageExtension, ImageExtension.jpeg); }); test('fromJson should initialize all properties', () { - final CameraInitializedEvent event = - CameraInitializedEvent.fromJson(const { + final CameraInitializedEvent event = CameraInitializedEvent.fromJson(const { 'cameraId': 1, 'previewWidth': 1024.0, 'previewHeight': 640.0, @@ -46,8 +45,8 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, - ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.heic); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.heic); final Map jsonMap = event.toJson(); @@ -63,118 +62,89 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent(2, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent(1, 2048, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent(1, 1024, - 980, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.locked, - true, - FocusMode.auto, - true, - ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true, ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); - test('equals should return false if exposurePointSupported is different', - () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - false, - FocusMode.auto, - true, - ImageFormat.jpeg); + test('equals should return false if exposurePointSupported is different', () { + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true, ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.locked, - true, - ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true, ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - false, - ImageFormat.jpeg); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false, ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); - test('equals should return true if imageFormat is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); - const CameraInitializedEvent secondEvent = CameraInitializedEvent(1, 1024, - 640, ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.heic); + test('equals should return true if imageExtension is different', () { + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.heic); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, - ExposureMode.auto, true, FocusMode.auto, true, ImageFormat.jpeg); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.previewWidth, @@ -183,7 +153,7 @@ void main() { event.exposurePointSupported, event.focusMode, event.focusPointSupported, - event.imageFormat, + event.imageExtension, ); expect(event.hashCode, expectedHashCode); @@ -192,8 +162,7 @@ void main() { group('CameraResolutionChangesEvent tests', () { test('Constructor should initialize all properties', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); expect(event.cameraId, 1); expect(event.captureWidth, 1024); @@ -201,8 +170,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraResolutionChangedEvent event = - CameraResolutionChangedEvent.fromJson(const { + final CameraResolutionChangedEvent event = CameraResolutionChangedEvent.fromJson(const { 'cameraId': 1, 'captureWidth': 1024.0, 'captureHeight': 640.0, @@ -214,8 +182,7 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); final Map jsonMap = event.toJson(); @@ -226,44 +193,35 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 640); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(2, 1024, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(2, 1024, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureWidth is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 2048, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 2048, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureHeight is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 1024, 980); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 980); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.captureWidth, @@ -282,8 +240,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraClosingEvent event = - CameraClosingEvent.fromJson(const { + final CameraClosingEvent event = CameraClosingEvent.fromJson(const { 'cameraId': 1, }); @@ -330,8 +287,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraErrorEvent event = CameraErrorEvent.fromJson( - const {'cameraId': 1, 'description': 'Error'}); + final CameraErrorEvent event = + CameraErrorEvent.fromJson(const {'cameraId': 1, 'description': 'Error'}); expect(event.cameraId, 1); expect(event.description, 'Error'); @@ -370,8 +327,7 @@ void main() { test('hashCode should match hashCode of all properties', () { const CameraErrorEvent event = CameraErrorEvent(1, 'Error'); - final int expectedHashCode = - Object.hash(event.cameraId.hashCode, event.description); + final int expectedHashCode = Object.hash(event.cameraId.hashCode, event.description); expect(event.hashCode, expectedHashCode); }); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index adbf220e3da..856e566595d 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -22,22 +22,18 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -45,28 +41,20 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test( - 'Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -81,26 +69,20 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test( - 'Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -115,10 +97,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -142,10 +122,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having((CameraException e) => e.code, 'code', - 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,15 +134,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -186,7 +162,7 @@ void main() { true, FocusMode.auto, true, - ImageFormat.heic, + ImageExtension.heic, )); await initializeFuture; @@ -206,13 +182,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( @@ -232,7 +207,7 @@ void main() { true, FocusMode.auto, true, - ImageFormat.heic, + ImageExtension.heic, )); await initializeFuture; @@ -281,17 +256,15 @@ void main() { true, FocusMode.auto, true, - ImageFormat.heic, + ImageExtension.heic, )); await initializeFuture; }); test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -302,10 +275,9 @@ void main() { true, FocusMode.auto, true, - ImageFormat.heic, + ImageExtension.heic, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -316,24 +288,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -347,19 +312,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -372,20 +332,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -398,20 +352,15 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); // Assert expect(await streamQueue.next, event); @@ -454,26 +403,17 @@ void main() { true, FocusMode.auto, true, - ImageFormat.heic, + ImageExtension.heic, ), ); await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -489,51 +429,40 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'availableCameras': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'availableCameras': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); // Act expect( camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test( - 'Should take a picture and return an XFile instance with jpg extension', - () async { + test('Should take a picture and return an XFile instance with jpg extension', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: {'takePicture': '/test/path.jpg'}); + channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -542,29 +471,25 @@ void main() { expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, - 'imageFormat': 'jpeg', + 'imageExtension': 'jpeg', }), ]); expect(file.path, '/test/path.jpg'); }); - test( - 'Should take a picture and return an XFile instance with heic extension', - () async { + test('Should take a picture and return an XFile instance with heic extension', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: {'takePicture': '/test/path.heic'}); + channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.heic'}); // Act - final XFile file = - await camera.takePicture(cameraId, imageFormat: ImageFormat.heic); + final XFile file = await camera.takePicture(cameraId, imageExtension: ImageExtension.heic); // Assert expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, - 'imageFormat': 'heic', + 'imageExtension': 'heic', }), ]); expect(file.path, '/test/path.heic'); @@ -614,23 +539,18 @@ void main() { ); // Act - const CameraDescription cameraDescription = CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0); + const CameraDescription cameraDescription = + CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0); await camera.setDescriptionWhileRecording(cameraDescription); // Assert expect(channel.log, [ isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': cameraDescription.name - }), + arguments: {'cameraName': cameraDescription.name}), ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -723,22 +643,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'off' - }), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -755,14 +663,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -779,18 +681,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -802,8 +696,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -822,8 +715,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -842,16 +734,14 @@ void main() { ); // Act - final double stepSize = - await camera.getExposureOffsetStepSize(cameraId); + final double stepSize = await camera.getExposureOffsetStepSize(cameraId); // Assert expect(stepSize, 0.25); expect(channel.log, [ - isMethodCall('getExposureOffsetStepSize', - arguments: { - 'cameraId': cameraId, - }), + isMethodCall('getExposureOffsetStepSize', arguments: { + 'cameraId': cameraId, + }), ]); }); @@ -863,8 +753,7 @@ void main() { ); // Act - final double actualOffset = - await camera.setExposureOffset(cameraId, 0.5); + final double actualOffset = await camera.setExposureOffset(cameraId, 0.5); // Assert expect(actualOffset, 0.6); @@ -889,14 +778,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -913,18 +796,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -937,13 +812,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final MethodChannelCamera camera = MethodChannelCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -997,13 +869,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -1020,8 +890,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1032,15 +901,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1056,8 +922,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1073,8 +938,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1090,8 +954,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1106,9 +969,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1129,9 +991,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart b/packages/camera/camera_platform_interface/test/types/image_extension_test.dart new file mode 100644 index 00000000000..8c8f7241edf --- /dev/null +++ b/packages/camera/camera_platform_interface/test/types/image_extension_test.dart @@ -0,0 +1,22 @@ +import 'package:camera_platform_interface/src/types/types.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('$ImageExtension tests', () { + test('ImageFormat extension returns correct values', () { + expect(ImageExtension.jpeg.name, 'jpeg'); + expect(ImageExtension.heic.name, 'heic'); + }); + + test('ImageExtensiont serialization', () { + expect(serializeImageExtension(ImageExtension.jpeg), 'jpeg'); + expect(serializeImageExtension(ImageExtension.heic), 'heic'); + }); + + test('ImageExtension deserialization', () { + expect(deserializeImageExtension('jpeg'), ImageExtension.jpeg); + expect(deserializeImageExtension('heic'), ImageExtension.heic); + expect(() => deserializeImageExtension('invalid'), throwsArgumentError); + }); + }); +} diff --git a/packages/camera/camera_platform_interface/test/types/image_format_test.dart b/packages/camera/camera_platform_interface/test/types/image_format_test.dart deleted file mode 100644 index e71940ee789..00000000000 --- a/packages/camera/camera_platform_interface/test/types/image_format_test.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:camera_platform_interface/src/types/types.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - group('$ImageFormat tests', () { - test('ImageFormat extension returns correct values', () { - expect(ImageFormat.jpeg.name, 'jpeg'); - expect(ImageFormat.heic.name, 'heic'); - }); - - test('ImageFormat serialization', () { - expect(serializeImageFormat(ImageFormat.jpeg), 'jpeg'); - expect(serializeImageFormat(ImageFormat.heic), 'heic'); - }); - - test('ImageFormat deserialization', () { - expect(deserializeImageFormat('jpeg'), ImageFormat.jpeg); - expect(deserializeImageFormat('heic'), ImageFormat.heic); - expect(() => deserializeImageFormat('invalid'), throwsArgumentError); - }); - }); -} From c67bf619da3ed022468ea0da0e53a9d683c9400b Mon Sep 17 00:00:00 2001 From: Mairramer <50643541+Mairramer@users.noreply.github.com> Date: Sun, 30 Jul 2023 13:29:05 -0300 Subject: [PATCH 08/71] Update FLTCam_Test.h --- packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h index 272fafaad62..467c7c4844a 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h @@ -31,7 +31,7 @@ @property(assign, nonatomic) BOOL isStreamingImages; /// The output format image capturing. -@property(assign, nonatomic) ImageFormat imageFormat; +@property(assign, nonatomic) ImageExtension imageExtension; /// A dictionary to retain all in-progress FLTSavePhotoDelegates. The key of the dictionary is the /// AVCapturePhotoSettings's uniqueID for each photo capture operation, and the value is the From 5f9a5fc77cd5ecf1bce64d90ecfd75fef250a9d2 Mon Sep 17 00:00:00 2001 From: Mairramer <50643541+Mairramer@users.noreply.github.com> Date: Sun, 30 Jul 2023 13:37:16 -0300 Subject: [PATCH 09/71] Update FLTCam.m --- packages/camera/camera_avfoundation/ios/Classes/FLTCam.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 1f973566d0a..aaef62abbbf 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -244,7 +244,7 @@ - (void)updateOrientation:(UIDeviceOrientation)orientation } } -- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageExtension:(imageExtension)imageExtension { +- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageExtension:(ImageExtension)imageExtension { AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; NSString *extension; if (_resolutionPreset == FLTResolutionPresetMax) { From 88bb20dd3a511245b72d1767374258ff28f14d67 Mon Sep 17 00:00:00 2001 From: Mairramer <50643541+Mairramer@users.noreply.github.com> Date: Sun, 30 Jul 2023 13:52:02 -0300 Subject: [PATCH 10/71] Update CameraPlugin.m --- packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index d1472325a4a..de5eceb7529 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -186,7 +186,7 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call }else if ([@"takePicture" isEqualToString:call.method]) { NSString *formatString = call.arguments[@"imageExtension"]; - imageExtension imageExtension = ImageExtensionJPEG; + ImageExtension imageExtension = ImageExtensionJPEG; if ([formatString isEqualToString:@"heic"]) { imageExtension = ImageExtensionHEIC; } From 1e77287d7260d26411802b48df62b24a5fe3f605 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 30 Jul 2023 14:16:15 -0300 Subject: [PATCH 11/71] new adjusts --- .../camera/lib/src/camera_controller.dart | 131 ++-- .../camera/test/camera_preview_test.dart | 3 + packages/camera/camera/test/camera_test.dart | 733 +++++++++++++----- .../lib/src/android_camera.dart | 101 ++- .../test/android_camera_test.dart | 348 ++++++--- .../lib/src/avfoundation_camera.dart | 104 ++- .../camera/camera_avfoundation/pubspec.yaml | 3 +- .../test/avfoundation_camera_test.dart | 362 ++++++--- .../lib/src/events/camera_event.dart | 31 +- .../method_channel/method_channel_camera.dart | 101 ++- .../platform_interface/camera_platform.dart | 18 +- .../test/events/camera_event_test.dart | 262 +++++-- .../method_channel_camera_test.dart | 397 +++++++--- 13 files changed, 1814 insertions(+), 780 deletions(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index b7d7403ea10..c67c3f8fb91 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -183,16 +183,21 @@ class CameraValue { flashMode: flashMode ?? this.flashMode, exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, - exposurePointSupported: exposurePointSupported ?? this.exposurePointSupported, + exposurePointSupported: + exposurePointSupported ?? this.exposurePointSupported, focusPointSupported: focusPointSupported ?? this.focusPointSupported, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: - lockedCaptureOrientation == null ? this.lockedCaptureOrientation : lockedCaptureOrientation.orNull, - recordingOrientation: recordingOrientation == null ? this.recordingOrientation : recordingOrientation.orNull, + lockedCaptureOrientation: lockedCaptureOrientation == null + ? this.lockedCaptureOrientation + : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null + ? this.recordingOrientation + : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, description: description ?? this.description, - previewPauseOrientation: - previewPauseOrientation == null ? this.previewPauseOrientation : previewPauseOrientation.orNull, + previewPauseOrientation: previewPauseOrientation == null + ? this.previewPauseOrientation + : previewPauseOrientation.orNull, ); } @@ -266,7 +271,8 @@ class CameraController extends ValueNotifier { bool _isDisposed = false; StreamSubscription? _imageStreamSubscription; FutureOr? _initCalled; - StreamSubscription? _deviceOrientationSubscription; + StreamSubscription? + _deviceOrientationSubscription; /// Checks whether [CameraController.dispose] has completed successfully. /// @@ -294,10 +300,12 @@ class CameraController extends ValueNotifier { ); } try { - final Completer initializeCompleter = Completer(); + final Completer initializeCompleter = + Completer(); - _deviceOrientationSubscription = - CameraPlatform.instance.onDeviceOrientationChanged().listen((DeviceOrientationChangedEvent event) { + _deviceOrientationSubscription = CameraPlatform.instance + .onDeviceOrientationChanged() + .listen((DeviceOrientationChangedEvent event) { value = value.copyWith( deviceOrientation: event.orientation, ); @@ -309,7 +317,10 @@ class CameraController extends ValueNotifier { enableAudio: enableAudio, ); - _unawaited(CameraPlatform.instance.onCameraInitialized(_cameraId).first.then((CameraInitializedEvent event) { + _unawaited(CameraPlatform.instance + .onCameraInitialized(_cameraId) + .first + .then((CameraInitializedEvent event) { initializeCompleter.complete(event); })); @@ -321,16 +332,19 @@ class CameraController extends ValueNotifier { value = value.copyWith( isInitialized: true, description: description, - previewSize: await initializeCompleter.future.then((CameraInitializedEvent event) => Size( - event.previewWidth, - event.previewHeight, - )), - exposureMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposureMode), - focusMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusMode), - exposurePointSupported: - await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposurePointSupported), - focusPointSupported: - await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusPointSupported), + previewSize: await initializeCompleter.future + .then((CameraInitializedEvent event) => Size( + event.previewWidth, + event.previewHeight, + )), + exposureMode: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.exposureMode), + focusMode: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.focusMode), + exposurePointSupported: await initializeCompleter.future.then( + (CameraInitializedEvent event) => event.exposurePointSupported), + focusPointSupported: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.focusPointSupported), ); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -363,8 +377,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: - Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); + previewPauseOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -377,8 +391,9 @@ class CameraController extends ValueNotifier { } try { await CameraPlatform.instance.resumePreview(_cameraId); - value = - value.copyWith(isPreviewPaused: false, previewPauseOrientation: const Optional.absent()); + value = value.copyWith( + isPreviewPaused: false, + previewPauseOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -409,7 +424,8 @@ class CameraController extends ValueNotifier { } try { value = value.copyWith(isTakingPicture: true); - final XFile file = await CameraPlatform.instance.takePicture(_cameraId, imageExtension: imageExtension); + final XFile file = await CameraPlatform.instance + .takePicture(_cameraId, imageExtension: imageExtension); value = value.copyWith(isTakingPicture: false); return file; } on PlatformException catch (e) { @@ -436,7 +452,8 @@ class CameraController extends ValueNotifier { /// // TODO(bmparr): Add settings for resolution and fps. Future startImageStream(onLatestImageAvailable onAvailable) async { - assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('startImageStream'); if (value.isRecordingVideo) { throw CameraException( @@ -452,8 +469,9 @@ class CameraController extends ValueNotifier { } try { - _imageStreamSubscription = - CameraPlatform.instance.onStreamedFrameAvailable(_cameraId).listen((CameraImageData imageData) { + _imageStreamSubscription = CameraPlatform.instance + .onStreamedFrameAvailable(_cameraId) + .listen((CameraImageData imageData) { onAvailable(CameraImage.fromPlatformInterface(imageData)); }); value = value.copyWith(isStreamingImages: true); @@ -470,7 +488,8 @@ class CameraController extends ValueNotifier { /// The `stopImageStream` method is only available on Android and iOS (other /// platforms won't be supported in current setup). Future stopImageStream() async { - assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('stopImageStream'); if (!value.isStreamingImages) { throw CameraException( @@ -495,7 +514,8 @@ class CameraController extends ValueNotifier { /// /// The video is returned as a [XFile] after calling [stopVideoRecording]. /// Throws a [CameraException] if the capture fails. - Future startVideoRecording({onLatestImageAvailable? onAvailable}) async { + Future startVideoRecording( + {onLatestImageAvailable? onAvailable}) async { _throwIfNotInitialized('startVideoRecording'); if (value.isRecordingVideo) { throw CameraException( @@ -512,12 +532,13 @@ class CameraController extends ValueNotifier { } try { - await CameraPlatform.instance.startVideoCapturing(VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); + await CameraPlatform.instance.startVideoCapturing( + VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, - recordingOrientation: - Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation), + recordingOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation), isStreamingImages: onAvailable != null); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -541,7 +562,8 @@ class CameraController extends ValueNotifier { } try { - final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); + final XFile file = + await CameraPlatform.instance.stopVideoRecording(_cameraId); value = value.copyWith( isRecordingVideo: false, recordingOrientation: const Optional.absent(), @@ -659,8 +681,10 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the exposure point to it's default /// value. Future setExposurePoint(Offset? point) async { - if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && + (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError( + 'The values of point should be anywhere between (0,0) and (1,1).'); } try { @@ -724,7 +748,8 @@ class CameraController extends ValueNotifier { Future setExposureOffset(double offset) async { _throwIfNotInitialized('setExposureOffset'); // Check if offset is in range - final List range = await Future.wait(>[getMinExposureOffset(), getMaxExposureOffset()]); + final List range = await Future.wait( + >[getMinExposureOffset(), getMaxExposureOffset()]); if (offset < range[0] || offset > range[1]) { throw CameraException( 'exposureOffsetOutOfBounds', @@ -757,9 +782,11 @@ class CameraController extends ValueNotifier { /// If [orientation] is omitted, the current device orientation is used. Future lockCaptureOrientation([DeviceOrientation? orientation]) async { try { - await CameraPlatform.instance.lockCaptureOrientation(_cameraId, orientation ?? value.deviceOrientation); + await CameraPlatform.instance.lockCaptureOrientation( + _cameraId, orientation ?? value.deviceOrientation); value = value.copyWith( - lockedCaptureOrientation: Optional.of(orientation ?? value.deviceOrientation)); + lockedCaptureOrientation: Optional.of( + orientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -779,7 +806,8 @@ class CameraController extends ValueNotifier { Future unlockCaptureOrientation() async { try { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith(lockedCaptureOrientation: const Optional.absent()); + value = value.copyWith( + lockedCaptureOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -790,8 +818,10 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the focus point to it's default /// value. Future setFocusPoint(Offset? point) async { - if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && + (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError( + 'The values of point should be anywhere between (0,0) and (1,1).'); } try { await CameraPlatform.instance.setFocusPoint( @@ -922,7 +952,9 @@ class Optional extends IterableBase { /// /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. Optional transform(S Function(T value) transformer) { - return _value == null ? Optional.absent() : Optional.of(transformer(_value as T)); + return _value == null + ? Optional.absent() + : Optional.of(transformer(_value as T)); } /// Transforms the Optional value. @@ -931,11 +963,14 @@ class Optional extends IterableBase { /// /// Returns [absent()] if the transformer returns `null`. Optional transformNullable(S? Function(T value) transformer) { - return _value == null ? Optional.absent() : Optional.fromNullable(transformer(_value as T)); + return _value == null + ? Optional.absent() + : Optional.fromNullable(transformer(_value as T)); } @override - Iterator get iterator => isPresent ? [_value as T].iterator : Iterable.empty().iterator; + Iterator get iterator => + isPresent ? [_value as T].iterator : Iterable.empty().iterator; /// Delegates to the underlying [value] hashCode. @override @@ -947,6 +982,8 @@ class Optional extends IterableBase { @override String toString() { - return _value == null ? 'Optional { absent }' : 'Optional { value: $_value }'; + return _value == null + ? 'Optional { absent }' + : 'Optional { value: $_value }'; } } diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index c73e1816445..fe27d3e5e46 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -122,6 +122,9 @@ class FakeController extends ValueNotifier @override CameraDescription get description => value.description; + + @override + ImageExtension get imageExtension => ImageExtension.png; } void main() { diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index 16ce61820f9..64cfac63ac3 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -15,13 +15,20 @@ import 'package:mockito/mockito.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; List get mockAvailableCameras => [ - const CameraDescription(name: 'camBack', lensDirection: CameraLensDirection.back, sensorOrientation: 90), - const CameraDescription(name: 'camFront', lensDirection: CameraLensDirection.front, sensorOrientation: 180), + const CameraDescription( + name: 'camBack', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), + const CameraDescription( + name: 'camFront', + lensDirection: CameraLensDirection.front, + sensorOrientation: 180), ]; int get mockInitializeCamera => 13; -CameraInitializedEvent get mockOnCameraInitializedEvent => const CameraInitializedEvent( +CameraInitializedEvent get mockOnCameraInitializedEvent => + const CameraInitializedEvent( 13, 75, 75, @@ -37,7 +44,8 @@ DeviceOrientationChangedEvent get mockOnDeviceOrientationChangedEvent => CameraClosingEvent get mockOnCameraClosingEvent => const CameraClosingEvent(13); -CameraErrorEvent get mockOnCameraErrorEvent => const CameraErrorEvent(13, 'closing'); +CameraErrorEvent get mockOnCameraErrorEvent => + const CameraErrorEvent(13, 'closing'); XFile mockTakePicture = XFile('foo/bar.png'); @@ -49,7 +57,8 @@ void main() { WidgetsFlutterBinding.ensureInitialized(); group('camera', () { - test('debugCheckIsDisposed should not throw assertion error when disposed', () { + test('debugCheckIsDisposed should not throw assertion error when disposed', + () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -61,7 +70,8 @@ void main() { expect(controller.debugCheckIsDisposed, returnsNormally); }); - test('debugCheckIsDisposed should throw assertion error when not disposed', () { + test('debugCheckIsDisposed should throw assertion error when not disposed', + () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -90,7 +100,10 @@ void main() { test('Can be initialized', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -101,7 +114,10 @@ void main() { test('can be disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -116,7 +132,10 @@ void main() { test('initialize() throws CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -137,9 +156,13 @@ void main() { ))); }); - test('initialize() throws $CameraException on $PlatformException ', () async { + test('initialize() throws $CameraException on $PlatformException ', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); mockPlatformException = true; @@ -157,17 +180,25 @@ void main() { test('initialize() sets imageFormat', () async { debugDefaultTargetPlatformOverride = TargetPlatform.android; final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max, imageFormatGroup: ImageFormatGroup.yuv420, ); await cameraController.initialize(); - verify(CameraPlatform.instance.initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)).called(1); + verify(CameraPlatform.instance + .initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)) + .called(1); }); test('prepareForVideoRecording() calls $CameraPlatform ', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -178,7 +209,10 @@ void main() { test('takePicture() throws $CameraException when uninitialized ', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( cameraController.takePicture(), @@ -198,13 +232,18 @@ void main() { ); }); - test('takePicture() throws $CameraException when takePicture is true', () async { + test('takePicture() throws $CameraException when takePicture is true', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isTakingPicture: true); + cameraController.value = + cameraController.value.copyWith(isTakingPicture: true); expect( cameraController.takePicture(), throwsA(isA().having( @@ -216,7 +255,10 @@ void main() { test('takePicture() returns $XFile', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); final XFile xFile = await cameraController.takePicture(); @@ -224,9 +266,13 @@ void main() { expect(xFile.path, mockTakePicture.path); }); - test('takePicture() throws $CameraException on $PlatformException', () async { + test('takePicture() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -241,9 +287,13 @@ void main() { mockPlatformException = false; }); - test('startVideoRecording() throws $CameraException when uninitialized', () async { + test('startVideoRecording() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -263,14 +313,19 @@ void main() { ), ); }); - test('startVideoRecording() throws $CameraException when recording videos', () async { + test('startVideoRecording() throws $CameraException when recording videos', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isRecordingVideo: true); + cameraController.value = + cameraController.value.copyWith(isRecordingVideo: true); expect( cameraController.startVideoRecording(), @@ -281,9 +336,13 @@ void main() { ))); }); - test('getMaxZoomLevel() throws $CameraException when uninitialized', () async { + test('getMaxZoomLevel() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -306,7 +365,10 @@ void main() { test('getMaxZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -330,20 +392,29 @@ void main() { ); }); - test('getMaxZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'getMaxZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenThrow(CameraException( + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMaxZoomLevel, - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -352,19 +423,27 @@ void main() { test('getMaxZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) + .thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMaxZoomLevel(); expect(maxZoomLevel, 42.0); }); - test('getMinZoomLevel() throws $CameraException when uninitialized', () async { + test('getMinZoomLevel() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -387,7 +466,10 @@ void main() { test('getMinZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -411,20 +493,29 @@ void main() { ); }); - test('getMinZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'getMinZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenThrow(CameraException( + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMinZoomLevel, - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -433,11 +524,15 @@ void main() { test('getMinZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) + .thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMinZoomLevel(); expect(maxZoomLevel, 42.0); @@ -445,7 +540,10 @@ void main() { test('setZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -468,7 +566,10 @@ void main() { test('setZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -492,20 +593,29 @@ void main() { ); }); - test('setZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'setZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).thenThrow(CameraException( + when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( () => cameraController.setZoomLevel(42), - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -514,35 +624,52 @@ void main() { reset(CameraPlatform.instance); }); - test('setZoomLevel() completes and calls method channel with correct value.', () async { + test( + 'setZoomLevel() completes and calls method channel with correct value.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setZoomLevel(42.0); - verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).called(1); + verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) + .called(1); }); test('setFlashMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setFlashMode(FlashMode.always); - verify(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).called(1); + verify(CameraPlatform.instance + .setFlashMode(cameraController.cameraId, FlashMode.always)) + .called(1); }); - test('setFlashMode() throws $CameraException on $PlatformException', () async { + test('setFlashMode() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).thenThrow( + when(CameraPlatform.instance + .setFlashMode(cameraController.cameraId, FlashMode.always)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -560,22 +687,33 @@ void main() { test('setExposureMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposureMode(ExposureMode.auto); - verify(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).called(1); + verify(CameraPlatform.instance + .setExposureMode(cameraController.cameraId, ExposureMode.auto)) + .called(1); }); - test('setExposureMode() throws $CameraException on $PlatformException', () async { + test('setExposureMode() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).thenThrow( + when(CameraPlatform.instance + .setExposureMode(cameraController.cameraId, ExposureMode.auto)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -593,23 +731,32 @@ void main() { test('setExposurePoint() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposurePoint(const Offset(0.5, 0.5)); - verify(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) + verify(CameraPlatform.instance.setExposurePoint( + cameraController.cameraId, const Point(0.5, 0.5))) .called(1); }); - test('setExposurePoint() throws $CameraException on $PlatformException', () async { + test('setExposurePoint() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) + when(CameraPlatform.instance.setExposurePoint( + cameraController.cameraId, const Point(0.5, 0.5))) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -628,25 +775,37 @@ void main() { test('getMinExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getMinExposureOffset(); - verify(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .called(1); }); - test('getMinExposureOffset() throws $CameraException on $PlatformException', () async { + test('getMinExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -664,25 +823,37 @@ void main() { test('getMaxExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(1.0)); await cameraController.getMaxExposureOffset(); - verify(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .called(1); }); - test('getMaxExposureOffset() throws $CameraException on $PlatformException', () async { + test('getMaxExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -700,25 +871,38 @@ void main() { test('getExposureOffsetStepSize() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)) + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getExposureOffsetStepSize(); - verify(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .called(1); }); - test('getExposureOffsetStepSize() throws $CameraException on $PlatformException', () async { + test( + 'getExposureOffsetStepSize() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -736,28 +920,53 @@ void main() { test('setExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .thenAnswer((_) async => 1.0); await cameraController.setExposureOffset(1.0); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .called(1); }); - test('setExposureOffset() throws $CameraException on $PlatformException', () async { + test('setExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenThrow( + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -773,17 +982,34 @@ void main() { ))); }); - test('setExposureOffset() throws $CameraException when offset is out of bounds', () async { + test( + 'setExposureOffset() throws $CameraException when offset is out of bounds', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 2.0)) + .thenAnswer((_) async => 0.0); expect( cameraController.setExposureOffset(3.0), @@ -804,27 +1030,56 @@ void main() { await cameraController.setExposureOffset(-1.0); await cameraController.setExposureOffset(2.0); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(1); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).called(1); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.0)) + .called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 2.0)) + .called(1); }); test('setExposureOffset() rounds offset to nearest step', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.2); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 1.2); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 0.4); - - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.2)).thenAnswer((_) async => -1.2); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).thenAnswer((_) async => -0.8); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).thenAnswer((_) async => -0.4); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).thenAnswer((_) async => 0.4); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).thenAnswer((_) async => 0.8); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.2)).thenAnswer((_) async => 1.2); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.2); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 1.2); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 0.4); + + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.2)) + .thenAnswer((_) async => -1.2); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.8)) + .thenAnswer((_) async => -0.8); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.4)) + .thenAnswer((_) async => -0.4); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.4)) + .thenAnswer((_) async => 0.4); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.8)) + .thenAnswer((_) async => 0.8); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.2)) + .thenAnswer((_) async => 1.2); await cameraController.setExposureOffset(1.2); await cameraController.setExposureOffset(-1.2); @@ -843,62 +1098,97 @@ void main() { await cameraController.setExposureOffset(-0.6); await cameraController.setExposureOffset(-0.7); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).called(4); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).called(4); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.8)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.8)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.4)) + .called(4); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.4)) + .called(4); }); test('pausePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(deviceOrientation: DeviceOrientation.portraitUp); + cameraController.value = cameraController.value + .copyWith(deviceOrientation: DeviceOrientation.portraitUp); await cameraController.pausePreview(); - verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)) + .called(1); expect(cameraController.value.isPreviewPaused, equals(true)); - expect(cameraController.value.previewPauseOrientation, DeviceOrientation.portraitUp); + expect(cameraController.value.previewPauseOrientation, + DeviceOrientation.portraitUp); }); - test('pausePreview() does not call $CameraPlatform when already paused', () async { + test('pausePreview() does not call $CameraPlatform when already paused', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); await cameraController.pausePreview(); - verifyNever(CameraPlatform.instance.pausePreview(cameraController.cameraId)); + verifyNever( + CameraPlatform.instance.pausePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(true)); }); - test('pausePreview() sets previewPauseOrientation according to locked orientation', () async { + test( + 'pausePreview() sets previewPauseOrientation according to locked orientation', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); cameraController.value = cameraController.value.copyWith( isPreviewPaused: false, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: Optional.of(DeviceOrientation.landscapeRight)); + lockedCaptureOrientation: + Optional.of(DeviceOrientation.landscapeRight)); await cameraController.pausePreview(); - expect(cameraController.value.deviceOrientation, equals(DeviceOrientation.portraitUp)); - expect(cameraController.value.previewPauseOrientation, equals(DeviceOrientation.landscapeRight)); + expect(cameraController.value.deviceOrientation, + equals(DeviceOrientation.portraitUp)); + expect(cameraController.value.previewPauseOrientation, + equals(DeviceOrientation.landscapeRight)); }); - test('pausePreview() throws $CameraException on $PlatformException', () async { + test('pausePreview() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.pausePreview(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance.pausePreview(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -916,37 +1206,54 @@ void main() { test('resumePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); await cameraController.resumePreview(); - verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)) + .called(1); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() does not call $CameraPlatform when not paused', () async { + test('resumePreview() does not call $CameraPlatform when not paused', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: false); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: false); await cameraController.resumePreview(); - verifyNever(CameraPlatform.instance.resumePreview(cameraController.cameraId)); + verifyNever( + CameraPlatform.instance.resumePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() throws $CameraException on $PlatformException', () async { + test('resumePreview() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); - when(CameraPlatform.instance.resumePreview(cameraController.cameraId)).thenThrow( + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); + when(CameraPlatform.instance.resumePreview(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -964,28 +1271,41 @@ void main() { test('lockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.lockCaptureOrientation(); - expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.portraitUp)); - await cameraController.lockCaptureOrientation(DeviceOrientation.landscapeRight); - expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.landscapeRight)); - - verify(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) + expect(cameraController.value.lockedCaptureOrientation, + equals(DeviceOrientation.portraitUp)); + await cameraController + .lockCaptureOrientation(DeviceOrientation.landscapeRight); + expect(cameraController.value.lockedCaptureOrientation, + equals(DeviceOrientation.landscapeRight)); + + verify(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.portraitUp)) .called(1); - verify(CameraPlatform.instance - .lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.landscapeRight)) + verify(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.landscapeRight)) .called(1); }); - test('lockCaptureOrientation() throws $CameraException on $PlatformException', () async { + test( + 'lockCaptureOrientation() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) + when(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.portraitUp)) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -1004,22 +1324,34 @@ void main() { test('unlockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.unlockCaptureOrientation(); expect(cameraController.value.lockedCaptureOrientation, equals(null)); - verify(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .unlockCaptureOrientation(cameraController.cameraId)) + .called(1); }); - test('unlockCaptureOrientation() throws $CameraException on $PlatformException', () async { + test( + 'unlockCaptureOrientation() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .unlockCaptureOrientation(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1037,7 +1369,9 @@ void main() { }); } -class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements CameraPlatform { +class MockCameraPlatform extends Mock + with MockPlatformInterfaceMixin + implements CameraPlatform { @override Future initializeCamera( int? cameraId, { @@ -1057,7 +1391,8 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements } @override - Future> availableCameras() => Future>.value(mockAvailableCameras); + Future> availableCameras() => + Future>.value(mockAvailableCameras); @override Future createCamera( @@ -1078,46 +1413,52 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements Stream.value(mockOnCameraClosingEvent); @override - Stream onCameraError(int cameraId) => Stream.value(mockOnCameraErrorEvent); + Stream onCameraError(int cameraId) => + Stream.value(mockOnCameraErrorEvent); @override Stream onDeviceOrientationChanged() => - Stream.value(mockOnDeviceOrientationChangedEvent); + Stream.value( + mockOnDeviceOrientationChangedEvent); @override - Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) => - mockPlatformException - ? throw PlatformException(code: 'foo', message: 'bar') - : Future.value(mockTakePicture); + Future takePicture(int cameraId) => mockPlatformException + ? throw PlatformException(code: 'foo', message: 'bar') + : Future.value(mockTakePicture); @override Future prepareForVideoRecording() async => super.noSuchMethod(Invocation.method(#prepareForVideoRecording, null)); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) => + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) => Future.value(mockVideoRecordingXFile); @override Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } @override - Future lockCaptureOrientation(int? cameraId, DeviceOrientation? orientation) async => - super.noSuchMethod(Invocation.method(#lockCaptureOrientation, [cameraId, orientation])); + Future lockCaptureOrientation( + int? cameraId, DeviceOrientation? orientation) async => + super.noSuchMethod(Invocation.method( + #lockCaptureOrientation, [cameraId, orientation])); @override Future unlockCaptureOrientation(int? cameraId) async => - super.noSuchMethod(Invocation.method(#unlockCaptureOrientation, [cameraId])); + super.noSuchMethod( + Invocation.method(#unlockCaptureOrientation, [cameraId])); @override Future pausePreview(int? cameraId) async => super.noSuchMethod(Invocation.method(#pausePreview, [cameraId])); @override - Future resumePreview(int? cameraId) async => - super.noSuchMethod(Invocation.method(#resumePreview, [cameraId])); + Future resumePreview(int? cameraId) async => super + .noSuchMethod(Invocation.method(#resumePreview, [cameraId])); @override Future getMaxZoomLevel(int? cameraId) async => super.noSuchMethod( @@ -1133,40 +1474,48 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements @override Future setZoomLevel(int? cameraId, double? zoom) async => - super.noSuchMethod(Invocation.method(#setZoomLevel, [cameraId, zoom])); + super.noSuchMethod( + Invocation.method(#setZoomLevel, [cameraId, zoom])); @override Future setFlashMode(int? cameraId, FlashMode? mode) async => - super.noSuchMethod(Invocation.method(#setFlashMode, [cameraId, mode])); + super.noSuchMethod( + Invocation.method(#setFlashMode, [cameraId, mode])); @override Future setExposureMode(int? cameraId, ExposureMode? mode) async => - super.noSuchMethod(Invocation.method(#setExposureMode, [cameraId, mode])); + super.noSuchMethod( + Invocation.method(#setExposureMode, [cameraId, mode])); @override Future setExposurePoint(int? cameraId, Point? point) async => - super.noSuchMethod(Invocation.method(#setExposurePoint, [cameraId, point])); + super.noSuchMethod( + Invocation.method(#setExposurePoint, [cameraId, point])); @override - Future getMinExposureOffset(int? cameraId) async => super.noSuchMethod( + Future getMinExposureOffset(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getMinExposureOffset, [cameraId]), returnValue: Future.value(0.0), ) as Future; @override - Future getMaxExposureOffset(int? cameraId) async => super.noSuchMethod( + Future getMaxExposureOffset(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getMaxExposureOffset, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future getExposureOffsetStepSize(int? cameraId) async => super.noSuchMethod( + Future getExposureOffsetStepSize(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getExposureOffsetStepSize, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future setExposureOffset(int? cameraId, double? offset) async => super.noSuchMethod( + Future setExposureOffset(int? cameraId, double? offset) async => + super.noSuchMethod( Invocation.method(#setExposureOffset, [cameraId, offset]), returnValue: Future.value(1.0), ) as Future; diff --git a/packages/camera/camera_android/lib/src/android_camera.dart b/packages/camera/camera_android/lib/src/android_camera.dart index 8b8267d79e0..1aa31820bc0 100644 --- a/packages/camera/camera_android/lib/src/android_camera.dart +++ b/packages/camera/camera_android/lib/src/android_camera.dart @@ -14,7 +14,8 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_android'); +const MethodChannel _channel = + MethodChannel('plugins.flutter.io/camera_android'); /// The Android implementation of [CameraPlatform] that uses method channels. class AndroidCamera extends CameraPlatform { @@ -28,7 +29,8 @@ class AndroidCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = 'plugins.flutter.io/camera_android/fromPlatform'; + static const String deviceEventChannelName = + 'plugins.flutter.io/camera_android/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -38,14 +40,16 @@ class AndroidCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = + _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -61,13 +65,14 @@ class AndroidCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -76,7 +81,8 @@ class AndroidCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -92,9 +98,12 @@ class AndroidCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -110,8 +119,10 @@ class AndroidCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_android/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = + MethodChannel('plugins.flutter.io/camera_android/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -188,7 +199,8 @@ class AndroidCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream.whereType(); + return _deviceEventStreamController.stream + .whereType(); } @override @@ -198,7 +210,10 @@ class AndroidCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -211,10 +226,14 @@ class AndroidCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) async { + Future takePicture(int cameraId, + {ImageExtension imageExtension = ImageExtension.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId, 'imageExtension': _serializeImageExtension(imageExtension)}, + { + 'cameraId': cameraId, + 'imageExtension': _serializeImageExtension(imageExtension) + }, ); if (path == null) { @@ -228,11 +247,14 @@ class AndroidCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -276,18 +298,21 @@ class AndroidCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController({Function()? onListen}) { + StreamController _installStreamController( + {Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -307,9 +332,12 @@ class AndroidCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_android/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera_android/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -321,11 +349,13 @@ class AndroidCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -334,7 +364,8 @@ class AndroidCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -402,7 +433,8 @@ class AndroidCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -478,7 +510,8 @@ class AndroidCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -553,8 +586,8 @@ class AndroidCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -599,7 +632,9 @@ class AndroidCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_android/test/android_camera_test.dart b/packages/camera/camera_android/test/android_camera_test.dart index 88df959c7a6..cd4fcc5335b 100644 --- a/packages/camera/camera_android/test/android_camera_test.dart +++ b/packages/camera/camera_android/test/android_camera_test.dart @@ -32,31 +32,37 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AndroidCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(const MethodCall( + 'orientation_changed', + {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AndroidCamera camera = AndroidCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -64,13 +70,18 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -92,13 +103,16 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -120,8 +134,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -145,7 +161,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,14 +176,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -205,12 +225,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( @@ -286,8 +307,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -300,7 +323,8 @@ void main() { true, ImageExtension.jpeg, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -311,17 +335,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -335,14 +366,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -355,14 +391,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -375,17 +417,22 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( - AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AndroidCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -435,11 +482,20 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -455,17 +511,21 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -479,16 +539,19 @@ void main() { camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -539,7 +602,8 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -562,7 +626,9 @@ void main() { ]); }); - test('Should pass enableStream if callback is passed when starting recording a video', () async { + test( + 'Should pass enableStream if callback is passed when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -571,7 +637,8 @@ void main() { // Act await camera.startVideoCapturing( - VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {}), + VideoCaptureOptions(cameraId, + streamCallback: (CameraImageData imageData) {}), ); // Assert @@ -645,17 +712,20 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = - CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); + const CameraDescription camera2Description = CameraDescription( + name: 'Test2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', + arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -674,10 +744,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -694,8 +772,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -712,10 +794,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -727,7 +817,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -746,7 +837,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -809,8 +901,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -827,10 +923,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -843,10 +947,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final AndroidCamera camera = AndroidCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -900,11 +1007,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -921,7 +1030,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -932,12 +1042,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -953,7 +1066,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -969,7 +1083,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -985,7 +1100,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -1000,8 +1116,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1022,8 +1139,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index eea473a8888..fe200c4d377 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,7 +14,8 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = + MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -28,7 +29,8 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = + 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -38,14 +40,16 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = + _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -61,13 +65,14 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -76,7 +81,8 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -92,9 +98,12 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -110,8 +119,10 @@ class AVFoundationCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel( + 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -188,7 +199,8 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream.whereType(); + return _deviceEventStreamController.stream + .whereType(); } @override @@ -198,7 +210,10 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -211,10 +226,14 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) async { + Future takePicture(int cameraId, + {ImageExtension imageExtension = ImageExtension.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId, 'imageExtension': _serializeImageExtension(imageExtension)}, + { + 'cameraId': cameraId, + 'imageExtension': _serializeImageExtension(imageExtension) + }, ); if (path == null) { @@ -228,11 +247,14 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -277,18 +299,22 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { - _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { + _frameStreamController = + _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController({Function()? onListen}) { + StreamController _createStreamController( + {Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -307,14 +333,17 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -326,11 +355,13 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -339,7 +370,8 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -407,7 +439,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -483,7 +516,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -558,8 +592,8 @@ class AVFoundationCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -604,7 +638,9 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index a0296cb28c0..f627a03ebc2 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -17,8 +17,7 @@ flutter: dartPluginClass: AVFoundationCamera dependencies: - camera_platform_interface: - path: ../camera_platform_interface + camera_platform_interface: ^2.5.2 flutter: sdk: flutter stream_transform: ^2.0.0 diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 588c38b05bb..8a6626f4940 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -32,31 +32,37 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(const MethodCall( + 'orientation_changed', + {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AVFoundationCamera camera = AVFoundationCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -64,13 +70,18 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -92,13 +103,16 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -120,8 +134,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -145,7 +161,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,14 +176,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -205,12 +225,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( @@ -286,8 +307,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -300,7 +323,8 @@ void main() { true, ImageExtension.jpeg, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -311,17 +335,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -335,14 +366,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -355,14 +391,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -375,17 +417,22 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -435,14 +482,23 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange // This deliberately uses 'dynamic' since that's what actual platform // channel results will be, so using typed mock data could mask type // handling bugs in the code under test. final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -458,17 +514,21 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -482,16 +542,20 @@ void main() { camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should take a picture and return an XFile instance with jpeg format', () async { + test('Should take a picture and return an XFile instance with jpeg format', + () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -506,13 +570,16 @@ void main() { expect(file.path, '/test/path.jpg'); }); - test('Should take a picture and return an XFile instance with heic format', () async { + test('Should take a picture and return an XFile instance with heic format', + () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.heic'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.heic'}); // Act - final XFile file = await camera.takePicture(cameraId, imageExtension: ImageExtension.heic); + final XFile file = await camera.takePicture(cameraId, + imageExtension: ImageExtension.heic); // Assert expect(channel.log, [ @@ -560,7 +627,8 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -583,7 +651,9 @@ void main() { ]); }); - test('Should pass enableStream if callback is passed when starting recording a video', () async { + test( + 'Should pass enableStream if callback is passed when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -591,7 +661,8 @@ void main() { ); // Act - await camera.startVideoCapturing(VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {})); + await camera.startVideoCapturing(VideoCaptureOptions(cameraId, + streamCallback: (CameraImageData imageData) {})); // Assert expect(channel.log, [ @@ -664,17 +735,20 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = - CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); + const CameraDescription camera2Description = CameraDescription( + name: 'Test2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', + arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -693,10 +767,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -713,8 +795,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -731,10 +817,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -746,7 +840,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -765,7 +860,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -828,8 +924,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -846,10 +946,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -862,10 +970,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final AVFoundationCamera camera = AVFoundationCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -919,11 +1030,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -940,7 +1053,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -951,12 +1065,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -972,7 +1089,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -988,7 +1106,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -1004,7 +1123,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -1019,8 +1139,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1041,8 +1162,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart index ab52bf8cdfe..22256c6d103 100644 --- a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart +++ b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart @@ -34,7 +34,10 @@ abstract class CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || other is CameraEvent && runtimeType == other.runtimeType && cameraId == other.cameraId; + identical(this, other) || + other is CameraEvent && + runtimeType == other.runtimeType && + cameraId == other.cameraId; @override int get hashCode => cameraId.hashCode; @@ -64,10 +67,12 @@ class CameraInitializedEvent extends CameraEvent { : previewWidth = json['previewWidth']! as double, previewHeight = json['previewHeight']! as double, exposureMode = deserializeExposureMode(json['exposureMode']! as String), - exposurePointSupported = (json['exposurePointSupported'] as bool?) ?? false, + exposurePointSupported = + (json['exposurePointSupported'] as bool?) ?? false, focusMode = deserializeFocusMode(json['focusMode']! as String), focusPointSupported = (json['focusPointSupported'] as bool?) ?? false, - imageExtension = deserializeImageExtension(json['imageExtension']! as String), + imageExtension = + deserializeImageExtension(json['imageExtension']! as String), super(json['cameraId']! as int); /// The width of the preview in pixels. @@ -186,7 +191,8 @@ class CameraClosingEvent extends CameraEvent { /// Converts the supplied [Map] to an instance of the [CameraClosingEvent] /// class. - CameraClosingEvent.fromJson(Map json) : super(json['cameraId']! as int); + CameraClosingEvent.fromJson(Map json) + : super(json['cameraId']! as int); /// Converts the [CameraClosingEvent] instance into a [Map] instance that can /// be serialized to JSON. @@ -196,7 +202,10 @@ class CameraClosingEvent extends CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || super == other && other is CameraClosingEvent && runtimeType == other.runtimeType; + identical(this, other) || + super == other && + other is CameraClosingEvent && + runtimeType == other.runtimeType; @override // This is here even though it just calls super to make it less likely that @@ -254,8 +263,9 @@ class VideoRecordedEvent extends CameraEvent { /// class. VideoRecordedEvent.fromJson(Map json) : file = XFile(json['path']! as String), - maxVideoDuration = - json['maxVideoDuration'] != null ? Duration(milliseconds: json['maxVideoDuration'] as int) : null, + maxVideoDuration = json['maxVideoDuration'] != null + ? Duration(milliseconds: json['maxVideoDuration'] as int) + : null, super(json['cameraId']! as int); /// XFile of the recorded video. @@ -266,8 +276,11 @@ class VideoRecordedEvent extends CameraEvent { /// Converts the [VideoRecordedEvent] instance into a [Map] instance that can be /// serialized to JSON. - Map toJson() => - {'cameraId': cameraId, 'path': file.path, 'maxVideoDuration': maxVideoDuration?.inMilliseconds}; + Map toJson() => { + 'cameraId': cameraId, + 'path': file.path, + 'maxVideoDuration': maxVideoDuration?.inMilliseconds + }; @override bool operator ==(Object other) => diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 02e659ba7b0..8c50155e588 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,8 +20,10 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler( + (MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -34,7 +36,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -44,7 +47,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = StreamController.broadcast(); + final StreamController deviceEventStreamController = + StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -53,13 +57,14 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -68,7 +73,8 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -84,9 +90,12 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -102,8 +111,10 @@ class MethodChannelCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -180,7 +191,8 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream.whereType(); + return deviceEventStreamController.stream + .whereType(); } @override @@ -190,7 +202,10 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -203,10 +218,14 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) async { + Future takePicture(int cameraId, + {ImageExtension imageExtension = ImageExtension.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId, 'imageFormat': _serializeImageExtension(imageExtension)}, + { + 'cameraId': cameraId, + 'imageFormat': _serializeImageExtension(imageExtension) + }, ); if (path == null) { @@ -220,11 +239,14 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -268,18 +290,21 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController({Function()? onListen}) { + StreamController _installStreamController( + {Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -299,8 +324,10 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -308,7 +335,8 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -320,11 +348,13 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -333,7 +363,8 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -401,7 +432,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -477,7 +509,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -541,8 +574,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -587,7 +620,9 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index be24eb41eec..3945d3174a3 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -99,11 +99,13 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError( + 'onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation( + int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -113,7 +115,8 @@ abstract class CameraPlatform extends PlatformInterface { } /// Captures an image and returns the file where it was saved. - Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) { + Future takePicture(int cameraId, + {ImageExtension imageExtension = ImageExtension.jpeg}) { throw UnimplementedError('takePicture() is not implemented.'); } @@ -140,7 +143,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -168,7 +172,8 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -267,7 +272,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError( + 'setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 779f2580dca..e7bdafeb4f6 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, + ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -24,7 +24,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraInitializedEvent event = CameraInitializedEvent.fromJson(const { + final CameraInitializedEvent event = + CameraInitializedEvent.fromJson(const { 'cameraId': 1, 'previewWidth': 1024.0, 'previewHeight': 640.0, @@ -45,8 +46,8 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.heic); + const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, + ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.heic); final Map jsonMap = event.toJson(); @@ -62,89 +63,216 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 2, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 2048, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 980, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.locked, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); - test('equals should return false if exposurePointSupported is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true, ImageExtension.jpeg); + test('equals should return false if exposurePointSupported is different', + () { + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + false, + FocusMode.auto, + true, + ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true, ImageExtension.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.locked, + true, + ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false, ImageExtension.jpeg); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + false, + ImageExtension.jpeg); expect(firstEvent == secondEvent, false); }); test('equals should return true if imageExtension is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.heic); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.jpeg); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ImageExtension.heic); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, + ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.previewWidth, @@ -162,7 +290,8 @@ void main() { group('CameraResolutionChangesEvent tests', () { test('Constructor should initialize all properties', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); expect(event.cameraId, 1); expect(event.captureWidth, 1024); @@ -170,7 +299,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraResolutionChangedEvent event = CameraResolutionChangedEvent.fromJson(const { + final CameraResolutionChangedEvent event = + CameraResolutionChangedEvent.fromJson(const { 'cameraId': 1, 'captureWidth': 1024.0, 'captureHeight': 640.0, @@ -182,7 +312,8 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); final Map jsonMap = event.toJson(); @@ -193,35 +324,44 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 1024, 640); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(2, 1024, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(2, 1024, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureWidth is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 2048, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 2048, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureHeight is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 980); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 1024, 980); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.captureWidth, @@ -240,7 +380,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraClosingEvent event = CameraClosingEvent.fromJson(const { + final CameraClosingEvent event = + CameraClosingEvent.fromJson(const { 'cameraId': 1, }); @@ -287,8 +428,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraErrorEvent event = - CameraErrorEvent.fromJson(const {'cameraId': 1, 'description': 'Error'}); + final CameraErrorEvent event = CameraErrorEvent.fromJson( + const {'cameraId': 1, 'description': 'Error'}); expect(event.cameraId, 1); expect(event.description, 'Error'); @@ -327,7 +468,8 @@ void main() { test('hashCode should match hashCode of all properties', () { const CameraErrorEvent event = CameraErrorEvent(1, 'Error'); - final int expectedHashCode = Object.hash(event.cameraId.hashCode, event.description); + final int expectedHashCode = + Object.hash(event.cameraId.hashCode, event.description); expect(event.hashCode, expectedHashCode); }); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index 856e566595d..61fe66a60ac 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -22,18 +22,22 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -41,20 +45,28 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test( + 'Should throw CameraException when create throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -69,20 +81,26 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test( + 'Should throw CameraException when create throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -97,8 +115,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -122,7 +142,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having((CameraException e) => e.code, 'code', + 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -134,14 +157,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -182,12 +206,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( @@ -263,8 +288,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -277,7 +304,8 @@ void main() { true, ImageExtension.heic, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -288,17 +316,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -312,14 +347,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -332,14 +372,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -352,15 +398,20 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); // Assert expect(await streamQueue.next, event); @@ -409,11 +460,20 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -429,40 +489,51 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'availableCameras': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'availableCameras': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); // Act expect( camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should take a picture and return an XFile instance with jpg extension', () async { + test( + 'Should take a picture and return an XFile instance with jpg extension', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.jpg'}); + channelName: 'plugins.flutter.io/camera', + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -477,13 +548,17 @@ void main() { expect(file.path, '/test/path.jpg'); }); - test('Should take a picture and return an XFile instance with heic extension', () async { + test( + 'Should take a picture and return an XFile instance with heic extension', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.heic'}); + channelName: 'plugins.flutter.io/camera', + methods: {'takePicture': '/test/path.heic'}); // Act - final XFile file = await camera.takePicture(cameraId, imageExtension: ImageExtension.heic); + final XFile file = await camera.takePicture(cameraId, + imageExtension: ImageExtension.heic); // Assert expect(channel.log, [ @@ -539,18 +614,23 @@ void main() { ); // Act - const CameraDescription cameraDescription = - CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0); + const CameraDescription cameraDescription = CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0); await camera.setDescriptionWhileRecording(cameraDescription); // Assert expect(channel.log, [ isMethodCall('setDescriptionWhileRecording', - arguments: {'cameraName': cameraDescription.name}), + arguments: { + 'cameraName': cameraDescription.name + }), ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -643,10 +723,22 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'off' + }), ]); }); @@ -663,8 +755,14 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -681,10 +779,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -696,7 +802,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -715,7 +822,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -734,14 +842,16 @@ void main() { ); // Act - final double stepSize = await camera.getExposureOffsetStepSize(cameraId); + final double stepSize = + await camera.getExposureOffsetStepSize(cameraId); // Assert expect(stepSize, 0.25); expect(channel.log, [ - isMethodCall('getExposureOffsetStepSize', arguments: { - 'cameraId': cameraId, - }), + isMethodCall('getExposureOffsetStepSize', + arguments: { + 'cameraId': cameraId, + }), ]); }); @@ -753,7 +863,8 @@ void main() { ); // Act - final double actualOffset = await camera.setExposureOffset(cameraId, 0.5); + final double actualOffset = + await camera.setExposureOffset(cameraId, 0.5); // Assert expect(actualOffset, 0.6); @@ -778,8 +889,14 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -796,10 +913,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -812,10 +937,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final MethodChannelCamera camera = MethodChannelCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -869,11 +997,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -890,7 +1020,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -901,12 +1032,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -922,7 +1056,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -938,7 +1073,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -954,7 +1090,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -969,8 +1106,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -991,8 +1129,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert From 2abeabe36526013383e4eaa3081a3a4476bf959f Mon Sep 17 00:00:00 2001 From: Mairramer <50643541+Mairramer@users.noreply.github.com> Date: Sun, 30 Jul 2023 14:27:07 -0300 Subject: [PATCH 12/71] Update FLTCam.h --- packages/camera/camera_avfoundation/ios/Classes/FLTCam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 30563276744..7d4be9e5df3 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -57,7 +57,7 @@ typedef NS_ENUM(NSInteger, ImageExtension) { - (void)stop; - (void)setDeviceOrientation:(UIDeviceOrientation)orientation; - (void)captureToFile:(FLTThreadSafeFlutterResult *)result - ImageExtension:(ImageExtension)imageExtension; + imageExtension:(ImageExtension)imageExtension; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; /** From d889f8b55b9b843c5a841dca7ef8f49f52f93276 Mon Sep 17 00:00:00 2001 From: Mairramer <50643541+Mairramer@users.noreply.github.com> Date: Sun, 30 Jul 2023 16:36:30 -0300 Subject: [PATCH 13/71] Update CHANGELOG.md --- packages/camera/camera_platform_interface/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index 3ad48c1ff3a..63cada6e5c7 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,4 +1,4 @@ -## 2.5.2 +## NEXT * Add support to HEIC format on take picture (only iOS). From 53a58380a0024540d04b581bf3968e8556b52790 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 30 Jul 2023 16:43:27 -0300 Subject: [PATCH 14/71] fix versions --- packages/camera/camera/pubspec.yaml | 2 +- packages/camera/camera_android/pubspec.yaml | 2 +- packages/camera/camera_platform_interface/pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 677b61b93e7..7ba688486a0 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -23,7 +23,7 @@ flutter: dependencies: camera_android: ^0.10.7 camera_avfoundation: ^0.9.14 - camera_platform_interface: ^2.5.2 + camera_platform_interface: ^2.5.1 camera_web: ^0.3.1 flutter: sdk: flutter diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml index 095026841d8..1858481ad45 100644 --- a/packages/camera/camera_android/pubspec.yaml +++ b/packages/camera/camera_android/pubspec.yaml @@ -19,7 +19,7 @@ flutter: dartPluginClass: AndroidCamera dependencies: - camera_platform_interface: ^2.5.2 + camera_platform_interface: ^2.5.1 flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.2 diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml index 77f0798999d..3dc49cec038 100644 --- a/packages/camera/camera_platform_interface/pubspec.yaml +++ b/packages/camera/camera_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.5.2 +version: 2.5.1 environment: sdk: ">=2.18.0 <4.0.0" From 89905f7baaf060780a2ce57fb43343ab811d41f8 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 30 Jul 2023 16:53:44 -0300 Subject: [PATCH 15/71] fix versions --- packages/camera/camera_android/pubspec.yaml | 2 +- packages/camera/camera_avfoundation/CHANGELOG.md | 5 +---- packages/camera/camera_platform_interface/pubspec.yaml | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml index 1858481ad45..095026841d8 100644 --- a/packages/camera/camera_android/pubspec.yaml +++ b/packages/camera/camera_android/pubspec.yaml @@ -19,7 +19,7 @@ flutter: dartPluginClass: AndroidCamera dependencies: - camera_platform_interface: ^2.5.1 + camera_platform_interface: ^2.5.2 flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.2 diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 29cb18f4b42..ea9fadc1c40 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,10 +1,7 @@ ## NEXT -* Fixes unawaited_futures violations. - -## 0.9.14 - * Add support to HEIC format +* Fixes unawaited_futures violations. ## 0.9.13+2 diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml index 3dc49cec038..77f0798999d 100644 --- a/packages/camera/camera_platform_interface/pubspec.yaml +++ b/packages/camera/camera_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.5.1 +version: 2.5.2 environment: sdk: ">=2.18.0 <4.0.0" From c748a8639bd32341d59dea9298bc72ec2b94dcb5 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 30 Jul 2023 17:16:33 -0300 Subject: [PATCH 16/71] fix versions to NEXT --- packages/camera/camera/pubspec.yaml | 2 +- packages/camera/camera_android/pubspec.yaml | 2 +- .../camera_avfoundation/example/pubspec.yaml | 2 +- .../camera/camera_avfoundation/pubspec.yaml | 4 +- .../method_channel/method_channel_camera.dart | 101 ++++++------------ .../camera_platform_interface/pubspec.yaml | 2 +- 6 files changed, 39 insertions(+), 74 deletions(-) diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 7ba688486a0..fa2597a68b4 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -22,7 +22,7 @@ flutter: dependencies: camera_android: ^0.10.7 - camera_avfoundation: ^0.9.14 + camera_avfoundation: ^0.9.13+2 camera_platform_interface: ^2.5.1 camera_web: ^0.3.1 flutter: diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml index 095026841d8..1858481ad45 100644 --- a/packages/camera/camera_android/pubspec.yaml +++ b/packages/camera/camera_android/pubspec.yaml @@ -19,7 +19,7 @@ flutter: dartPluginClass: AndroidCamera dependencies: - camera_platform_interface: ^2.5.2 + camera_platform_interface: ^2.5.1 flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.2 diff --git a/packages/camera/camera_avfoundation/example/pubspec.yaml b/packages/camera/camera_avfoundation/example/pubspec.yaml index 957dfeacca3..0aa841addaa 100644 --- a/packages/camera/camera_avfoundation/example/pubspec.yaml +++ b/packages/camera/camera_avfoundation/example/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - camera_platform_interface: ^2.5.2 + camera_platform_interface: ^2.5.1 flutter: sdk: flutter path_provider: ^2.0.0 diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index f627a03ebc2..4d19fc78690 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_avfoundation description: iOS implementation of the camera plugin. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.14 +version: 0.9.13+2 environment: sdk: ">=2.18.0 <4.0.0" @@ -17,7 +17,7 @@ flutter: dartPluginClass: AVFoundationCamera dependencies: - camera_platform_interface: ^2.5.2 + camera_platform_interface: ^2.5.1 flutter: sdk: flutter stream_transform: ^2.0.0 diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 8c50155e588..c27e1421d3a 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,10 +20,8 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler( - (MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -36,8 +34,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -47,8 +44,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = - StreamController.broadcast(); + final StreamController deviceEventStreamController = StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -57,14 +53,13 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -73,8 +68,7 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -90,12 +84,9 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -111,10 +102,8 @@ class MethodChannelCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -191,8 +180,7 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream - .whereType(); + return deviceEventStreamController.stream.whereType(); } @override @@ -202,10 +190,7 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -218,14 +203,10 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, - {ImageExtension imageExtension = ImageExtension.jpeg}) async { + Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - { - 'cameraId': cameraId, - 'imageFormat': _serializeImageExtension(imageExtension) - }, + {'cameraId': cameraId, 'imageExtension': _serializeImageExtension(imageExtension)}, ); if (path == null) { @@ -239,14 +220,11 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -290,21 +268,18 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController( - {Function()? onListen}) { + StreamController _installStreamController({Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -324,10 +299,8 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -335,8 +308,7 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -348,13 +320,11 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -363,8 +333,7 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -432,8 +401,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -509,8 +477,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -574,8 +541,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -620,9 +587,7 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml index 77f0798999d..3dc49cec038 100644 --- a/packages/camera/camera_platform_interface/pubspec.yaml +++ b/packages/camera/camera_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.5.2 +version: 2.5.1 environment: sdk: ">=2.18.0 <4.0.0" From 4d7b623911b647768cdd6f77772962d4c53f6312 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 30 Jul 2023 17:26:14 -0300 Subject: [PATCH 17/71] versions next section --- packages/camera/camera/pubspec.yaml | 45 +++++++++---------- .../camera_avfoundation/example/pubspec.yaml | 2 +- .../camera/camera_avfoundation/pubspec.yaml | 4 +- .../camera_platform_interface/pubspec.yaml | 2 +- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index fa2597a68b4..453c5867362 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -1,38 +1,33 @@ -name: camera -description: A Flutter plugin for controlling the camera. Supports previewing - the camera feed, capturing images and video, and streaming image buffers to - Dart. -repository: https://github.com/flutter/packages/tree/main/packages/camera/camera -issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.10.6 - -environment: - sdk: ">=2.18.0 <4.0.0" - flutter: ">=3.3.0" - -flutter: - plugin: - platforms: - android: - default_package: camera_android - ios: - default_package: camera_avfoundation - web: - default_package: camera_web - +--- dependencies: camera_android: ^0.10.7 - camera_avfoundation: ^0.9.13+2 - camera_platform_interface: ^2.5.1 + camera_avfoundation: ^0.9.14 + camera_platform_interface: ^2.5.2 camera_web: ^0.3.1 flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.2 quiver: ^3.0.0 - +description: A Flutter plugin for controlling the camera. Supports previewing the camera feed, capturing images and video, and streaming image buffers to Dart. dev_dependencies: flutter_test: sdk: flutter mockito: 5.4.1 plugin_platform_interface: ^2.0.0 video_player: ^2.0.0 +environment: + flutter: '>=3.3.0' + sdk: '>=2.18.0 <4.0.0' +flutter: + plugin: + platforms: + android: + default_package: camera_android + ios: + default_package: camera_avfoundation + web: + default_package: camera_web +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 +name: camera +repository: https://github.com/flutter/packages/tree/main/packages/camera/camera +version: 0.10.6 \ No newline at end of file diff --git a/packages/camera/camera_avfoundation/example/pubspec.yaml b/packages/camera/camera_avfoundation/example/pubspec.yaml index 0aa841addaa..957dfeacca3 100644 --- a/packages/camera/camera_avfoundation/example/pubspec.yaml +++ b/packages/camera/camera_avfoundation/example/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - camera_platform_interface: ^2.5.1 + camera_platform_interface: ^2.5.2 flutter: sdk: flutter path_provider: ^2.0.0 diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index 4d19fc78690..f627a03ebc2 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_avfoundation description: iOS implementation of the camera plugin. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.13+2 +version: 0.9.14 environment: sdk: ">=2.18.0 <4.0.0" @@ -17,7 +17,7 @@ flutter: dartPluginClass: AVFoundationCamera dependencies: - camera_platform_interface: ^2.5.1 + camera_platform_interface: ^2.5.2 flutter: sdk: flutter stream_transform: ^2.0.0 diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml index 3dc49cec038..77f0798999d 100644 --- a/packages/camera/camera_platform_interface/pubspec.yaml +++ b/packages/camera/camera_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.5.1 +version: 2.5.2 environment: sdk: ">=2.18.0 <4.0.0" From 42cdd9d286ac32c4b697bf194dc49481769633ee Mon Sep 17 00:00:00 2001 From: Mairramer Date: Mon, 31 Jul 2023 11:55:58 -0300 Subject: [PATCH 18/71] fix tests --- .../camera/test/camera_preview_test.dart | 2 +- packages/camera/camera/test/camera_test.dart | 8 +- .../method_channel/method_channel_camera.dart | 101 ++++++++++++------ 3 files changed, 74 insertions(+), 37 deletions(-) diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index fe27d3e5e46..33a6d7c2dcb 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -124,7 +124,7 @@ class FakeController extends ValueNotifier CameraDescription get description => value.description; @override - ImageExtension get imageExtension => ImageExtension.png; + ImageExtension get imageExtension => ImageExtension.jpeg; } void main() { diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index 64cfac63ac3..ad039c15c76 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -1422,9 +1422,11 @@ class MockCameraPlatform extends Mock mockOnDeviceOrientationChangedEvent); @override - Future takePicture(int cameraId) => mockPlatformException - ? throw PlatformException(code: 'foo', message: 'bar') - : Future.value(mockTakePicture); + Future takePicture(int cameraId, + {ImageExtension imageExtension = ImageExtension.jpeg}) => + mockPlatformException + ? throw PlatformException(code: 'foo', message: 'bar') + : Future.value(mockTakePicture); @override Future prepareForVideoRecording() async => diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index c27e1421d3a..b0e13a8a465 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,8 +20,10 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler( + (MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -34,7 +36,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -44,7 +47,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = StreamController.broadcast(); + final StreamController deviceEventStreamController = + StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -53,13 +57,14 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -68,7 +73,8 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -84,9 +90,12 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -102,8 +111,10 @@ class MethodChannelCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -180,7 +191,8 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream.whereType(); + return deviceEventStreamController.stream + .whereType(); } @override @@ -190,7 +202,10 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -203,10 +218,14 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) async { + Future takePicture(int cameraId, + {ImageExtension imageExtension = ImageExtension.jpeg}) async { final String? path = await _channel.invokeMethod( 'takePicture', - {'cameraId': cameraId, 'imageExtension': _serializeImageExtension(imageExtension)}, + { + 'cameraId': cameraId, + 'imageExtension': _serializeImageExtension(imageExtension) + }, ); if (path == null) { @@ -220,11 +239,14 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -268,18 +290,21 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController({Function()? onListen}) { + StreamController _installStreamController( + {Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -299,8 +324,10 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -308,7 +335,8 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -320,11 +348,13 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -333,7 +363,8 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -401,7 +432,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -477,7 +509,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -541,8 +574,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -587,7 +620,9 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': From 4ee252714162b89284cff97fd38bc5004b33258f Mon Sep 17 00:00:00 2001 From: Mairramer Date: Thu, 3 Aug 2023 17:58:15 -0300 Subject: [PATCH 19/71] refactor code --- packages/camera/camera/example/pubspec.yaml | 5 ++ packages/camera/camera/pubspec.yaml | 53 ++++++++++++------- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 4 +- .../camera_avfoundation/example/pubspec.yaml | 5 ++ .../ios/Classes/CameraPlugin.m | 10 +--- .../ios/Classes/CameraProperties.h | 15 ++++++ .../ios/Classes/CameraProperties.m | 17 ++++++ .../camera_avfoundation/ios/Classes/FLTCam.h | 12 +---- .../camera_avfoundation/ios/Classes/FLTCam.m | 23 ++++---- .../camera/camera_avfoundation/pubspec.yaml | 5 ++ 10 files changed, 95 insertions(+), 54 deletions(-) diff --git a/packages/camera/camera/example/pubspec.yaml b/packages/camera/camera/example/pubspec.yaml index 41ed519cd17..7d904d9fd67 100644 --- a/packages/camera/camera/example/pubspec.yaml +++ b/packages/camera/camera/example/pubspec.yaml @@ -30,3 +30,8 @@ dev_dependencies: flutter: uses-material-design: true + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changing-federated-plugins +dependency_overrides: + {camera_platform_interface: {path: ../../../camera/camera_platform_interface}} diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 453c5867362..00861accc98 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -1,33 +1,46 @@ ---- +name: camera +description: A Flutter plugin for controlling the camera. Supports previewing + the camera feed, capturing images and video, and streaming image buffers to + Dart. +repository: https://github.com/flutter/packages/tree/main/packages/camera/camera +issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 +version: 0.10.6 + +environment: + sdk: ">=2.18.0 <4.0.0" + flutter: ">=3.3.0" + +flutter: + plugin: + platforms: + android: + default_package: camera_android + ios: + default_package: camera_avfoundation + web: + default_package: camera_web + dependencies: camera_android: ^0.10.7 - camera_avfoundation: ^0.9.14 - camera_platform_interface: ^2.5.2 + camera_avfoundation: ^0.9.13+2 + camera_platform_interface: ^2.5.1 camera_web: ^0.3.1 flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.2 quiver: ^3.0.0 -description: A Flutter plugin for controlling the camera. Supports previewing the camera feed, capturing images and video, and streaming image buffers to Dart. + dev_dependencies: flutter_test: sdk: flutter mockito: 5.4.1 plugin_platform_interface: ^2.0.0 video_player: ^2.0.0 -environment: - flutter: '>=3.3.0' - sdk: '>=2.18.0 <4.0.0' -flutter: - plugin: - platforms: - android: - default_package: camera_android - ios: - default_package: camera_avfoundation - web: - default_package: camera_web -issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -name: camera -repository: https://github.com/flutter/packages/tree/main/packages/camera/camera -version: 0.10.6 \ No newline at end of file + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changing-federated-plugins +dependency_overrides: + { + camera_avfoundation: {path: ../../camera/camera_avfoundation}, + camera_platform_interface: {path: ../../camera/camera_platform_interface}, + } diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 1856f110b9e..09be99356c2 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -49,7 +49,7 @@ - (void)testCaptureToFile_mustReportErrorToResultIfSavePhotoDelegateCompletionsW // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult imageExtenion:ImageExtensionHEIC]; + [cam captureToFile:mockResult imageExtensionString:@"heic"]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -89,7 +89,7 @@ - (void)testCaptureToFile_mustReportPathToResultIfSavePhotoDelegateCompletionsWi // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult imageExtenion:ImageExtensionHEIC]; + [cam captureToFile:mockResult imageExtensionString:@"heic"]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; } diff --git a/packages/camera/camera_avfoundation/example/pubspec.yaml b/packages/camera/camera_avfoundation/example/pubspec.yaml index 957dfeacca3..7288f28dd50 100644 --- a/packages/camera/camera_avfoundation/example/pubspec.yaml +++ b/packages/camera/camera_avfoundation/example/pubspec.yaml @@ -30,3 +30,8 @@ dev_dependencies: flutter: uses-material-design: true + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changing-federated-plugins +dependency_overrides: + {camera_platform_interface: {path: ../../../camera/camera_platform_interface}} diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index de5eceb7529..1baa66ecd0d 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -184,15 +184,9 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call [_camera start]; [result sendSuccess]; }else if ([@"takePicture" isEqualToString:call.method]) { - NSString *formatString = call.arguments[@"imageExtension"]; - - ImageExtension imageExtension = ImageExtensionJPEG; - if ([formatString isEqualToString:@"heic"]) { - imageExtension = ImageExtensionHEIC; - } + NSString *formatString = call.arguments[@"imageExtension"]; - - [_camera captureToFile:result imageExtension:imageExtension]; + [_camera captureToFile:result imageExtensionString:formatString]; } else if ([@"dispose" isEqualToString:call.method]) { [_registry unregisterTexture:cameraId]; diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index aee4d643f64..385db610c94 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -115,4 +115,19 @@ extern FLTResolutionPreset FLTGetFLTResolutionPresetForString(NSString *preset); */ extern OSType FLTGetVideoFormatFromString(NSString *videoFormatString); +/** + * Represents image format. Mirrors ImageExtension in camera.dart. + */ +typedef NS_ENUM(NSInteger, ImageExtension) { + ImageExtensionJPEG, + ImageExtensionHEIC, +}; + +#pragma mark - image extension + +/** + * Gets ImageExtension from its string representation. + */ +extern ImageExtension FLTGetImageExtensionForString(NSString *imageExtensionString); + NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m index e36f98af27f..20d0a23eb81 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m @@ -3,6 +3,7 @@ // found in the LICENSE file. #import "CameraProperties.h" +#import #pragma mark - flash mode @@ -185,3 +186,19 @@ OSType FLTGetVideoFormatFromString(NSString *videoFormatString) { return kCVPixelFormatType_32BGRA; } } + +#pragma mark - video codec + +ImageExtension FLTGetImageExtensionForString(NSString *extensionString) { + if ([extensionString isEqualToString:@"jpg"]) { + return ImageExtensionJPEG; + } else if ([extensionString isEqualToString:@"heic"]) { + return ImageExtensionHEIC; + } else { + NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain + code:NSURLErrorUnknown + userInfo:@{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Unknown image extension %@", extensionString] }]; + @throw error; + } +} + diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 7d4be9e5df3..6c256a69852 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -14,14 +14,6 @@ NS_ASSUME_NONNULL_BEGIN -/** - * Represents image format. Mirrors ImageExtension in camera.dart. - */ -typedef NS_ENUM(NSInteger, ImageExtension) { - ImageExtensionJPEG, - ImageExtensionHEIC, -}; - /** * A class that manages camera's state and performs camera operations. */ @@ -38,7 +30,7 @@ typedef NS_ENUM(NSInteger, ImageExtension) { @property(assign, nonatomic) FLTFlashMode flashMode; // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; -@property(readonly, nonatomic) ImageExtension imageExtension; +@property(assign, nonatomic, readonly) ImageExtension imageExtension; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. @@ -57,7 +49,7 @@ typedef NS_ENUM(NSInteger, ImageExtension) { - (void)stop; - (void)setDeviceOrientation:(UIDeviceOrientation)orientation; - (void)captureToFile:(FLTThreadSafeFlutterResult *)result - imageExtension:(ImageExtension)imageExtension; + imageExtensionString:(NSString *)imageExtensionString; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; /** diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index aaef62abbbf..de85d671446 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -244,24 +244,19 @@ - (void)updateOrientation:(UIDeviceOrientation)orientation } } -- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageExtension:(ImageExtension)imageExtension { +- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageExtensionString:(NSString *)imageExtensionString { + ImageExtension imageExtension = FLTGetImageExtensionForString(imageExtensionString); + AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; - NSString *extension; + NSString *extension = @"jpg"; if (_resolutionPreset == FLTResolutionPresetMax) { [settings setHighResolutionPhotoEnabled:YES]; } - - if (self.imageExtension == ImageExtensionHEIC) { - if (@available(iOS 11.0, *)) { - if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { - settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{ AVVideoCodecKey : AVVideoCodecTypeHEVC }]; - extension = @"heic"; - } else { - settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{ AVVideoCodecKey : AVVideoCodecTypeJPEG }]; - extension = @"jpg"; - } - } else { - extension = @"jpg"; + + if (imageExtension == ImageExtensionHEIC && @available(iOS 11.0, *)) { + if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { + settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{ AVVideoCodecKey : AVVideoCodecTypeHEVC }]; + extension = @"heic"; } } diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index f627a03ebc2..3627ddecfdb 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -26,3 +26,8 @@ dev_dependencies: async: ^2.5.0 flutter_test: sdk: flutter + +# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. +# See https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changing-federated-plugins +dependency_overrides: + {camera_platform_interface: {path: ../../camera/camera_platform_interface}} From a446d0197986b66606b308b357c8c598097186ef Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 4 Aug 2023 10:19:09 -0300 Subject: [PATCH 20/71] added default value --- .../lib/src/android_camera.dart | 19 +- .../test/android_camera_test.dart | 5 - .../lib/src/avfoundation_camera.dart | 3 +- .../test/avfoundation_camera_test.dart | 5 - .../lib/src/events/camera_event.dart | 17 +- .../method_channel/method_channel_camera.dart | 3 +- .../test/events/camera_event_test.dart | 176 +++--------------- .../method_channel_camera_test.dart | 10 +- 8 files changed, 45 insertions(+), 193 deletions(-) diff --git a/packages/camera/camera_android/lib/src/android_camera.dart b/packages/camera/camera_android/lib/src/android_camera.dart index 1aa31820bc0..eca1003247c 100644 --- a/packages/camera/camera_android/lib/src/android_camera.dart +++ b/packages/camera/camera_android/lib/src/android_camera.dart @@ -226,14 +226,10 @@ class AndroidCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, - {ImageExtension imageExtension = ImageExtension.jpeg}) async { + Future takePicture(int cameraId) async { final String? path = await _channel.invokeMethod( 'takePicture', - { - 'cameraId': cameraId, - 'imageExtension': _serializeImageExtension(imageExtension) - }, + {'cameraId': cameraId}, ); if (path == null) { @@ -571,16 +567,6 @@ class AndroidCamera extends CameraPlatform { return 'max'; } - /// Returns the format of the image as a String. - String _serializeImageExtension(ImageExtension imageExtension) { - switch (imageExtension) { - case ImageExtension.jpeg: - return 'jpeg'; - case ImageExtension.heic: - return 'heic'; - } - } - /// Converts messages received from the native platform into device events. Future _handleDeviceMethodCall(MethodCall call) async { switch (call.method) { @@ -611,7 +597,6 @@ class AndroidCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, - deserializeImageExtension(arguments['imageExtension']! as String), )); break; case 'resolution_changed': diff --git a/packages/camera/camera_android/test/android_camera_test.dart b/packages/camera/camera_android/test/android_camera_test.dart index cd4fcc5335b..49a09bcbcbb 100644 --- a/packages/camera/camera_android/test/android_camera_test.dart +++ b/packages/camera/camera_android/test/android_camera_test.dart @@ -205,7 +205,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, )); await initializeFuture; @@ -251,7 +250,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, )); await initializeFuture; @@ -300,7 +298,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, )); await initializeFuture; }); @@ -321,7 +318,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, ); await camera.handleCameraMethodCall( MethodCall('initialized', event.toJson()), cameraId); @@ -476,7 +472,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, ), ); await initializeFuture; diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index fe200c4d377..8b4ef0b9eda 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -617,7 +617,8 @@ class AVFoundationCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, - deserializeImageExtension(arguments['imageExtension']! as String), + imageExtension: + deserializeImageExtension(arguments['imageExtension']! as String), )); break; case 'resolution_changed': diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 8a6626f4940..2558da3919e 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -205,7 +205,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, )); await initializeFuture; @@ -251,7 +250,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, )); await initializeFuture; @@ -300,7 +298,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, )); await initializeFuture; }); @@ -321,7 +318,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, ); await camera.handleCameraMethodCall( MethodCall('initialized', event.toJson()), cameraId); @@ -476,7 +472,6 @@ void main() { true, FocusMode.auto, true, - ImageExtension.jpeg, ), ); await initializeFuture; diff --git a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart index 22256c6d103..8a342cc6279 100644 --- a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart +++ b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart @@ -51,15 +51,14 @@ class CameraInitializedEvent extends CameraEvent { /// The `previewWidth` represents the width of the generated preview in pixels. /// The `previewHeight` represents the height of the generated preview in pixels. const CameraInitializedEvent( - super.cameraId, - this.previewWidth, - this.previewHeight, - this.exposureMode, - this.exposurePointSupported, - this.focusMode, - this.focusPointSupported, - this.imageExtension, - ); + super.cameraId, + this.previewWidth, + this.previewHeight, + this.exposureMode, + this.exposurePointSupported, + this.focusMode, + this.focusPointSupported, + {this.imageExtension = ImageExtension.jpeg}); /// Converts the supplied [Map] to an instance of the [CameraInitializedEvent] /// class. diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index b0e13a8a465..583b8e42417 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -599,7 +599,8 @@ class MethodChannelCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, - deserializeImageExtension(arguments['imageExtension']! as String), + imageExtension: + deserializeImageExtension(arguments['imageExtension']! as String), )); break; case 'resolution_changed': diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index e7bdafeb4f6..e2028d60641 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, - ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent event = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -46,8 +46,9 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, - ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.heic); + const CameraInitializedEvent event = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, + imageExtension: ImageExtension.heic); final Map jsonMap = event.toJson(); @@ -64,115 +65,45 @@ void main() { test('equals should return true if objects are the same', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 2, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 2048, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 980, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.locked, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); @@ -180,99 +111,44 @@ void main() { test('equals should return false if exposurePointSupported is different', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - false, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.locked, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - false, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); expect(firstEvent == secondEvent, false); }); test('equals should return true if imageExtension is different', () { const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.jpeg); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ImageExtension.heic); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, + imageExtension: ImageExtension.heic); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent(1, 1024, 640, - ExposureMode.auto, true, FocusMode.auto, true, ImageExtension.jpeg); + const CameraInitializedEvent event = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.previewWidth, diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index 61fe66a60ac..c7643064f38 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -186,7 +186,7 @@ void main() { true, FocusMode.auto, true, - ImageExtension.heic, + imageExtension: ImageExtension.heic, )); await initializeFuture; @@ -232,7 +232,7 @@ void main() { true, FocusMode.auto, true, - ImageExtension.heic, + imageExtension: ImageExtension.heic, )); await initializeFuture; @@ -281,7 +281,7 @@ void main() { true, FocusMode.auto, true, - ImageExtension.heic, + imageExtension: ImageExtension.heic, )); await initializeFuture; }); @@ -302,7 +302,7 @@ void main() { true, FocusMode.auto, true, - ImageExtension.heic, + imageExtension: ImageExtension.heic, ); await camera.handleCameraMethodCall( MethodCall('initialized', event.toJson()), cameraId); @@ -454,7 +454,7 @@ void main() { true, FocusMode.auto, true, - ImageExtension.heic, + imageExtension: ImageExtension.heic, ), ); await initializeFuture; From c5a812ad5b95131842b3c0aeb3d84871b9b68cd3 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 13 Oct 2023 21:21:39 -0300 Subject: [PATCH 21/71] rebase main --- .../camera/lib/src/camera_controller.dart | 131 ++-- packages/camera/camera/test/camera_test.dart | 739 +++++------------- .../test/android_camera_test.dart | 345 +++----- .../ios/Classes/CameraPlugin.m | 7 +- .../ios/Classes/CameraProperties.h | 2 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 11 +- .../lib/src/avfoundation_camera.dart | 108 +-- .../test/avfoundation_camera_test.dart | 375 +++------ .../lib/src/events/camera_event.dart | 54 +- .../method_channel/method_channel_camera.dart | 115 +-- .../platform_interface/camera_platform.dart | 19 +- .../lib/src/types/image_extension.dart | 31 +- .../test/events/camera_event_test.dart | 151 ++-- .../method_channel_camera_test.dart | 417 +++------- .../test/types/image_extension_test.dart | 15 +- 15 files changed, 791 insertions(+), 1729 deletions(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index c6ca72a95a4..4ec5982db96 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -183,21 +183,16 @@ class CameraValue { flashMode: flashMode ?? this.flashMode, exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, - exposurePointSupported: - exposurePointSupported ?? this.exposurePointSupported, + exposurePointSupported: exposurePointSupported ?? this.exposurePointSupported, focusPointSupported: focusPointSupported ?? this.focusPointSupported, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: lockedCaptureOrientation == null - ? this.lockedCaptureOrientation - : lockedCaptureOrientation.orNull, - recordingOrientation: recordingOrientation == null - ? this.recordingOrientation - : recordingOrientation.orNull, + lockedCaptureOrientation: + lockedCaptureOrientation == null ? this.lockedCaptureOrientation : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null ? this.recordingOrientation : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, description: description ?? this.description, - previewPauseOrientation: previewPauseOrientation == null - ? this.previewPauseOrientation - : previewPauseOrientation.orNull, + previewPauseOrientation: + previewPauseOrientation == null ? this.previewPauseOrientation : previewPauseOrientation.orNull, ); } @@ -274,8 +269,7 @@ class CameraController extends ValueNotifier { // just called). If the controller has not been initialized at least once, // this value is null. Future? _initializeFuture; - StreamSubscription? - _deviceOrientationSubscription; + StreamSubscription? _deviceOrientationSubscription; /// Checks whether [CameraController.dispose] has completed successfully. /// @@ -307,12 +301,10 @@ class CameraController extends ValueNotifier { _initializeFuture = initializeCompleter.future; try { - final Completer initializeCompleter = - Completer(); + final Completer initializeCompleter = Completer(); - _deviceOrientationSubscription ??= CameraPlatform.instance - .onDeviceOrientationChanged() - .listen((DeviceOrientationChangedEvent event) { + _deviceOrientationSubscription ??= + CameraPlatform.instance.onDeviceOrientationChanged().listen((DeviceOrientationChangedEvent event) { value = value.copyWith( deviceOrientation: event.orientation, ); @@ -324,10 +316,7 @@ class CameraController extends ValueNotifier { enableAudio: enableAudio, ); - _unawaited(CameraPlatform.instance - .onCameraInitialized(_cameraId) - .first - .then((CameraInitializedEvent event) { + _unawaited(CameraPlatform.instance.onCameraInitialized(_cameraId).first.then((CameraInitializedEvent event) { initializeCompleter.complete(event); })); @@ -339,19 +328,16 @@ class CameraController extends ValueNotifier { value = value.copyWith( isInitialized: true, description: description, - previewSize: await initializeCompleter.future - .then((CameraInitializedEvent event) => Size( - event.previewWidth, - event.previewHeight, - )), - exposureMode: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.exposureMode), - focusMode: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.focusMode), - exposurePointSupported: await initializeCompleter.future.then( - (CameraInitializedEvent event) => event.exposurePointSupported), - focusPointSupported: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.focusPointSupported), + previewSize: await initializeCompleter.future.then((CameraInitializedEvent event) => Size( + event.previewWidth, + event.previewHeight, + )), + exposureMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposureMode), + focusMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusMode), + exposurePointSupported: + await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposurePointSupported), + focusPointSupported: + await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusPointSupported), ); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -384,8 +370,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: Optional.of( - value.lockedCaptureOrientation ?? value.deviceOrientation)); + previewPauseOrientation: + Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -398,9 +384,8 @@ class CameraController extends ValueNotifier { } try { await CameraPlatform.instance.resumePreview(_cameraId); - value = value.copyWith( - isPreviewPaused: false, - previewPauseOrientation: const Optional.absent()); + value = + value.copyWith(isPreviewPaused: false, previewPauseOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -436,8 +421,7 @@ class CameraController extends ValueNotifier { } try { value = value.copyWith(isTakingPicture: true); - final XFile file = await CameraPlatform.instance - .takePicture(_cameraId, imageExtension: imageExtension); + final XFile file = await CameraPlatform.instance.takePicture(_cameraId); value = value.copyWith(isTakingPicture: false); return file; } on PlatformException catch (e) { @@ -464,8 +448,7 @@ class CameraController extends ValueNotifier { /// // TODO(bmparr): Add settings for resolution and fps. Future startImageStream(onLatestImageAvailable onAvailable) async { - assert(defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('startImageStream'); if (value.isRecordingVideo) { throw CameraException( @@ -481,9 +464,8 @@ class CameraController extends ValueNotifier { } try { - _imageStreamSubscription = CameraPlatform.instance - .onStreamedFrameAvailable(_cameraId) - .listen((CameraImageData imageData) { + _imageStreamSubscription = + CameraPlatform.instance.onStreamedFrameAvailable(_cameraId).listen((CameraImageData imageData) { onAvailable(CameraImage.fromPlatformInterface(imageData)); }); value = value.copyWith(isStreamingImages: true); @@ -500,8 +482,7 @@ class CameraController extends ValueNotifier { /// The `stopImageStream` method is only available on Android and iOS (other /// platforms won't be supported in current setup). Future stopImageStream() async { - assert(defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('stopImageStream'); if (!value.isStreamingImages) { throw CameraException( @@ -526,8 +507,7 @@ class CameraController extends ValueNotifier { /// /// The video is returned as a [XFile] after calling [stopVideoRecording]. /// Throws a [CameraException] if the capture fails. - Future startVideoRecording( - {onLatestImageAvailable? onAvailable}) async { + Future startVideoRecording({onLatestImageAvailable? onAvailable}) async { _throwIfNotInitialized('startVideoRecording'); if (value.isRecordingVideo) { throw CameraException( @@ -544,13 +524,12 @@ class CameraController extends ValueNotifier { } try { - await CameraPlatform.instance.startVideoCapturing( - VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); + await CameraPlatform.instance.startVideoCapturing(VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, - recordingOrientation: Optional.of( - value.lockedCaptureOrientation ?? value.deviceOrientation), + recordingOrientation: + Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation), isStreamingImages: onAvailable != null); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -574,8 +553,7 @@ class CameraController extends ValueNotifier { } try { - final XFile file = - await CameraPlatform.instance.stopVideoRecording(_cameraId); + final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); value = value.copyWith( isRecordingVideo: false, recordingOrientation: const Optional.absent(), @@ -693,10 +671,8 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the exposure point to it's default /// value. Future setExposurePoint(Offset? point) async { - if (point != null && - (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError( - 'The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); } try { @@ -760,8 +736,7 @@ class CameraController extends ValueNotifier { Future setExposureOffset(double offset) async { _throwIfNotInitialized('setExposureOffset'); // Check if offset is in range - final List range = await Future.wait( - >[getMinExposureOffset(), getMaxExposureOffset()]); + final List range = await Future.wait(>[getMinExposureOffset(), getMaxExposureOffset()]); if (offset < range[0] || offset > range[1]) { throw CameraException( 'exposureOffsetOutOfBounds', @@ -794,11 +769,9 @@ class CameraController extends ValueNotifier { /// If [orientation] is omitted, the current device orientation is used. Future lockCaptureOrientation([DeviceOrientation? orientation]) async { try { - await CameraPlatform.instance.lockCaptureOrientation( - _cameraId, orientation ?? value.deviceOrientation); + await CameraPlatform.instance.lockCaptureOrientation(_cameraId, orientation ?? value.deviceOrientation); value = value.copyWith( - lockedCaptureOrientation: Optional.of( - orientation ?? value.deviceOrientation)); + lockedCaptureOrientation: Optional.of(orientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -818,8 +791,7 @@ class CameraController extends ValueNotifier { Future unlockCaptureOrientation() async { try { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith( - lockedCaptureOrientation: const Optional.absent()); + value = value.copyWith(lockedCaptureOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -830,10 +802,8 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the focus point to it's default /// value. Future setFocusPoint(Offset? point) async { - if (point != null && - (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError( - 'The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); } try { await CameraPlatform.instance.setFocusPoint( @@ -964,9 +934,7 @@ class Optional extends IterableBase { /// /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. Optional transform(S Function(T value) transformer) { - return _value == null - ? Optional.absent() - : Optional.of(transformer(_value as T)); + return _value == null ? Optional.absent() : Optional.of(transformer(_value as T)); } /// Transforms the Optional value. @@ -975,14 +943,11 @@ class Optional extends IterableBase { /// /// Returns [absent()] if the transformer returns `null`. Optional transformNullable(S? Function(T value) transformer) { - return _value == null - ? Optional.absent() - : Optional.fromNullable(transformer(_value as T)); + return _value == null ? Optional.absent() : Optional.fromNullable(transformer(_value as T)); } @override - Iterator get iterator => - isPresent ? [_value as T].iterator : Iterable.empty().iterator; + Iterator get iterator => isPresent ? [_value as T].iterator : Iterable.empty().iterator; /// Delegates to the underlying [value] hashCode. @override @@ -994,8 +959,6 @@ class Optional extends IterableBase { @override String toString() { - return _value == null - ? 'Optional { absent }' - : 'Optional { value: $_value }'; + return _value == null ? 'Optional { absent }' : 'Optional { value: $_value }'; } } diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index 195eaff7187..ece19d0360c 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -15,20 +15,13 @@ import 'package:mockito/mockito.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; List get mockAvailableCameras => [ - const CameraDescription( - name: 'camBack', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), - const CameraDescription( - name: 'camFront', - lensDirection: CameraLensDirection.front, - sensorOrientation: 180), + const CameraDescription(name: 'camBack', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription(name: 'camFront', lensDirection: CameraLensDirection.front, sensorOrientation: 180), ]; int get mockInitializeCamera => 13; -CameraInitializedEvent get mockOnCameraInitializedEvent => - const CameraInitializedEvent( +CameraInitializedEvent get mockOnCameraInitializedEvent => const CameraInitializedEvent( 13, 75, 75, @@ -36,7 +29,6 @@ CameraInitializedEvent get mockOnCameraInitializedEvent => true, FocusMode.auto, true, - ImageExtension.jpeg, ); DeviceOrientationChangedEvent get mockOnDeviceOrientationChangedEvent => @@ -44,8 +36,7 @@ DeviceOrientationChangedEvent get mockOnDeviceOrientationChangedEvent => CameraClosingEvent get mockOnCameraClosingEvent => const CameraClosingEvent(13); -CameraErrorEvent get mockOnCameraErrorEvent => - const CameraErrorEvent(13, 'closing'); +CameraErrorEvent get mockOnCameraErrorEvent => const CameraErrorEvent(13, 'closing'); XFile mockTakePicture = XFile('foo/bar.png'); @@ -57,8 +48,7 @@ void main() { WidgetsFlutterBinding.ensureInitialized(); group('camera', () { - test('debugCheckIsDisposed should not throw assertion error when disposed', - () { + test('debugCheckIsDisposed should not throw assertion error when disposed', () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -70,8 +60,7 @@ void main() { expect(controller.debugCheckIsDisposed, returnsNormally); }); - test('debugCheckIsDisposed should throw assertion error when not disposed', - () { + test('debugCheckIsDisposed should throw assertion error when not disposed', () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -100,10 +89,7 @@ void main() { test('Can be initialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -114,10 +100,7 @@ void main() { test('can be disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -132,10 +115,7 @@ void main() { test('initialize() throws CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -156,13 +136,9 @@ void main() { ))); }); - test('initialize() throws $CameraException on $PlatformException ', - () async { + test('initialize() throws $CameraException on $PlatformException ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); mockPlatformException = true; @@ -180,21 +156,15 @@ void main() { test('initialize() sets imageFormat', () async { debugDefaultTargetPlatformOverride = TargetPlatform.android; final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max, imageFormatGroup: ImageFormatGroup.yuv420, ); await cameraController.initialize(); - verify(CameraPlatform.instance - .initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)) - .called(1); + verify(CameraPlatform.instance.initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)).called(1); }); - test('setDescription waits for initialize before calling dispose', - () async { + test('setDescription waits for initialize before calling dispose', () async { final CameraController cameraController = CameraController( const CameraDescription( name: 'cam', @@ -216,10 +186,7 @@ void main() { unawaited(cameraController.initialize()); final Future setDescriptionFuture = cameraController.setDescription( - const CameraDescription( - name: 'cam2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 90), + const CameraDescription(name: 'cam2', lensDirection: CameraLensDirection.front, sensorOrientation: 90), ); verifyNever(CameraPlatform.instance.dispose(mockInitializeCamera)); @@ -231,10 +198,7 @@ void main() { test('prepareForVideoRecording() calls $CameraPlatform ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -245,10 +209,7 @@ void main() { test('takePicture() throws $CameraException when uninitialized ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( cameraController.takePicture(), @@ -268,18 +229,13 @@ void main() { ); }); - test('takePicture() throws $CameraException when takePicture is true', - () async { + test('takePicture() throws $CameraException when takePicture is true', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isTakingPicture: true); + cameraController.value = cameraController.value.copyWith(isTakingPicture: true); expect( cameraController.takePicture(), throwsA(isA().having( @@ -291,10 +247,7 @@ void main() { test('takePicture() returns $XFile', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); final XFile xFile = await cameraController.takePicture(); @@ -302,13 +255,9 @@ void main() { expect(xFile.path, mockTakePicture.path); }); - test('takePicture() throws $CameraException on $PlatformException', - () async { + test('takePicture() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -323,13 +272,9 @@ void main() { mockPlatformException = false; }); - test('startVideoRecording() throws $CameraException when uninitialized', - () async { + test('startVideoRecording() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -349,19 +294,14 @@ void main() { ), ); }); - test('startVideoRecording() throws $CameraException when recording videos', - () async { + test('startVideoRecording() throws $CameraException when recording videos', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isRecordingVideo: true); + cameraController.value = cameraController.value.copyWith(isRecordingVideo: true); expect( cameraController.startVideoRecording(), @@ -372,13 +312,9 @@ void main() { ))); }); - test('getMaxZoomLevel() throws $CameraException when uninitialized', - () async { + test('getMaxZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -401,10 +337,7 @@ void main() { test('getMaxZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -428,29 +361,20 @@ void main() { ); }); - test( - 'getMaxZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('getMaxZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) - .thenThrow(CameraException( + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMaxZoomLevel, - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -459,27 +383,19 @@ void main() { test('getMaxZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) - .thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMaxZoomLevel(); expect(maxZoomLevel, 42.0); }); - test('getMinZoomLevel() throws $CameraException when uninitialized', - () async { + test('getMinZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -502,10 +418,7 @@ void main() { test('getMinZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -529,29 +442,20 @@ void main() { ); }); - test( - 'getMinZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('getMinZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) - .thenThrow(CameraException( + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMinZoomLevel, - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -560,15 +464,11 @@ void main() { test('getMinZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) - .thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMinZoomLevel(); expect(maxZoomLevel, 42.0); @@ -576,10 +476,7 @@ void main() { test('setZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -602,10 +499,7 @@ void main() { test('setZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -629,29 +523,20 @@ void main() { ); }); - test( - 'setZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('setZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) - .thenThrow(CameraException( + when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( () => cameraController.setZoomLevel(42), - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -660,52 +545,35 @@ void main() { reset(CameraPlatform.instance); }); - test( - 'setZoomLevel() completes and calls method channel with correct value.', - () async { + test('setZoomLevel() completes and calls method channel with correct value.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setZoomLevel(42.0); - verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) - .called(1); + verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).called(1); }); test('setFlashMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setFlashMode(FlashMode.always); - verify(CameraPlatform.instance - .setFlashMode(cameraController.cameraId, FlashMode.always)) - .called(1); + verify(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).called(1); }); - test('setFlashMode() throws $CameraException on $PlatformException', - () async { + test('setFlashMode() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .setFlashMode(cameraController.cameraId, FlashMode.always)) - .thenThrow( + when(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -723,33 +591,22 @@ void main() { test('setExposureMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposureMode(ExposureMode.auto); - verify(CameraPlatform.instance - .setExposureMode(cameraController.cameraId, ExposureMode.auto)) - .called(1); + verify(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).called(1); }); - test('setExposureMode() throws $CameraException on $PlatformException', - () async { + test('setExposureMode() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .setExposureMode(cameraController.cameraId, ExposureMode.auto)) - .thenThrow( + when(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -767,32 +624,23 @@ void main() { test('setExposurePoint() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposurePoint(const Offset(0.5, 0.5)); - verify(CameraPlatform.instance.setExposurePoint( - cameraController.cameraId, const Point(0.5, 0.5))) + verify(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) .called(1); }); - test('setExposurePoint() throws $CameraException on $PlatformException', - () async { + test('setExposurePoint() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposurePoint( - cameraController.cameraId, const Point(0.5, 0.5))) + when(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -811,37 +659,25 @@ void main() { test('getMinExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getMinExposureOffset(); - verify(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).called(1); }); - test('getMinExposureOffset() throws $CameraException on $PlatformException', - () async { + test('getMinExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -859,37 +695,25 @@ void main() { test('getMaxExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(1.0)); await cameraController.getMaxExposureOffset(); - verify(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).called(1); }); - test('getMaxExposureOffset() throws $CameraException on $PlatformException', - () async { + test('getMaxExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -907,38 +731,25 @@ void main() { test('getExposureOffsetStepSize() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getExposureOffsetStepSize(); - verify(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).called(1); }); - test( - 'getExposureOffsetStepSize() throws $CameraException on $PlatformException', - () async { + test('getExposureOffsetStepSize() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -956,53 +767,28 @@ void main() { test('setExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenAnswer((_) async => 1.0); await cameraController.setExposureOffset(1.0); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).called(1); }); - test('setExposureOffset() throws $CameraException on $PlatformException', - () async { + test('setExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .thenThrow( + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -1018,34 +804,17 @@ void main() { ))); }); - test( - 'setExposureOffset() throws $CameraException when offset is out of bounds', - () async { + test('setExposureOffset() throws $CameraException when offset is out of bounds', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 2.0)) - .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).thenAnswer((_) async => 0.0); expect( cameraController.setExposureOffset(3.0), @@ -1066,56 +835,27 @@ void main() { await cameraController.setExposureOffset(-1.0); await cameraController.setExposureOffset(2.0); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .called(1); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.0)) - .called(1); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 2.0)) - .called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).called(1); }); test('setExposureOffset() rounds offset to nearest step', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.2); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 1.2); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 0.4); - - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.2)) - .thenAnswer((_) async => -1.2); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.8)) - .thenAnswer((_) async => -0.8); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.4)) - .thenAnswer((_) async => -0.4); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.4)) - .thenAnswer((_) async => 0.4); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.8)) - .thenAnswer((_) async => 0.8); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.2)) - .thenAnswer((_) async => 1.2); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.2); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 1.2); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 0.4); + + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.2)).thenAnswer((_) async => -1.2); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).thenAnswer((_) async => -0.8); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).thenAnswer((_) async => -0.4); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).thenAnswer((_) async => 0.4); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).thenAnswer((_) async => 0.8); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.2)).thenAnswer((_) async => 1.2); await cameraController.setExposureOffset(1.2); await cameraController.setExposureOffset(-1.2); @@ -1134,97 +874,62 @@ void main() { await cameraController.setExposureOffset(-0.6); await cameraController.setExposureOffset(-0.7); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.8)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.8)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.4)) - .called(4); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.4)) - .called(4); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).called(4); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).called(4); }); test('pausePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value - .copyWith(deviceOrientation: DeviceOrientation.portraitUp); + cameraController.value = cameraController.value.copyWith(deviceOrientation: DeviceOrientation.portraitUp); await cameraController.pausePreview(); - verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)).called(1); expect(cameraController.value.isPreviewPaused, equals(true)); - expect(cameraController.value.previewPauseOrientation, - DeviceOrientation.portraitUp); + expect(cameraController.value.previewPauseOrientation, DeviceOrientation.portraitUp); }); - test('pausePreview() does not call $CameraPlatform when already paused', - () async { + test('pausePreview() does not call $CameraPlatform when already paused', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); await cameraController.pausePreview(); - verifyNever( - CameraPlatform.instance.pausePreview(cameraController.cameraId)); + verifyNever(CameraPlatform.instance.pausePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(true)); }); - test( - 'pausePreview() sets previewPauseOrientation according to locked orientation', - () async { + test('pausePreview() sets previewPauseOrientation according to locked orientation', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); cameraController.value = cameraController.value.copyWith( isPreviewPaused: false, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: - Optional.of(DeviceOrientation.landscapeRight)); + lockedCaptureOrientation: Optional.of(DeviceOrientation.landscapeRight)); await cameraController.pausePreview(); - expect(cameraController.value.deviceOrientation, - equals(DeviceOrientation.portraitUp)); - expect(cameraController.value.previewPauseOrientation, - equals(DeviceOrientation.landscapeRight)); + expect(cameraController.value.deviceOrientation, equals(DeviceOrientation.portraitUp)); + expect(cameraController.value.previewPauseOrientation, equals(DeviceOrientation.landscapeRight)); }); - test('pausePreview() throws $CameraException on $PlatformException', - () async { + test('pausePreview() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.pausePreview(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.pausePreview(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1242,54 +947,37 @@ void main() { test('resumePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); await cameraController.resumePreview(); - verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)).called(1); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() does not call $CameraPlatform when not paused', - () async { + test('resumePreview() does not call $CameraPlatform when not paused', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: false); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: false); await cameraController.resumePreview(); - verifyNever( - CameraPlatform.instance.resumePreview(cameraController.cameraId)); + verifyNever(CameraPlatform.instance.resumePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() throws $CameraException on $PlatformException', - () async { + test('resumePreview() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); - when(CameraPlatform.instance.resumePreview(cameraController.cameraId)) - .thenThrow( + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + when(CameraPlatform.instance.resumePreview(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1307,41 +995,28 @@ void main() { test('lockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.lockCaptureOrientation(); - expect(cameraController.value.lockedCaptureOrientation, - equals(DeviceOrientation.portraitUp)); - await cameraController - .lockCaptureOrientation(DeviceOrientation.landscapeRight); - expect(cameraController.value.lockedCaptureOrientation, - equals(DeviceOrientation.landscapeRight)); - - verify(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.portraitUp)) + expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.portraitUp)); + await cameraController.lockCaptureOrientation(DeviceOrientation.landscapeRight); + expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.landscapeRight)); + + verify(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) .called(1); - verify(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.landscapeRight)) + verify(CameraPlatform.instance + .lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.landscapeRight)) .called(1); }); - test( - 'lockCaptureOrientation() throws $CameraException on $PlatformException', - () async { + test('lockCaptureOrientation() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.portraitUp)) + when(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -1360,34 +1035,22 @@ void main() { test('unlockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.unlockCaptureOrientation(); expect(cameraController.value.lockedCaptureOrientation, equals(null)); - verify(CameraPlatform.instance - .unlockCaptureOrientation(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).called(1); }); - test( - 'unlockCaptureOrientation() throws $CameraException on $PlatformException', - () async { + test('unlockCaptureOrientation() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .unlockCaptureOrientation(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1405,13 +1068,12 @@ void main() { }); } -class MockCameraPlatform extends Mock - with MockPlatformInterfaceMixin - implements CameraPlatform { +class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements CameraPlatform { @override Future initializeCamera( int? cameraId, { ImageFormatGroup? imageFormatGroup = ImageFormatGroup.unknown, + ImageExtension imageExtension = ImageExtension.jpeg, }) async => super.noSuchMethod(Invocation.method( #initializeCamera, @@ -1427,8 +1089,7 @@ class MockCameraPlatform extends Mock } @override - Future> availableCameras() => - Future>.value(mockAvailableCameras); + Future> availableCameras() => Future>.value(mockAvailableCameras); @override Future createCamera( @@ -1449,17 +1110,14 @@ class MockCameraPlatform extends Mock Stream.value(mockOnCameraClosingEvent); @override - Stream onCameraError(int cameraId) => - Stream.value(mockOnCameraErrorEvent); + Stream onCameraError(int cameraId) => Stream.value(mockOnCameraErrorEvent); @override Stream onDeviceOrientationChanged() => - Stream.value( - mockOnDeviceOrientationChangedEvent); + Stream.value(mockOnDeviceOrientationChangedEvent); @override - Future takePicture(int cameraId, - {ImageExtension imageExtension = ImageExtension.jpeg}) => + Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) => mockPlatformException ? throw PlatformException(code: 'foo', message: 'bar') : Future.value(mockTakePicture); @@ -1469,34 +1127,29 @@ class MockCameraPlatform extends Mock super.noSuchMethod(Invocation.method(#prepareForVideoRecording, null)); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) => + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) => Future.value(mockVideoRecordingXFile); @override Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } @override - Future lockCaptureOrientation( - int? cameraId, DeviceOrientation? orientation) async => - super.noSuchMethod(Invocation.method( - #lockCaptureOrientation, [cameraId, orientation])); + Future lockCaptureOrientation(int? cameraId, DeviceOrientation? orientation) async => + super.noSuchMethod(Invocation.method(#lockCaptureOrientation, [cameraId, orientation])); @override Future unlockCaptureOrientation(int? cameraId) async => - super.noSuchMethod( - Invocation.method(#unlockCaptureOrientation, [cameraId])); + super.noSuchMethod(Invocation.method(#unlockCaptureOrientation, [cameraId])); @override Future pausePreview(int? cameraId) async => super.noSuchMethod(Invocation.method(#pausePreview, [cameraId])); @override - Future resumePreview(int? cameraId) async => super - .noSuchMethod(Invocation.method(#resumePreview, [cameraId])); + Future resumePreview(int? cameraId) async => + super.noSuchMethod(Invocation.method(#resumePreview, [cameraId])); @override Future getMaxZoomLevel(int? cameraId) async => super.noSuchMethod( @@ -1512,48 +1165,40 @@ class MockCameraPlatform extends Mock @override Future setZoomLevel(int? cameraId, double? zoom) async => - super.noSuchMethod( - Invocation.method(#setZoomLevel, [cameraId, zoom])); + super.noSuchMethod(Invocation.method(#setZoomLevel, [cameraId, zoom])); @override Future setFlashMode(int? cameraId, FlashMode? mode) async => - super.noSuchMethod( - Invocation.method(#setFlashMode, [cameraId, mode])); + super.noSuchMethod(Invocation.method(#setFlashMode, [cameraId, mode])); @override Future setExposureMode(int? cameraId, ExposureMode? mode) async => - super.noSuchMethod( - Invocation.method(#setExposureMode, [cameraId, mode])); + super.noSuchMethod(Invocation.method(#setExposureMode, [cameraId, mode])); @override Future setExposurePoint(int? cameraId, Point? point) async => - super.noSuchMethod( - Invocation.method(#setExposurePoint, [cameraId, point])); + super.noSuchMethod(Invocation.method(#setExposurePoint, [cameraId, point])); @override - Future getMinExposureOffset(int? cameraId) async => - super.noSuchMethod( + Future getMinExposureOffset(int? cameraId) async => super.noSuchMethod( Invocation.method(#getMinExposureOffset, [cameraId]), returnValue: Future.value(0.0), ) as Future; @override - Future getMaxExposureOffset(int? cameraId) async => - super.noSuchMethod( + Future getMaxExposureOffset(int? cameraId) async => super.noSuchMethod( Invocation.method(#getMaxExposureOffset, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future getExposureOffsetStepSize(int? cameraId) async => - super.noSuchMethod( + Future getExposureOffsetStepSize(int? cameraId) async => super.noSuchMethod( Invocation.method(#getExposureOffsetStepSize, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future setExposureOffset(int? cameraId, double? offset) async => - super.noSuchMethod( + Future setExposureOffset(int? cameraId, double? offset) async => super.noSuchMethod( Invocation.method(#setExposureOffset, [cameraId, offset]), returnValue: Future.value(1.0), ) as Future; diff --git a/packages/camera/camera_android/test/android_camera_test.dart b/packages/camera/camera_android/test/android_camera_test.dart index 5ed750e2d1e..a0ef9c9c71c 100644 --- a/packages/camera/camera_android/test/android_camera_test.dart +++ b/packages/camera/camera_android/test/android_camera_test.dart @@ -32,13 +32,11 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await TestDefaultBinaryMessengerBinding - .instance.defaultBinaryMessenger + final ByteData? response = await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .handlePlatformMessage( AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(const MethodCall( - 'orientation_changed', - {'orientation': 'portraitDown'})), + const StandardMethodCodec().encodeMethodCall( + const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), (ByteData? data) {}); expect(response, null); }); @@ -46,22 +44,18 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AndroidCamera camera = AndroidCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -69,18 +63,13 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -102,16 +91,13 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -133,10 +119,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -160,10 +144,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -175,15 +156,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -216,6 +196,7 @@ void main() { arguments: { 'cameraId': 1, 'imageFormatGroup': 'unknown', + 'imageExtension': 'jpeg', }, ), ]); @@ -223,13 +204,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( @@ -303,10 +283,8 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -318,8 +296,7 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -330,24 +307,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -361,19 +331,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -386,20 +351,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -412,21 +371,17 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .handlePlatformMessage( - AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - MethodCall('orientation_changed', event.toJson())), - null); + await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage( + AndroidCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -475,20 +430,11 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -504,21 +450,17 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -532,29 +474,23 @@ void main() { camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); // Assert expect(channel.log, [ - isMethodCall('takePicture', arguments: { - 'cameraId': cameraId, - 'imageExtension': 'jpeg', - }), + isMethodCall('takePicture', arguments: {'cameraId': cameraId}), ]); expect(file.path, '/test/path.jpg'); }); @@ -595,8 +531,7 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -619,9 +554,7 @@ void main() { ]); }); - test( - 'Should pass enableStream if callback is passed when starting recording a video', - () async { + test('Should pass enableStream if callback is passed when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -630,8 +563,7 @@ void main() { // Act await camera.startVideoCapturing( - VideoCaptureOptions(cameraId, - streamCallback: (CameraImageData imageData) {}), + VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {}), ); // Assert @@ -705,20 +637,17 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = CameraDescription( - name: 'Test2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 0); + const CameraDescription camera2Description = + CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -737,18 +666,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -765,12 +686,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -787,18 +704,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -810,8 +719,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -830,8 +738,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -894,12 +801,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -916,18 +819,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -940,13 +835,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final AndroidCamera camera = AndroidCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -1000,13 +892,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -1023,8 +913,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1035,15 +924,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1059,8 +945,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1076,8 +961,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1093,8 +977,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1109,9 +992,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1132,9 +1014,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index 1baa66ecd0d..f4f99b3151c 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -153,7 +153,10 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call NSUInteger cameraId = ((NSNumber *)argsMap[@"cameraId"]).unsignedIntegerValue; if ([@"initialize" isEqualToString:call.method]) { NSString *videoFormatValue = ((NSString *)argsMap[@"imageFormatGroup"]); + NSString *imageExtension = ((NSString *)argsMap[@"imageExtension"]); + [_camera setVideoFormat:FLTGetVideoFormatFromString(videoFormatValue)]; + [_camera setImageExtension:FLTGetImageExtensionFromString(imageExtension)]; __weak CameraPlugin *weakSelf = self; _camera.onFrameAvailable = ^{ @@ -184,9 +187,7 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call [_camera start]; [result sendSuccess]; }else if ([@"takePicture" isEqualToString:call.method]) { - NSString *formatString = call.arguments[@"imageExtension"]; - - [_camera captureToFile:result imageExtensionString:formatString]; + [_camera captureToFile:result]; } else if ([@"dispose" isEqualToString:call.method]) { [_registry unregisterTexture:cameraId]; diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index b0cf45be7a5..a9fdd0a703e 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -140,6 +140,6 @@ typedef NS_ENUM(NSInteger, ImageExtension) { /** * Gets ImageExtension from its string representation. */ -extern ImageExtension FLTGetImageExtensionForString(NSString *imageExtensionString); +extern ImageExtension FLTGetImageExtensionFromString(NSString *imageExtensionString); NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index e7b67ff5b6a..b54862a8cad 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -144,6 +144,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName _deviceOrientation = orientation; _videoFormat = kCVPixelFormatType_32BGRA; _inProgressSavePhotoDelegates = [NSMutableDictionary dictionary]; + _imageExtension = ImageExtensionJPEG; // To limit memory consumption, limit the number of frames pending processing. // After some testing, 4 was determined to be the best maximum value. @@ -218,6 +219,10 @@ - (void)setVideoFormat:(OSType)videoFormat { @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)}; } +- (void)setImageExtension:(ImageExtension *)imageExtension { + _imageExtension = imageExtension; +} + - (void)setDeviceOrientation:(UIDeviceOrientation)orientation { if (_deviceOrientation == orientation) { return; @@ -252,16 +257,14 @@ - (void)updateOrientation:(UIDeviceOrientation)orientation } } -- (void)captureToFile:(FLTThreadSafeFlutterResult *)result imageExtensionString:(NSString *)imageExtensionString { - ImageExtension imageExtension = FLTGetImageExtensionForString(imageExtensionString); - +- (void)captureToFile:(FLTThreadSafeFlutterResult *)result { AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; NSString *extension = @"jpg"; if (_resolutionPreset == FLTResolutionPresetMax) { [settings setHighResolutionPhotoEnabled:YES]; } - if (imageExtension == ImageExtensionHEIC && @available(iOS 11.0, *)) { + if (_imageExtension == ImageExtensionHEIC && @available(iOS 11.0, *)) { if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{ AVVideoCodecKey : AVVideoCodecTypeHEVC }]; extension = @"heic"; diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 8b4ef0b9eda..0df098f27e9 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,8 +14,7 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = - MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -29,8 +28,7 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = - 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -40,16 +38,14 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = - _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -65,14 +61,13 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -81,8 +76,7 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -98,12 +92,9 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -117,12 +108,11 @@ class AVFoundationCamera extends CameraPlatform { Future initializeCamera( int cameraId, { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, + ImageExtension imageExtension = ImageExtension.jpeg, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel( - 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -137,6 +127,7 @@ class AVFoundationCamera extends CameraPlatform { { 'cameraId': cameraId, 'imageFormatGroup': imageFormatGroup.name(), + 'imageExtension': _serializeImageExtension(imageExtension), }, ).catchError( // TODO(srawlins): This should return a value of the future's type. This @@ -199,8 +190,7 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream - .whereType(); + return _deviceEventStreamController.stream.whereType(); } @override @@ -210,10 +200,7 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -226,14 +213,10 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, - {ImageExtension imageExtension = ImageExtension.jpeg}) async { + Future takePicture(int cameraId) async { final String? path = await _channel.invokeMethod( 'takePicture', - { - 'cameraId': cameraId, - 'imageExtension': _serializeImageExtension(imageExtension) - }, + {'cameraId': cameraId}, ); if (path == null) { @@ -247,14 +230,11 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -299,22 +279,18 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { - _frameStreamController = - _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController( - {Function()? onListen}) { + StreamController _createStreamController({Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -333,17 +309,14 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -355,13 +328,11 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -370,8 +341,7 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -439,8 +409,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -516,8 +485,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -592,8 +560,8 @@ class AVFoundationCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -617,8 +585,6 @@ class AVFoundationCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, - imageExtension: - deserializeImageExtension(arguments['imageExtension']! as String), )); break; case 'resolution_changed': @@ -639,9 +605,7 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 2558da3919e..89ec2a8c93c 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -32,37 +32,31 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(const MethodCall( - 'orientation_changed', - {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AVFoundationCamera camera = AVFoundationCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -70,18 +64,13 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -103,16 +92,13 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -134,10 +120,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -161,10 +145,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -176,15 +157,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + 'imageExtension': 'jpeg', + }, + 'initialize': null + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -217,6 +198,7 @@ void main() { arguments: { 'cameraId': 1, 'imageFormatGroup': 'unknown', + 'imageExtension': 'jpeg', }, ), ]); @@ -224,13 +206,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( @@ -304,10 +285,8 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -319,8 +298,7 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -331,24 +309,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -362,19 +333,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -387,20 +353,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -413,22 +373,17 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -477,23 +432,14 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange // This deliberately uses 'dynamic' since that's what actual platform // channel results will be, so using typed mock data could mask type // handling bugs in the code under test. final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -509,21 +455,17 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -537,20 +479,16 @@ void main() { camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should take a picture and return an XFile instance with jpeg format', - () async { + test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -559,33 +497,11 @@ void main() { expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, - 'imageExtension': 'jpeg', }), ]); expect(file.path, '/test/path.jpg'); }); - test('Should take a picture and return an XFile instance with heic format', - () async { - // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.heic'}); - - // Act - final XFile file = await camera.takePicture(cameraId, - imageExtension: ImageExtension.heic); - - // Assert - expect(channel.log, [ - isMethodCall('takePicture', arguments: { - 'cameraId': cameraId, - 'imageExtension': 'heic', - }), - ]); - expect(file.path, '/test/path.heic'); - }); - test('Should prepare for video recording', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( @@ -622,8 +538,7 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -646,9 +561,7 @@ void main() { ]); }); - test( - 'Should pass enableStream if callback is passed when starting recording a video', - () async { + test('Should pass enableStream if callback is passed when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -656,8 +569,7 @@ void main() { ); // Act - await camera.startVideoCapturing(VideoCaptureOptions(cameraId, - streamCallback: (CameraImageData imageData) {})); + await camera.startVideoCapturing(VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {})); // Assert expect(channel.log, [ @@ -730,20 +642,17 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = CameraDescription( - name: 'Test2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 0); + const CameraDescription camera2Description = + CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -762,18 +671,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -790,12 +691,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -812,18 +709,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -835,8 +724,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -855,8 +743,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -919,12 +806,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -941,18 +824,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -965,13 +840,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final AVFoundationCamera camera = AVFoundationCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -1025,13 +897,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -1048,8 +918,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1060,15 +929,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1084,8 +950,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1101,8 +966,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1118,8 +982,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1134,9 +997,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1157,9 +1019,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart index 8a342cc6279..31a819e97e1 100644 --- a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart +++ b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart @@ -34,10 +34,7 @@ abstract class CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || - other is CameraEvent && - runtimeType == other.runtimeType && - cameraId == other.cameraId; + identical(this, other) || other is CameraEvent && runtimeType == other.runtimeType && cameraId == other.cameraId; @override int get hashCode => cameraId.hashCode; @@ -51,14 +48,14 @@ class CameraInitializedEvent extends CameraEvent { /// The `previewWidth` represents the width of the generated preview in pixels. /// The `previewHeight` represents the height of the generated preview in pixels. const CameraInitializedEvent( - super.cameraId, - this.previewWidth, - this.previewHeight, - this.exposureMode, - this.exposurePointSupported, - this.focusMode, - this.focusPointSupported, - {this.imageExtension = ImageExtension.jpeg}); + super.cameraId, + this.previewWidth, + this.previewHeight, + this.exposureMode, + this.exposurePointSupported, + this.focusMode, + this.focusPointSupported, + ); /// Converts the supplied [Map] to an instance of the [CameraInitializedEvent] /// class. @@ -66,12 +63,9 @@ class CameraInitializedEvent extends CameraEvent { : previewWidth = json['previewWidth']! as double, previewHeight = json['previewHeight']! as double, exposureMode = deserializeExposureMode(json['exposureMode']! as String), - exposurePointSupported = - (json['exposurePointSupported'] as bool?) ?? false, + exposurePointSupported = (json['exposurePointSupported'] as bool?) ?? false, focusMode = deserializeFocusMode(json['focusMode']! as String), focusPointSupported = (json['focusPointSupported'] as bool?) ?? false, - imageExtension = - deserializeImageExtension(json['imageExtension']! as String), super(json['cameraId']! as int); /// The width of the preview in pixels. @@ -92,9 +86,6 @@ class CameraInitializedEvent extends CameraEvent { /// Whether setting focus points is supported. final bool focusPointSupported; - /// The default image extension - final ImageExtension imageExtension; - /// Converts the [CameraInitializedEvent] instance into a [Map] instance that /// can be serialized to JSON. Map toJson() => { @@ -105,7 +96,6 @@ class CameraInitializedEvent extends CameraEvent { 'exposurePointSupported': exposurePointSupported, 'focusMode': serializeFocusMode(focusMode), 'focusPointSupported': focusPointSupported, - 'imageExtension': serializeImageExtension(imageExtension), }; @override @@ -119,8 +109,7 @@ class CameraInitializedEvent extends CameraEvent { exposureMode == other.exposureMode && exposurePointSupported == other.exposurePointSupported && focusMode == other.focusMode && - focusPointSupported == other.focusPointSupported && - imageExtension == other.imageExtension; + focusPointSupported == other.focusPointSupported; @override int get hashCode => Object.hash( @@ -131,7 +120,6 @@ class CameraInitializedEvent extends CameraEvent { exposurePointSupported, focusMode, focusPointSupported, - imageExtension, ); } @@ -190,8 +178,7 @@ class CameraClosingEvent extends CameraEvent { /// Converts the supplied [Map] to an instance of the [CameraClosingEvent] /// class. - CameraClosingEvent.fromJson(Map json) - : super(json['cameraId']! as int); + CameraClosingEvent.fromJson(Map json) : super(json['cameraId']! as int); /// Converts the [CameraClosingEvent] instance into a [Map] instance that can /// be serialized to JSON. @@ -201,10 +188,7 @@ class CameraClosingEvent extends CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || - super == other && - other is CameraClosingEvent && - runtimeType == other.runtimeType; + identical(this, other) || super == other && other is CameraClosingEvent && runtimeType == other.runtimeType; @override // This is here even though it just calls super to make it less likely that @@ -262,9 +246,8 @@ class VideoRecordedEvent extends CameraEvent { /// class. VideoRecordedEvent.fromJson(Map json) : file = XFile(json['path']! as String), - maxVideoDuration = json['maxVideoDuration'] != null - ? Duration(milliseconds: json['maxVideoDuration'] as int) - : null, + maxVideoDuration = + json['maxVideoDuration'] != null ? Duration(milliseconds: json['maxVideoDuration'] as int) : null, super(json['cameraId']! as int); /// XFile of the recorded video. @@ -275,11 +258,8 @@ class VideoRecordedEvent extends CameraEvent { /// Converts the [VideoRecordedEvent] instance into a [Map] instance that can be /// serialized to JSON. - Map toJson() => { - 'cameraId': cameraId, - 'path': file.path, - 'maxVideoDuration': maxVideoDuration?.inMilliseconds - }; + Map toJson() => + {'cameraId': cameraId, 'path': file.path, 'maxVideoDuration': maxVideoDuration?.inMilliseconds}; @override bool operator ==(Object other) => diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 583b8e42417..a7949d9b0e9 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,10 +20,8 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler( - (MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -36,8 +34,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -47,8 +44,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = - StreamController.broadcast(); + final StreamController deviceEventStreamController = StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -57,14 +53,13 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -73,8 +68,7 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -90,12 +84,9 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -109,12 +100,11 @@ class MethodChannelCamera extends CameraPlatform { Future initializeCamera( int cameraId, { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, + ImageExtension imageExtension = ImageExtension.jpeg, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -129,6 +119,7 @@ class MethodChannelCamera extends CameraPlatform { { 'cameraId': cameraId, 'imageFormatGroup': imageFormatGroup.name(), + 'imageExtension': imageExtension.name(), }, ).catchError( // TODO(srawlins): This should return a value of the future's type. This @@ -191,8 +182,7 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream - .whereType(); + return deviceEventStreamController.stream.whereType(); } @override @@ -202,10 +192,7 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -218,14 +205,10 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future takePicture(int cameraId, - {ImageExtension imageExtension = ImageExtension.jpeg}) async { + Future takePicture(int cameraId) async { final String? path = await _channel.invokeMethod( 'takePicture', - { - 'cameraId': cameraId, - 'imageExtension': _serializeImageExtension(imageExtension) - }, + {'cameraId': cameraId}, ); if (path == null) { @@ -239,14 +222,11 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -290,21 +270,18 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController( - {Function()? onListen}) { + StreamController _installStreamController({Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -324,10 +301,8 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -335,8 +310,7 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -348,13 +322,11 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -363,8 +335,7 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -432,8 +403,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -509,8 +479,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -556,16 +525,6 @@ class MethodChannelCamera extends CameraPlatform { } } - /// Returns the image extension as a String. - String _serializeImageExtension(ImageExtension imageExtension) { - switch (imageExtension) { - case ImageExtension.jpeg: - return 'jpeg'; - case ImageExtension.heic: - return 'heic'; - } - } - /// Converts messages received from the native platform into device events. /// /// This is only exposed for test purposes. It shouldn't be used by clients of @@ -574,8 +533,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -599,8 +558,6 @@ class MethodChannelCamera extends CameraPlatform { arguments['exposurePointSupported']! as bool, deserializeFocusMode(arguments['focusMode']! as String), arguments['focusPointSupported']! as bool, - imageExtension: - deserializeImageExtension(arguments['imageExtension']! as String), )); break; case 'resolution_changed': @@ -621,9 +578,7 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 3945d3174a3..18118b77fb7 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -64,6 +64,7 @@ abstract class CameraPlatform extends PlatformInterface { Future initializeCamera( int cameraId, { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, + ImageExtension imageExtension = ImageExtension.jpeg, }) { throw UnimplementedError('initializeCamera() is not implemented.'); } @@ -99,13 +100,11 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError( - 'onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation( - int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -115,8 +114,7 @@ abstract class CameraPlatform extends PlatformInterface { } /// Captures an image and returns the file where it was saved. - Future takePicture(int cameraId, - {ImageExtension imageExtension = ImageExtension.jpeg}) { + Future takePicture(int cameraId) { throw UnimplementedError('takePicture() is not implemented.'); } @@ -143,8 +141,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -172,8 +169,7 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -272,8 +268,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError( - 'setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart b/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart index 80ff38241cc..328080e08a8 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart @@ -12,24 +12,17 @@ enum ImageExtension { heic, } -/// Returns the image extension as a String. -String serializeImageExtension(ImageExtension imageExtension) { - switch (imageExtension) { - case ImageExtension.jpeg: - return 'jpeg'; - case ImageExtension.heic: - return 'heic'; - } -} - -/// Returns the image extension as a String. -ImageExtension deserializeImageExtension(String str) { - switch (str) { - case 'jpeg': - return ImageExtension.jpeg; - case 'heic': - return ImageExtension.heic; - default: - throw ArgumentError('"$str" is not a valid image extension.'); +/// Extension on [ImageExtension] to stringify the enum +extension ImageExtensionName on ImageExtension { + /// returns a String value for [ImageExtension] + /// returns 'jpeg' if platform is not supported + /// or if [ImageExtension] is not supported for the platform + String name() { + switch (this) { + case ImageExtension.jpeg: + return 'jpeg'; + case ImageExtension.heic: + return 'heic'; + } } } diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index e2028d60641..4068150ff5d 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -20,12 +20,10 @@ void main() { expect(event.focusMode, FocusMode.auto); expect(event.exposurePointSupported, true); expect(event.focusPointSupported, true); - expect(event.imageExtension, ImageExtension.jpeg); }); test('fromJson should initialize all properties', () { - final CameraInitializedEvent event = - CameraInitializedEvent.fromJson(const { + final CameraInitializedEvent event = CameraInitializedEvent.fromJson(const { 'cameraId': 1, 'previewWidth': 1024.0, 'previewHeight': 640.0, @@ -47,8 +45,14 @@ void main() { test('toJson should return a map with all fields', () { const CameraInitializedEvent event = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, - imageExtension: ImageExtension.heic); + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ); final Map jsonMap = event.toJson(); @@ -60,95 +64,99 @@ void main() { expect(jsonMap['exposurePointSupported'], true); expect(jsonMap['focusMode'], 'auto'); expect(jsonMap['focusPointSupported'], true); - expect(jsonMap['imageFormat'], 'heic'); }); test('equals should return true if objects are the same', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); - test('equals should return false if exposurePointSupported is different', - () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); + test('equals should return false if exposurePointSupported is different', () { + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); expect(firstEvent == secondEvent, false); }); test('equals should return true if imageExtension is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true, - imageExtension: ImageExtension.heic); + 1, + 1024, + 640, + ExposureMode.auto, + true, + FocusMode.auto, + true, + ); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.previewWidth, @@ -157,7 +165,6 @@ void main() { event.exposurePointSupported, event.focusMode, event.focusPointSupported, - event.imageExtension, ); expect(event.hashCode, expectedHashCode); @@ -166,8 +173,7 @@ void main() { group('CameraResolutionChangesEvent tests', () { test('Constructor should initialize all properties', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); expect(event.cameraId, 1); expect(event.captureWidth, 1024); @@ -175,8 +181,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraResolutionChangedEvent event = - CameraResolutionChangedEvent.fromJson(const { + final CameraResolutionChangedEvent event = CameraResolutionChangedEvent.fromJson(const { 'cameraId': 1, 'captureWidth': 1024.0, 'captureHeight': 640.0, @@ -188,8 +193,7 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); final Map jsonMap = event.toJson(); @@ -200,44 +204,35 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 640); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(2, 1024, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(2, 1024, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureWidth is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 2048, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 2048, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureHeight is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 1024, 980); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 980); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.captureWidth, @@ -256,8 +251,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraClosingEvent event = - CameraClosingEvent.fromJson(const { + final CameraClosingEvent event = CameraClosingEvent.fromJson(const { 'cameraId': 1, }); @@ -304,8 +298,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraErrorEvent event = CameraErrorEvent.fromJson( - const {'cameraId': 1, 'description': 'Error'}); + final CameraErrorEvent event = + CameraErrorEvent.fromJson(const {'cameraId': 1, 'description': 'Error'}); expect(event.cameraId, 1); expect(event.description, 'Error'); @@ -344,8 +338,7 @@ void main() { test('hashCode should match hashCode of all properties', () { const CameraErrorEvent event = CameraErrorEvent(1, 'Error'); - final int expectedHashCode = - Object.hash(event.cameraId.hashCode, event.description); + final int expectedHashCode = Object.hash(event.cameraId.hashCode, event.description); expect(event.hashCode, expectedHashCode); }); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index c7643064f38..07f35bbd9ff 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -22,22 +22,18 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -45,28 +41,20 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test( - 'Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -81,26 +69,20 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test( - 'Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -115,10 +97,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -142,10 +122,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having((CameraException e) => e.code, 'code', - 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,15 +134,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + 'imageExtension': 'jpeg', + }, + 'initialize': null + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -186,7 +163,6 @@ void main() { true, FocusMode.auto, true, - imageExtension: ImageExtension.heic, )); await initializeFuture; @@ -199,6 +175,7 @@ void main() { arguments: { 'cameraId': 1, 'imageFormatGroup': 'unknown', + 'imageExtension': 'jpeg', }, ), ]); @@ -206,13 +183,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( @@ -232,7 +208,6 @@ void main() { true, FocusMode.auto, true, - imageExtension: ImageExtension.heic, )); await initializeFuture; @@ -281,17 +256,14 @@ void main() { true, FocusMode.auto, true, - imageExtension: ImageExtension.heic, )); await initializeFuture; }); test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -302,10 +274,8 @@ void main() { true, FocusMode.auto, true, - imageExtension: ImageExtension.heic, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -316,24 +286,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -347,19 +310,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -372,20 +330,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -398,20 +350,15 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); // Assert expect(await streamQueue.next, event); @@ -454,26 +401,16 @@ void main() { true, FocusMode.auto, true, - imageExtension: ImageExtension.heic, ), ); await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -489,51 +426,40 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'availableCameras': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'availableCameras': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); // Act expect( camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test( - 'Should take a picture and return an XFile instance with jpg extension', - () async { + test('Should take a picture and return an XFile instance', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: {'takePicture': '/test/path.jpg'}); + channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -542,34 +468,11 @@ void main() { expect(channel.log, [ isMethodCall('takePicture', arguments: { 'cameraId': cameraId, - 'imageExtension': 'jpeg', }), ]); expect(file.path, '/test/path.jpg'); }); - test( - 'Should take a picture and return an XFile instance with heic extension', - () async { - // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: {'takePicture': '/test/path.heic'}); - - // Act - final XFile file = await camera.takePicture(cameraId, - imageExtension: ImageExtension.heic); - - // Assert - expect(channel.log, [ - isMethodCall('takePicture', arguments: { - 'cameraId': cameraId, - 'imageExtension': 'heic', - }), - ]); - expect(file.path, '/test/path.heic'); - }); - test('Should prepare for video recording', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( @@ -614,23 +517,18 @@ void main() { ); // Act - const CameraDescription cameraDescription = CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0); + const CameraDescription cameraDescription = + CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0); await camera.setDescriptionWhileRecording(cameraDescription); // Assert expect(channel.log, [ isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': cameraDescription.name - }), + arguments: {'cameraName': cameraDescription.name}), ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -723,22 +621,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'off' - }), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -755,14 +641,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -779,18 +659,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -802,8 +674,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -822,8 +693,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -842,16 +712,14 @@ void main() { ); // Act - final double stepSize = - await camera.getExposureOffsetStepSize(cameraId); + final double stepSize = await camera.getExposureOffsetStepSize(cameraId); // Assert expect(stepSize, 0.25); expect(channel.log, [ - isMethodCall('getExposureOffsetStepSize', - arguments: { - 'cameraId': cameraId, - }), + isMethodCall('getExposureOffsetStepSize', arguments: { + 'cameraId': cameraId, + }), ]); }); @@ -863,8 +731,7 @@ void main() { ); // Act - final double actualOffset = - await camera.setExposureOffset(cameraId, 0.5); + final double actualOffset = await camera.setExposureOffset(cameraId, 0.5); // Assert expect(actualOffset, 0.6); @@ -889,14 +756,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -913,18 +774,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -937,13 +790,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final MethodChannelCamera camera = MethodChannelCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -997,13 +847,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -1020,8 +868,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1032,15 +879,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1056,8 +900,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1073,8 +916,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1090,8 +932,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1106,9 +947,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1129,9 +969,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart b/packages/camera/camera_platform_interface/test/types/image_extension_test.dart index 8c8f7241edf..105b490ed22 100644 --- a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart +++ b/packages/camera/camera_platform_interface/test/types/image_extension_test.dart @@ -4,19 +4,8 @@ import 'package:flutter_test/flutter_test.dart'; void main() { group('$ImageExtension tests', () { test('ImageFormat extension returns correct values', () { - expect(ImageExtension.jpeg.name, 'jpeg'); - expect(ImageExtension.heic.name, 'heic'); - }); - - test('ImageExtensiont serialization', () { - expect(serializeImageExtension(ImageExtension.jpeg), 'jpeg'); - expect(serializeImageExtension(ImageExtension.heic), 'heic'); - }); - - test('ImageExtension deserialization', () { - expect(deserializeImageExtension('jpeg'), ImageExtension.jpeg); - expect(deserializeImageExtension('heic'), ImageExtension.heic); - expect(() => deserializeImageExtension('invalid'), throwsArgumentError); + expect(ImageExtension.jpeg.name(), 'jpeg'); + expect(ImageExtension.heic.name(), 'heic'); }); }); } From d15112e2d5c085749a52abffbf831f8687261147 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 13 Oct 2023 21:24:22 -0300 Subject: [PATCH 22/71] fix header --- packages/camera/camera_avfoundation/ios/Classes/FLTCam.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 6c256a69852..39483665d4f 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -48,8 +48,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)start; - (void)stop; - (void)setDeviceOrientation:(UIDeviceOrientation)orientation; -- (void)captureToFile:(FLTThreadSafeFlutterResult *)result - imageExtensionString:(NSString *)imageExtensionString; +- (void)captureToFile:(FLTThreadSafeFlutterResult *)result; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; /** From f906e99b02db731c7275b6a3c9c49d8a4d011ed4 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 13 Oct 2023 21:29:00 -0300 Subject: [PATCH 23/71] format code --- .../camera/lib/src/camera_controller.dart | 128 +-- packages/camera/camera/test/camera_test.dart | 737 +++++++++++++----- .../test/android_camera_test.dart | 342 +++++--- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 6 +- .../lib/src/avfoundation_camera.dart | 96 ++- .../test/avfoundation_camera_test.dart | 350 ++++++--- .../lib/src/events/camera_event.dart | 28 +- .../method_channel/method_channel_camera.dart | 93 ++- .../platform_interface/camera_platform.dart | 15 +- .../test/events/camera_event_test.dart | 128 +-- .../method_channel_camera_test.dart | 385 ++++++--- 11 files changed, 1582 insertions(+), 726 deletions(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index 4ec5982db96..7cef0bc54ee 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -183,16 +183,21 @@ class CameraValue { flashMode: flashMode ?? this.flashMode, exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, - exposurePointSupported: exposurePointSupported ?? this.exposurePointSupported, + exposurePointSupported: + exposurePointSupported ?? this.exposurePointSupported, focusPointSupported: focusPointSupported ?? this.focusPointSupported, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: - lockedCaptureOrientation == null ? this.lockedCaptureOrientation : lockedCaptureOrientation.orNull, - recordingOrientation: recordingOrientation == null ? this.recordingOrientation : recordingOrientation.orNull, + lockedCaptureOrientation: lockedCaptureOrientation == null + ? this.lockedCaptureOrientation + : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null + ? this.recordingOrientation + : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, description: description ?? this.description, - previewPauseOrientation: - previewPauseOrientation == null ? this.previewPauseOrientation : previewPauseOrientation.orNull, + previewPauseOrientation: previewPauseOrientation == null + ? this.previewPauseOrientation + : previewPauseOrientation.orNull, ); } @@ -269,7 +274,8 @@ class CameraController extends ValueNotifier { // just called). If the controller has not been initialized at least once, // this value is null. Future? _initializeFuture; - StreamSubscription? _deviceOrientationSubscription; + StreamSubscription? + _deviceOrientationSubscription; /// Checks whether [CameraController.dispose] has completed successfully. /// @@ -301,10 +307,12 @@ class CameraController extends ValueNotifier { _initializeFuture = initializeCompleter.future; try { - final Completer initializeCompleter = Completer(); + final Completer initializeCompleter = + Completer(); - _deviceOrientationSubscription ??= - CameraPlatform.instance.onDeviceOrientationChanged().listen((DeviceOrientationChangedEvent event) { + _deviceOrientationSubscription ??= CameraPlatform.instance + .onDeviceOrientationChanged() + .listen((DeviceOrientationChangedEvent event) { value = value.copyWith( deviceOrientation: event.orientation, ); @@ -316,7 +324,10 @@ class CameraController extends ValueNotifier { enableAudio: enableAudio, ); - _unawaited(CameraPlatform.instance.onCameraInitialized(_cameraId).first.then((CameraInitializedEvent event) { + _unawaited(CameraPlatform.instance + .onCameraInitialized(_cameraId) + .first + .then((CameraInitializedEvent event) { initializeCompleter.complete(event); })); @@ -328,16 +339,19 @@ class CameraController extends ValueNotifier { value = value.copyWith( isInitialized: true, description: description, - previewSize: await initializeCompleter.future.then((CameraInitializedEvent event) => Size( - event.previewWidth, - event.previewHeight, - )), - exposureMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposureMode), - focusMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusMode), - exposurePointSupported: - await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposurePointSupported), - focusPointSupported: - await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusPointSupported), + previewSize: await initializeCompleter.future + .then((CameraInitializedEvent event) => Size( + event.previewWidth, + event.previewHeight, + )), + exposureMode: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.exposureMode), + focusMode: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.focusMode), + exposurePointSupported: await initializeCompleter.future.then( + (CameraInitializedEvent event) => event.exposurePointSupported), + focusPointSupported: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.focusPointSupported), ); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -370,8 +384,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: - Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); + previewPauseOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -384,8 +398,9 @@ class CameraController extends ValueNotifier { } try { await CameraPlatform.instance.resumePreview(_cameraId); - value = - value.copyWith(isPreviewPaused: false, previewPauseOrientation: const Optional.absent()); + value = value.copyWith( + isPreviewPaused: false, + previewPauseOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -448,7 +463,8 @@ class CameraController extends ValueNotifier { /// // TODO(bmparr): Add settings for resolution and fps. Future startImageStream(onLatestImageAvailable onAvailable) async { - assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('startImageStream'); if (value.isRecordingVideo) { throw CameraException( @@ -464,8 +480,9 @@ class CameraController extends ValueNotifier { } try { - _imageStreamSubscription = - CameraPlatform.instance.onStreamedFrameAvailable(_cameraId).listen((CameraImageData imageData) { + _imageStreamSubscription = CameraPlatform.instance + .onStreamedFrameAvailable(_cameraId) + .listen((CameraImageData imageData) { onAvailable(CameraImage.fromPlatformInterface(imageData)); }); value = value.copyWith(isStreamingImages: true); @@ -482,7 +499,8 @@ class CameraController extends ValueNotifier { /// The `stopImageStream` method is only available on Android and iOS (other /// platforms won't be supported in current setup). Future stopImageStream() async { - assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('stopImageStream'); if (!value.isStreamingImages) { throw CameraException( @@ -507,7 +525,8 @@ class CameraController extends ValueNotifier { /// /// The video is returned as a [XFile] after calling [stopVideoRecording]. /// Throws a [CameraException] if the capture fails. - Future startVideoRecording({onLatestImageAvailable? onAvailable}) async { + Future startVideoRecording( + {onLatestImageAvailable? onAvailable}) async { _throwIfNotInitialized('startVideoRecording'); if (value.isRecordingVideo) { throw CameraException( @@ -524,12 +543,13 @@ class CameraController extends ValueNotifier { } try { - await CameraPlatform.instance.startVideoCapturing(VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); + await CameraPlatform.instance.startVideoCapturing( + VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, - recordingOrientation: - Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation), + recordingOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation), isStreamingImages: onAvailable != null); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -553,7 +573,8 @@ class CameraController extends ValueNotifier { } try { - final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); + final XFile file = + await CameraPlatform.instance.stopVideoRecording(_cameraId); value = value.copyWith( isRecordingVideo: false, recordingOrientation: const Optional.absent(), @@ -671,8 +692,10 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the exposure point to it's default /// value. Future setExposurePoint(Offset? point) async { - if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && + (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError( + 'The values of point should be anywhere between (0,0) and (1,1).'); } try { @@ -736,7 +759,8 @@ class CameraController extends ValueNotifier { Future setExposureOffset(double offset) async { _throwIfNotInitialized('setExposureOffset'); // Check if offset is in range - final List range = await Future.wait(>[getMinExposureOffset(), getMaxExposureOffset()]); + final List range = await Future.wait( + >[getMinExposureOffset(), getMaxExposureOffset()]); if (offset < range[0] || offset > range[1]) { throw CameraException( 'exposureOffsetOutOfBounds', @@ -769,9 +793,11 @@ class CameraController extends ValueNotifier { /// If [orientation] is omitted, the current device orientation is used. Future lockCaptureOrientation([DeviceOrientation? orientation]) async { try { - await CameraPlatform.instance.lockCaptureOrientation(_cameraId, orientation ?? value.deviceOrientation); + await CameraPlatform.instance.lockCaptureOrientation( + _cameraId, orientation ?? value.deviceOrientation); value = value.copyWith( - lockedCaptureOrientation: Optional.of(orientation ?? value.deviceOrientation)); + lockedCaptureOrientation: Optional.of( + orientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -791,7 +817,8 @@ class CameraController extends ValueNotifier { Future unlockCaptureOrientation() async { try { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith(lockedCaptureOrientation: const Optional.absent()); + value = value.copyWith( + lockedCaptureOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -802,8 +829,10 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the focus point to it's default /// value. Future setFocusPoint(Offset? point) async { - if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && + (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError( + 'The values of point should be anywhere between (0,0) and (1,1).'); } try { await CameraPlatform.instance.setFocusPoint( @@ -934,7 +963,9 @@ class Optional extends IterableBase { /// /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. Optional transform(S Function(T value) transformer) { - return _value == null ? Optional.absent() : Optional.of(transformer(_value as T)); + return _value == null + ? Optional.absent() + : Optional.of(transformer(_value as T)); } /// Transforms the Optional value. @@ -943,11 +974,14 @@ class Optional extends IterableBase { /// /// Returns [absent()] if the transformer returns `null`. Optional transformNullable(S? Function(T value) transformer) { - return _value == null ? Optional.absent() : Optional.fromNullable(transformer(_value as T)); + return _value == null + ? Optional.absent() + : Optional.fromNullable(transformer(_value as T)); } @override - Iterator get iterator => isPresent ? [_value as T].iterator : Iterable.empty().iterator; + Iterator get iterator => + isPresent ? [_value as T].iterator : Iterable.empty().iterator; /// Delegates to the underlying [value] hashCode. @override @@ -959,6 +993,8 @@ class Optional extends IterableBase { @override String toString() { - return _value == null ? 'Optional { absent }' : 'Optional { value: $_value }'; + return _value == null + ? 'Optional { absent }' + : 'Optional { value: $_value }'; } } diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index ece19d0360c..021fc17410e 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -15,13 +15,20 @@ import 'package:mockito/mockito.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; List get mockAvailableCameras => [ - const CameraDescription(name: 'camBack', lensDirection: CameraLensDirection.back, sensorOrientation: 90), - const CameraDescription(name: 'camFront', lensDirection: CameraLensDirection.front, sensorOrientation: 180), + const CameraDescription( + name: 'camBack', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), + const CameraDescription( + name: 'camFront', + lensDirection: CameraLensDirection.front, + sensorOrientation: 180), ]; int get mockInitializeCamera => 13; -CameraInitializedEvent get mockOnCameraInitializedEvent => const CameraInitializedEvent( +CameraInitializedEvent get mockOnCameraInitializedEvent => + const CameraInitializedEvent( 13, 75, 75, @@ -36,7 +43,8 @@ DeviceOrientationChangedEvent get mockOnDeviceOrientationChangedEvent => CameraClosingEvent get mockOnCameraClosingEvent => const CameraClosingEvent(13); -CameraErrorEvent get mockOnCameraErrorEvent => const CameraErrorEvent(13, 'closing'); +CameraErrorEvent get mockOnCameraErrorEvent => + const CameraErrorEvent(13, 'closing'); XFile mockTakePicture = XFile('foo/bar.png'); @@ -48,7 +56,8 @@ void main() { WidgetsFlutterBinding.ensureInitialized(); group('camera', () { - test('debugCheckIsDisposed should not throw assertion error when disposed', () { + test('debugCheckIsDisposed should not throw assertion error when disposed', + () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -60,7 +69,8 @@ void main() { expect(controller.debugCheckIsDisposed, returnsNormally); }); - test('debugCheckIsDisposed should throw assertion error when not disposed', () { + test('debugCheckIsDisposed should throw assertion error when not disposed', + () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -89,7 +99,10 @@ void main() { test('Can be initialized', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -100,7 +113,10 @@ void main() { test('can be disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -115,7 +131,10 @@ void main() { test('initialize() throws CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -136,9 +155,13 @@ void main() { ))); }); - test('initialize() throws $CameraException on $PlatformException ', () async { + test('initialize() throws $CameraException on $PlatformException ', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); mockPlatformException = true; @@ -156,15 +179,21 @@ void main() { test('initialize() sets imageFormat', () async { debugDefaultTargetPlatformOverride = TargetPlatform.android; final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max, imageFormatGroup: ImageFormatGroup.yuv420, ); await cameraController.initialize(); - verify(CameraPlatform.instance.initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)).called(1); + verify(CameraPlatform.instance + .initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)) + .called(1); }); - test('setDescription waits for initialize before calling dispose', () async { + test('setDescription waits for initialize before calling dispose', + () async { final CameraController cameraController = CameraController( const CameraDescription( name: 'cam', @@ -186,7 +215,10 @@ void main() { unawaited(cameraController.initialize()); final Future setDescriptionFuture = cameraController.setDescription( - const CameraDescription(name: 'cam2', lensDirection: CameraLensDirection.front, sensorOrientation: 90), + const CameraDescription( + name: 'cam2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 90), ); verifyNever(CameraPlatform.instance.dispose(mockInitializeCamera)); @@ -198,7 +230,10 @@ void main() { test('prepareForVideoRecording() calls $CameraPlatform ', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -209,7 +244,10 @@ void main() { test('takePicture() throws $CameraException when uninitialized ', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( cameraController.takePicture(), @@ -229,13 +267,18 @@ void main() { ); }); - test('takePicture() throws $CameraException when takePicture is true', () async { + test('takePicture() throws $CameraException when takePicture is true', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isTakingPicture: true); + cameraController.value = + cameraController.value.copyWith(isTakingPicture: true); expect( cameraController.takePicture(), throwsA(isA().having( @@ -247,7 +290,10 @@ void main() { test('takePicture() returns $XFile', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); final XFile xFile = await cameraController.takePicture(); @@ -255,9 +301,13 @@ void main() { expect(xFile.path, mockTakePicture.path); }); - test('takePicture() throws $CameraException on $PlatformException', () async { + test('takePicture() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -272,9 +322,13 @@ void main() { mockPlatformException = false; }); - test('startVideoRecording() throws $CameraException when uninitialized', () async { + test('startVideoRecording() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -294,14 +348,19 @@ void main() { ), ); }); - test('startVideoRecording() throws $CameraException when recording videos', () async { + test('startVideoRecording() throws $CameraException when recording videos', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isRecordingVideo: true); + cameraController.value = + cameraController.value.copyWith(isRecordingVideo: true); expect( cameraController.startVideoRecording(), @@ -312,9 +371,13 @@ void main() { ))); }); - test('getMaxZoomLevel() throws $CameraException when uninitialized', () async { + test('getMaxZoomLevel() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -337,7 +400,10 @@ void main() { test('getMaxZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -361,20 +427,29 @@ void main() { ); }); - test('getMaxZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'getMaxZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenThrow(CameraException( + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMaxZoomLevel, - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -383,19 +458,27 @@ void main() { test('getMaxZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) + .thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMaxZoomLevel(); expect(maxZoomLevel, 42.0); }); - test('getMinZoomLevel() throws $CameraException when uninitialized', () async { + test('getMinZoomLevel() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -418,7 +501,10 @@ void main() { test('getMinZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -442,20 +528,29 @@ void main() { ); }); - test('getMinZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'getMinZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenThrow(CameraException( + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMinZoomLevel, - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -464,11 +559,15 @@ void main() { test('getMinZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) + .thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMinZoomLevel(); expect(maxZoomLevel, 42.0); @@ -476,7 +575,10 @@ void main() { test('setZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -499,7 +601,10 @@ void main() { test('setZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -523,20 +628,29 @@ void main() { ); }); - test('setZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'setZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).thenThrow(CameraException( + when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( () => cameraController.setZoomLevel(42), - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -545,35 +659,52 @@ void main() { reset(CameraPlatform.instance); }); - test('setZoomLevel() completes and calls method channel with correct value.', () async { + test( + 'setZoomLevel() completes and calls method channel with correct value.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setZoomLevel(42.0); - verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).called(1); + verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) + .called(1); }); test('setFlashMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setFlashMode(FlashMode.always); - verify(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).called(1); + verify(CameraPlatform.instance + .setFlashMode(cameraController.cameraId, FlashMode.always)) + .called(1); }); - test('setFlashMode() throws $CameraException on $PlatformException', () async { + test('setFlashMode() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).thenThrow( + when(CameraPlatform.instance + .setFlashMode(cameraController.cameraId, FlashMode.always)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -591,22 +722,33 @@ void main() { test('setExposureMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposureMode(ExposureMode.auto); - verify(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).called(1); + verify(CameraPlatform.instance + .setExposureMode(cameraController.cameraId, ExposureMode.auto)) + .called(1); }); - test('setExposureMode() throws $CameraException on $PlatformException', () async { + test('setExposureMode() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).thenThrow( + when(CameraPlatform.instance + .setExposureMode(cameraController.cameraId, ExposureMode.auto)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -624,23 +766,32 @@ void main() { test('setExposurePoint() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposurePoint(const Offset(0.5, 0.5)); - verify(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) + verify(CameraPlatform.instance.setExposurePoint( + cameraController.cameraId, const Point(0.5, 0.5))) .called(1); }); - test('setExposurePoint() throws $CameraException on $PlatformException', () async { + test('setExposurePoint() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) + when(CameraPlatform.instance.setExposurePoint( + cameraController.cameraId, const Point(0.5, 0.5))) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -659,25 +810,37 @@ void main() { test('getMinExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getMinExposureOffset(); - verify(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .called(1); }); - test('getMinExposureOffset() throws $CameraException on $PlatformException', () async { + test('getMinExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -695,25 +858,37 @@ void main() { test('getMaxExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(1.0)); await cameraController.getMaxExposureOffset(); - verify(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .called(1); }); - test('getMaxExposureOffset() throws $CameraException on $PlatformException', () async { + test('getMaxExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -731,25 +906,38 @@ void main() { test('getExposureOffsetStepSize() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)) + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getExposureOffsetStepSize(); - verify(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .called(1); }); - test('getExposureOffsetStepSize() throws $CameraException on $PlatformException', () async { + test( + 'getExposureOffsetStepSize() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -767,28 +955,53 @@ void main() { test('setExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .thenAnswer((_) async => 1.0); await cameraController.setExposureOffset(1.0); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .called(1); }); - test('setExposureOffset() throws $CameraException on $PlatformException', () async { + test('setExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenThrow( + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -804,17 +1017,34 @@ void main() { ))); }); - test('setExposureOffset() throws $CameraException when offset is out of bounds', () async { + test( + 'setExposureOffset() throws $CameraException when offset is out of bounds', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 2.0)) + .thenAnswer((_) async => 0.0); expect( cameraController.setExposureOffset(3.0), @@ -835,27 +1065,56 @@ void main() { await cameraController.setExposureOffset(-1.0); await cameraController.setExposureOffset(2.0); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(1); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).called(1); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.0)) + .called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 2.0)) + .called(1); }); test('setExposureOffset() rounds offset to nearest step', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.2); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 1.2); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 0.4); - - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.2)).thenAnswer((_) async => -1.2); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).thenAnswer((_) async => -0.8); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).thenAnswer((_) async => -0.4); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).thenAnswer((_) async => 0.4); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).thenAnswer((_) async => 0.8); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.2)).thenAnswer((_) async => 1.2); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.2); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 1.2); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 0.4); + + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.2)) + .thenAnswer((_) async => -1.2); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.8)) + .thenAnswer((_) async => -0.8); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.4)) + .thenAnswer((_) async => -0.4); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.4)) + .thenAnswer((_) async => 0.4); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.8)) + .thenAnswer((_) async => 0.8); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.2)) + .thenAnswer((_) async => 1.2); await cameraController.setExposureOffset(1.2); await cameraController.setExposureOffset(-1.2); @@ -874,62 +1133,97 @@ void main() { await cameraController.setExposureOffset(-0.6); await cameraController.setExposureOffset(-0.7); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).called(4); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).called(4); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.8)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.8)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.4)) + .called(4); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.4)) + .called(4); }); test('pausePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(deviceOrientation: DeviceOrientation.portraitUp); + cameraController.value = cameraController.value + .copyWith(deviceOrientation: DeviceOrientation.portraitUp); await cameraController.pausePreview(); - verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)) + .called(1); expect(cameraController.value.isPreviewPaused, equals(true)); - expect(cameraController.value.previewPauseOrientation, DeviceOrientation.portraitUp); + expect(cameraController.value.previewPauseOrientation, + DeviceOrientation.portraitUp); }); - test('pausePreview() does not call $CameraPlatform when already paused', () async { + test('pausePreview() does not call $CameraPlatform when already paused', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); await cameraController.pausePreview(); - verifyNever(CameraPlatform.instance.pausePreview(cameraController.cameraId)); + verifyNever( + CameraPlatform.instance.pausePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(true)); }); - test('pausePreview() sets previewPauseOrientation according to locked orientation', () async { + test( + 'pausePreview() sets previewPauseOrientation according to locked orientation', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); cameraController.value = cameraController.value.copyWith( isPreviewPaused: false, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: Optional.of(DeviceOrientation.landscapeRight)); + lockedCaptureOrientation: + Optional.of(DeviceOrientation.landscapeRight)); await cameraController.pausePreview(); - expect(cameraController.value.deviceOrientation, equals(DeviceOrientation.portraitUp)); - expect(cameraController.value.previewPauseOrientation, equals(DeviceOrientation.landscapeRight)); + expect(cameraController.value.deviceOrientation, + equals(DeviceOrientation.portraitUp)); + expect(cameraController.value.previewPauseOrientation, + equals(DeviceOrientation.landscapeRight)); }); - test('pausePreview() throws $CameraException on $PlatformException', () async { + test('pausePreview() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.pausePreview(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance.pausePreview(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -947,37 +1241,54 @@ void main() { test('resumePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); await cameraController.resumePreview(); - verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)) + .called(1); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() does not call $CameraPlatform when not paused', () async { + test('resumePreview() does not call $CameraPlatform when not paused', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: false); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: false); await cameraController.resumePreview(); - verifyNever(CameraPlatform.instance.resumePreview(cameraController.cameraId)); + verifyNever( + CameraPlatform.instance.resumePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() throws $CameraException on $PlatformException', () async { + test('resumePreview() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); - when(CameraPlatform.instance.resumePreview(cameraController.cameraId)).thenThrow( + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); + when(CameraPlatform.instance.resumePreview(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -995,28 +1306,41 @@ void main() { test('lockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.lockCaptureOrientation(); - expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.portraitUp)); - await cameraController.lockCaptureOrientation(DeviceOrientation.landscapeRight); - expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.landscapeRight)); - - verify(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) + expect(cameraController.value.lockedCaptureOrientation, + equals(DeviceOrientation.portraitUp)); + await cameraController + .lockCaptureOrientation(DeviceOrientation.landscapeRight); + expect(cameraController.value.lockedCaptureOrientation, + equals(DeviceOrientation.landscapeRight)); + + verify(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.portraitUp)) .called(1); - verify(CameraPlatform.instance - .lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.landscapeRight)) + verify(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.landscapeRight)) .called(1); }); - test('lockCaptureOrientation() throws $CameraException on $PlatformException', () async { + test( + 'lockCaptureOrientation() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) + when(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.portraitUp)) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -1035,22 +1359,34 @@ void main() { test('unlockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.unlockCaptureOrientation(); expect(cameraController.value.lockedCaptureOrientation, equals(null)); - verify(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .unlockCaptureOrientation(cameraController.cameraId)) + .called(1); }); - test('unlockCaptureOrientation() throws $CameraException on $PlatformException', () async { + test( + 'unlockCaptureOrientation() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .unlockCaptureOrientation(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1068,7 +1404,9 @@ void main() { }); } -class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements CameraPlatform { +class MockCameraPlatform extends Mock + with MockPlatformInterfaceMixin + implements CameraPlatform { @override Future initializeCamera( int? cameraId, { @@ -1089,7 +1427,8 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements } @override - Future> availableCameras() => Future>.value(mockAvailableCameras); + Future> availableCameras() => + Future>.value(mockAvailableCameras); @override Future createCamera( @@ -1110,14 +1449,17 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements Stream.value(mockOnCameraClosingEvent); @override - Stream onCameraError(int cameraId) => Stream.value(mockOnCameraErrorEvent); + Stream onCameraError(int cameraId) => + Stream.value(mockOnCameraErrorEvent); @override Stream onDeviceOrientationChanged() => - Stream.value(mockOnDeviceOrientationChangedEvent); + Stream.value( + mockOnDeviceOrientationChangedEvent); @override - Future takePicture(int cameraId, {ImageExtension imageExtension = ImageExtension.jpeg}) => + Future takePicture(int cameraId, + {ImageExtension imageExtension = ImageExtension.jpeg}) => mockPlatformException ? throw PlatformException(code: 'foo', message: 'bar') : Future.value(mockTakePicture); @@ -1127,29 +1469,34 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements super.noSuchMethod(Invocation.method(#prepareForVideoRecording, null)); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) => + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) => Future.value(mockVideoRecordingXFile); @override Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } @override - Future lockCaptureOrientation(int? cameraId, DeviceOrientation? orientation) async => - super.noSuchMethod(Invocation.method(#lockCaptureOrientation, [cameraId, orientation])); + Future lockCaptureOrientation( + int? cameraId, DeviceOrientation? orientation) async => + super.noSuchMethod(Invocation.method( + #lockCaptureOrientation, [cameraId, orientation])); @override Future unlockCaptureOrientation(int? cameraId) async => - super.noSuchMethod(Invocation.method(#unlockCaptureOrientation, [cameraId])); + super.noSuchMethod( + Invocation.method(#unlockCaptureOrientation, [cameraId])); @override Future pausePreview(int? cameraId) async => super.noSuchMethod(Invocation.method(#pausePreview, [cameraId])); @override - Future resumePreview(int? cameraId) async => - super.noSuchMethod(Invocation.method(#resumePreview, [cameraId])); + Future resumePreview(int? cameraId) async => super + .noSuchMethod(Invocation.method(#resumePreview, [cameraId])); @override Future getMaxZoomLevel(int? cameraId) async => super.noSuchMethod( @@ -1165,40 +1512,48 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements @override Future setZoomLevel(int? cameraId, double? zoom) async => - super.noSuchMethod(Invocation.method(#setZoomLevel, [cameraId, zoom])); + super.noSuchMethod( + Invocation.method(#setZoomLevel, [cameraId, zoom])); @override Future setFlashMode(int? cameraId, FlashMode? mode) async => - super.noSuchMethod(Invocation.method(#setFlashMode, [cameraId, mode])); + super.noSuchMethod( + Invocation.method(#setFlashMode, [cameraId, mode])); @override Future setExposureMode(int? cameraId, ExposureMode? mode) async => - super.noSuchMethod(Invocation.method(#setExposureMode, [cameraId, mode])); + super.noSuchMethod( + Invocation.method(#setExposureMode, [cameraId, mode])); @override Future setExposurePoint(int? cameraId, Point? point) async => - super.noSuchMethod(Invocation.method(#setExposurePoint, [cameraId, point])); + super.noSuchMethod( + Invocation.method(#setExposurePoint, [cameraId, point])); @override - Future getMinExposureOffset(int? cameraId) async => super.noSuchMethod( + Future getMinExposureOffset(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getMinExposureOffset, [cameraId]), returnValue: Future.value(0.0), ) as Future; @override - Future getMaxExposureOffset(int? cameraId) async => super.noSuchMethod( + Future getMaxExposureOffset(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getMaxExposureOffset, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future getExposureOffsetStepSize(int? cameraId) async => super.noSuchMethod( + Future getExposureOffsetStepSize(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getExposureOffsetStepSize, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future setExposureOffset(int? cameraId, double? offset) async => super.noSuchMethod( + Future setExposureOffset(int? cameraId, double? offset) async => + super.noSuchMethod( Invocation.method(#setExposureOffset, [cameraId, offset]), returnValue: Future.value(1.0), ) as Future; diff --git a/packages/camera/camera_android/test/android_camera_test.dart b/packages/camera/camera_android/test/android_camera_test.dart index a0ef9c9c71c..8ffc901be7c 100644 --- a/packages/camera/camera_android/test/android_camera_test.dart +++ b/packages/camera/camera_android/test/android_camera_test.dart @@ -32,11 +32,13 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + final ByteData? response = await TestDefaultBinaryMessengerBinding + .instance.defaultBinaryMessenger .handlePlatformMessage( AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), + const StandardMethodCodec().encodeMethodCall(const MethodCall( + 'orientation_changed', + {'orientation': 'portraitDown'})), (ByteData? data) {}); expect(response, null); }); @@ -44,18 +46,22 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AndroidCamera camera = AndroidCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -63,13 +69,18 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -91,13 +102,16 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -119,8 +133,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -144,7 +160,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -156,14 +175,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -204,12 +224,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( @@ -283,8 +304,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -296,7 +319,8 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -307,17 +331,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -331,14 +362,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -351,14 +387,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -371,17 +413,21 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage( - AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), - null); + await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .handlePlatformMessage( + AndroidCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -430,11 +476,20 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -450,17 +505,21 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -474,23 +533,27 @@ void main() { camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); // Assert expect(channel.log, [ - isMethodCall('takePicture', arguments: {'cameraId': cameraId}), + isMethodCall('takePicture', + arguments: {'cameraId': cameraId}), ]); expect(file.path, '/test/path.jpg'); }); @@ -531,7 +594,8 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -554,7 +618,9 @@ void main() { ]); }); - test('Should pass enableStream if callback is passed when starting recording a video', () async { + test( + 'Should pass enableStream if callback is passed when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -563,7 +629,8 @@ void main() { // Act await camera.startVideoCapturing( - VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {}), + VideoCaptureOptions(cameraId, + streamCallback: (CameraImageData imageData) {}), ); // Assert @@ -637,17 +704,20 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = - CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); + const CameraDescription camera2Description = CameraDescription( + name: 'Test2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', + arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -666,10 +736,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -686,8 +764,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -704,10 +786,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -719,7 +809,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -738,7 +829,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -801,8 +893,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -819,10 +915,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -835,10 +939,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final AndroidCamera camera = AndroidCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -892,11 +999,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -913,7 +1022,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -924,12 +1034,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -945,7 +1058,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -961,7 +1075,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -977,7 +1092,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -992,8 +1108,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1014,8 +1131,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 09be99356c2..5daf7d405ba 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -49,7 +49,7 @@ - (void)testCaptureToFile_mustReportErrorToResultIfSavePhotoDelegateCompletionsW // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult imageExtensionString:@"heic"]; + [cam captureToFile:mockResult]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; @@ -89,9 +89,9 @@ - (void)testCaptureToFile_mustReportPathToResultIfSavePhotoDelegateCompletionsWi // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult imageExtensionString:@"heic"]; + [cam captureToFile:mockResult]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; } -@end +@end \ No newline at end of file diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 0df098f27e9..e50ee006e75 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,7 +14,8 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = + MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -28,7 +29,8 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = + 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -38,14 +40,16 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = + _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -61,13 +65,14 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -76,7 +81,8 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -92,9 +98,12 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -111,8 +120,10 @@ class AVFoundationCamera extends CameraPlatform { ImageExtension imageExtension = ImageExtension.jpeg, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel( + 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -190,7 +201,8 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream.whereType(); + return _deviceEventStreamController.stream + .whereType(); } @override @@ -200,7 +212,10 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -230,11 +245,14 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -279,18 +297,22 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { - _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { + _frameStreamController = + _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController({Function()? onListen}) { + StreamController _createStreamController( + {Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -309,14 +331,17 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -328,11 +353,13 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -341,7 +368,8 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -409,7 +437,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -485,7 +514,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -560,8 +590,8 @@ class AVFoundationCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -605,7 +635,9 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 89ec2a8c93c..e1ae682c04d 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -32,31 +32,37 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(const MethodCall( + 'orientation_changed', + {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AVFoundationCamera camera = AVFoundationCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -64,13 +70,18 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -92,13 +103,16 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -120,8 +134,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -145,7 +161,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,15 +176,16 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - 'imageExtension': 'jpeg', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + 'imageExtension': 'jpeg', + }, + 'initialize': null + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -206,12 +226,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( @@ -285,8 +306,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -298,7 +321,8 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -309,17 +333,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -333,14 +364,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -353,14 +389,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -373,17 +415,22 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -432,14 +479,23 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange // This deliberately uses 'dynamic' since that's what actual platform // channel results will be, so using typed mock data could mask type // handling bugs in the code under test. final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -455,17 +511,21 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -479,16 +539,19 @@ void main() { camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -538,7 +601,8 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -561,7 +625,9 @@ void main() { ]); }); - test('Should pass enableStream if callback is passed when starting recording a video', () async { + test( + 'Should pass enableStream if callback is passed when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -569,7 +635,8 @@ void main() { ); // Act - await camera.startVideoCapturing(VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {})); + await camera.startVideoCapturing(VideoCaptureOptions(cameraId, + streamCallback: (CameraImageData imageData) {})); // Assert expect(channel.log, [ @@ -642,17 +709,20 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = - CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); + const CameraDescription camera2Description = CameraDescription( + name: 'Test2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', + arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -671,10 +741,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -691,8 +769,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -709,10 +791,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -724,7 +814,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -743,7 +834,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -806,8 +898,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -824,10 +920,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -840,10 +944,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final AVFoundationCamera camera = AVFoundationCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -897,11 +1004,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -918,7 +1027,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -929,12 +1039,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -950,7 +1063,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -966,7 +1080,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -982,7 +1097,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -997,8 +1113,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1019,8 +1136,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart index 31a819e97e1..1c76c341d9b 100644 --- a/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart +++ b/packages/camera/camera_platform_interface/lib/src/events/camera_event.dart @@ -34,7 +34,10 @@ abstract class CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || other is CameraEvent && runtimeType == other.runtimeType && cameraId == other.cameraId; + identical(this, other) || + other is CameraEvent && + runtimeType == other.runtimeType && + cameraId == other.cameraId; @override int get hashCode => cameraId.hashCode; @@ -63,7 +66,8 @@ class CameraInitializedEvent extends CameraEvent { : previewWidth = json['previewWidth']! as double, previewHeight = json['previewHeight']! as double, exposureMode = deserializeExposureMode(json['exposureMode']! as String), - exposurePointSupported = (json['exposurePointSupported'] as bool?) ?? false, + exposurePointSupported = + (json['exposurePointSupported'] as bool?) ?? false, focusMode = deserializeFocusMode(json['focusMode']! as String), focusPointSupported = (json['focusPointSupported'] as bool?) ?? false, super(json['cameraId']! as int); @@ -178,7 +182,8 @@ class CameraClosingEvent extends CameraEvent { /// Converts the supplied [Map] to an instance of the [CameraClosingEvent] /// class. - CameraClosingEvent.fromJson(Map json) : super(json['cameraId']! as int); + CameraClosingEvent.fromJson(Map json) + : super(json['cameraId']! as int); /// Converts the [CameraClosingEvent] instance into a [Map] instance that can /// be serialized to JSON. @@ -188,7 +193,10 @@ class CameraClosingEvent extends CameraEvent { @override bool operator ==(Object other) => - identical(this, other) || super == other && other is CameraClosingEvent && runtimeType == other.runtimeType; + identical(this, other) || + super == other && + other is CameraClosingEvent && + runtimeType == other.runtimeType; @override // This is here even though it just calls super to make it less likely that @@ -246,8 +254,9 @@ class VideoRecordedEvent extends CameraEvent { /// class. VideoRecordedEvent.fromJson(Map json) : file = XFile(json['path']! as String), - maxVideoDuration = - json['maxVideoDuration'] != null ? Duration(milliseconds: json['maxVideoDuration'] as int) : null, + maxVideoDuration = json['maxVideoDuration'] != null + ? Duration(milliseconds: json['maxVideoDuration'] as int) + : null, super(json['cameraId']! as int); /// XFile of the recorded video. @@ -258,8 +267,11 @@ class VideoRecordedEvent extends CameraEvent { /// Converts the [VideoRecordedEvent] instance into a [Map] instance that can be /// serialized to JSON. - Map toJson() => - {'cameraId': cameraId, 'path': file.path, 'maxVideoDuration': maxVideoDuration?.inMilliseconds}; + Map toJson() => { + 'cameraId': cameraId, + 'path': file.path, + 'maxVideoDuration': maxVideoDuration?.inMilliseconds + }; @override bool operator ==(Object other) => diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index a7949d9b0e9..14a1dfe6c3a 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,8 +20,10 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler( + (MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -34,7 +36,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -44,7 +47,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = StreamController.broadcast(); + final StreamController deviceEventStreamController = + StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -53,13 +57,14 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -68,7 +73,8 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -84,9 +90,12 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -103,8 +112,10 @@ class MethodChannelCamera extends CameraPlatform { ImageExtension imageExtension = ImageExtension.jpeg, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -182,7 +193,8 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream.whereType(); + return deviceEventStreamController.stream + .whereType(); } @override @@ -192,7 +204,10 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -222,11 +237,14 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -270,18 +288,21 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController({Function()? onListen}) { + StreamController _installStreamController( + {Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -301,8 +322,10 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -310,7 +333,8 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -322,11 +346,13 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -335,7 +361,8 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -403,7 +430,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -479,7 +507,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -533,8 +562,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -578,7 +607,9 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 18118b77fb7..5f8eb796cda 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -100,11 +100,13 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError( + 'onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation( + int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -141,7 +143,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -169,7 +172,8 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -268,7 +272,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError( + 'setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 4068150ff5d..6b73ce20175 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -23,7 +23,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraInitializedEvent event = CameraInitializedEvent.fromJson(const { + final CameraInitializedEvent event = + CameraInitializedEvent.fromJson(const { 'cameraId': 1, 'previewWidth': 1024.0, 'previewHeight': 640.0, @@ -67,80 +68,81 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); - test('equals should return false if exposurePointSupported is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); + test('equals should return false if exposurePointSupported is different', + () { + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); expect(firstEvent == secondEvent, false); }); test('equals should return true if imageExtension is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); const CameraInitializedEvent secondEvent = CameraInitializedEvent( 1, 1024, @@ -155,8 +157,8 @@ void main() { }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.previewWidth, @@ -173,7 +175,8 @@ void main() { group('CameraResolutionChangesEvent tests', () { test('Constructor should initialize all properties', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); expect(event.cameraId, 1); expect(event.captureWidth, 1024); @@ -181,7 +184,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraResolutionChangedEvent event = CameraResolutionChangedEvent.fromJson(const { + final CameraResolutionChangedEvent event = + CameraResolutionChangedEvent.fromJson(const { 'cameraId': 1, 'captureWidth': 1024.0, 'captureHeight': 640.0, @@ -193,7 +197,8 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); final Map jsonMap = event.toJson(); @@ -204,35 +209,44 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 1024, 640); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(2, 1024, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(2, 1024, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureWidth is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 2048, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 2048, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureHeight is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 980); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 1024, 980); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.captureWidth, @@ -251,7 +265,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraClosingEvent event = CameraClosingEvent.fromJson(const { + final CameraClosingEvent event = + CameraClosingEvent.fromJson(const { 'cameraId': 1, }); @@ -298,8 +313,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraErrorEvent event = - CameraErrorEvent.fromJson(const {'cameraId': 1, 'description': 'Error'}); + final CameraErrorEvent event = CameraErrorEvent.fromJson( + const {'cameraId': 1, 'description': 'Error'}); expect(event.cameraId, 1); expect(event.description, 'Error'); @@ -338,7 +353,8 @@ void main() { test('hashCode should match hashCode of all properties', () { const CameraErrorEvent event = CameraErrorEvent(1, 'Error'); - final int expectedHashCode = Object.hash(event.cameraId.hashCode, event.description); + final int expectedHashCode = + Object.hash(event.cameraId.hashCode, event.description); expect(event.hashCode, expectedHashCode); }); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index 07f35bbd9ff..a2e80907747 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -22,18 +22,22 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -41,20 +45,28 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test( + 'Should throw CameraException when create throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -69,20 +81,26 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test( + 'Should throw CameraException when create throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -97,8 +115,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -122,7 +142,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having((CameraException e) => e.code, 'code', + 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -134,15 +157,16 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - 'imageExtension': 'jpeg', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + 'imageExtension': 'jpeg', + }, + 'initialize': null + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -183,12 +207,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( @@ -262,8 +287,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -275,7 +302,8 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -286,17 +314,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -310,14 +345,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -330,14 +370,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -350,15 +396,20 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); // Assert expect(await streamQueue.next, event); @@ -406,11 +457,20 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -426,32 +486,40 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'availableCameras': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'availableCameras': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); // Act expect( camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -459,7 +527,8 @@ void main() { test('Should take a picture and return an XFile instance', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.jpg'}); + channelName: 'plugins.flutter.io/camera', + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -517,18 +586,23 @@ void main() { ); // Act - const CameraDescription cameraDescription = - CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0); + const CameraDescription cameraDescription = CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0); await camera.setDescriptionWhileRecording(cameraDescription); // Assert expect(channel.log, [ isMethodCall('setDescriptionWhileRecording', - arguments: {'cameraName': cameraDescription.name}), + arguments: { + 'cameraName': cameraDescription.name + }), ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -621,10 +695,22 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'off' + }), ]); }); @@ -641,8 +727,14 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -659,10 +751,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -674,7 +774,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -693,7 +794,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -712,14 +814,16 @@ void main() { ); // Act - final double stepSize = await camera.getExposureOffsetStepSize(cameraId); + final double stepSize = + await camera.getExposureOffsetStepSize(cameraId); // Assert expect(stepSize, 0.25); expect(channel.log, [ - isMethodCall('getExposureOffsetStepSize', arguments: { - 'cameraId': cameraId, - }), + isMethodCall('getExposureOffsetStepSize', + arguments: { + 'cameraId': cameraId, + }), ]); }); @@ -731,7 +835,8 @@ void main() { ); // Act - final double actualOffset = await camera.setExposureOffset(cameraId, 0.5); + final double actualOffset = + await camera.setExposureOffset(cameraId, 0.5); // Assert expect(actualOffset, 0.6); @@ -756,8 +861,14 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -774,10 +885,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -790,10 +909,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final MethodChannelCamera camera = MethodChannelCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -847,11 +969,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -868,7 +992,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -879,12 +1004,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -900,7 +1028,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -916,7 +1045,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -932,7 +1062,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -947,8 +1078,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -969,8 +1101,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert From b6be5b5e910d2c322800f03d1ffa9fd0e32bb3d9 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 14 Oct 2023 08:52:19 -0300 Subject: [PATCH 24/71] add interface --- packages/camera/camera_avfoundation/ios/Classes/FLTCam.h | 1 + packages/camera/camera_avfoundation/ios/Classes/FLTCam.m | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 39483665d4f..d21c0f4a24c 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -107,6 +107,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)getMinZoomLevelWithResult:(FLTThreadSafeFlutterResult *)result; - (void)setZoomLevel:(CGFloat)zoom Result:(FLTThreadSafeFlutterResult *)result; - (void)setUpCaptureSessionForAudio; +- (void)setImageExtension:(ImageExtension)imageExtension; @end diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index b54862a8cad..fdb003699c4 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -219,7 +219,7 @@ - (void)setVideoFormat:(OSType)videoFormat { @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)}; } -- (void)setImageExtension:(ImageExtension *)imageExtension { +- (void)setImageExtension:(ImageExtension)imageExtension { _imageExtension = imageExtension; } From f57a9c21480103b25c1e1250d06dff4f40d43c1e Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 14 Oct 2023 09:11:49 -0300 Subject: [PATCH 25/71] fixes --- .../ios/Classes/CameraPlugin.m | 5 ++-- .../ios/Classes/CameraProperties.m | 29 ++++++++++--------- .../camera_avfoundation/ios/Classes/FLTCam.h | 1 - .../camera_avfoundation/ios/Classes/FLTCam.m | 4 +-- .../camera/camera_platform_interface/AUTHORS | 1 + .../camera_platform_interface/CHANGELOG.md | 2 +- .../camera_platform_interface/pubspec.yaml | 2 +- .../test/types/image_extension_test.dart | 4 +++ 8 files changed, 27 insertions(+), 21 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index f4f99b3151c..9cfdf0df039 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -186,10 +186,9 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call [self sendDeviceOrientation:[UIDevice currentDevice].orientation]; [_camera start]; [result sendSuccess]; - }else if ([@"takePicture" isEqualToString:call.method]) { + } else if ([@"takePicture" isEqualToString:call.method]) { [_camera captureToFile:result]; - } - else if ([@"dispose" isEqualToString:call.method]) { + } else if ([@"dispose" isEqualToString:call.method]) { [_registry unregisterTexture:cameraId]; [_camera close]; [result sendSuccess]; diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m index 61b721a869d..fdf10c2ea3c 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m @@ -152,16 +152,19 @@ OSType FLTGetVideoFormatFromString(NSString *videoFormatString) { #pragma mark - video codec -ImageExtension FLTGetImageExtensionForString(NSString *extensionString) { - if ([extensionString isEqualToString:@"jpg"]) { - return ImageExtensionJPEG; - } else if ([extensionString isEqualToString:@"heic"]) { - return ImageExtensionHEIC; - } else { - NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain - code:NSURLErrorUnknown - userInfo:@{ NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Unknown image extension %@", extensionString] }]; - @throw error; - } -} - +ImageExtension FLTGetImageExtensionFromString(NSString *extensionString) { + if ([extensionString isEqualToString:@"jpg"]) { + return ImageExtensionJPEG; + } else if ([extensionString isEqualToString:@"heic"]) { + return ImageExtensionHEIC; + } else { + NSError *error = [NSError + errorWithDomain:NSCocoaErrorDomain + code:NSURLErrorUnknown + userInfo:@{ + NSLocalizedDescriptionKey : + [NSString stringWithFormat:@"Unknown image extension %@", extensionString] + }]; + @throw error; + } +} \ No newline at end of file diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index d21c0f4a24c..39483665d4f 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -107,7 +107,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)getMinZoomLevelWithResult:(FLTThreadSafeFlutterResult *)result; - (void)setZoomLevel:(CGFloat)zoom Result:(FLTThreadSafeFlutterResult *)result; - (void)setUpCaptureSessionForAudio; -- (void)setImageExtension:(ImageExtension)imageExtension; @end diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index fdb003699c4..6c8f0ce12aa 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -266,12 +266,12 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { if (_imageExtension == ImageExtensionHEIC && @available(iOS 11.0, *)) { if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { - settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{ AVVideoCodecKey : AVVideoCodecTypeHEVC }]; + settings = [AVCapturePhotoSettings + photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; extension = @"heic"; } } - AVCaptureFlashMode avFlashMode = FLTGetAVCaptureFlashModeForFLTFlashMode(_flashMode); if (avFlashMode != -1) { [settings setFlashMode:avFlashMode]; diff --git a/packages/camera/camera_platform_interface/AUTHORS b/packages/camera/camera_platform_interface/AUTHORS index 493a0b4ef9c..0d1bfa6a90c 100644 --- a/packages/camera/camera_platform_interface/AUTHORS +++ b/packages/camera/camera_platform_interface/AUTHORS @@ -64,3 +64,4 @@ Aleksandr Yurkovskiy Anton Borries Alex Li Rahul Raj <64.rahulraj@gmail.com> +Mairramer diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index 978ede30dfc..e28b981c8e6 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.10.6 +## 2.5.3 * Add support to HEIC format to iOS diff --git a/packages/camera/camera_platform_interface/pubspec.yaml b/packages/camera/camera_platform_interface/pubspec.yaml index 09caeda73eb..93bd28638ab 100644 --- a/packages/camera/camera_platform_interface/pubspec.yaml +++ b/packages/camera/camera_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 2.5.2 +version: 2.5.3 environment: sdk: ">=2.19.0 <4.0.0" diff --git a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart b/packages/camera/camera_platform_interface/test/types/image_extension_test.dart index 105b490ed22..3eb286fa6c7 100644 --- a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart +++ b/packages/camera/camera_platform_interface/test/types/image_extension_test.dart @@ -1,3 +1,7 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + import 'package:camera_platform_interface/src/types/types.dart'; import 'package:flutter_test/flutter_test.dart'; From 729b7a2982fc8c2daf40870ecce2c97dfe86767a Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 14 Oct 2023 09:16:14 -0300 Subject: [PATCH 26/71] add interface --- packages/camera/camera_avfoundation/ios/Classes/FLTCam.h | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 39483665d4f..d21c0f4a24c 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -107,6 +107,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)getMinZoomLevelWithResult:(FLTThreadSafeFlutterResult *)result; - (void)setZoomLevel:(CGFloat)zoom Result:(FLTThreadSafeFlutterResult *)result; - (void)setUpCaptureSessionForAudio; +- (void)setImageExtension:(ImageExtension)imageExtension; @end From d14f6cbda0955686797e9e0d1261788dbaab146b Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 14 Oct 2023 12:10:34 -0300 Subject: [PATCH 27/71] added test --- .../ios/Runner.xcodeproj/project.pbxproj | 26 +++++++--- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 52 ++++++++++++++++++- .../example/lib/camera_controller.dart | 7 +++ .../camera_avfoundation/ios/Classes/FLTCam.h | 4 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 12 +++-- .../ios/Classes/FLTCam_Test.h | 3 -- .../platform_interface/camera_platform.dart | 19 ++++--- 7 files changed, 96 insertions(+), 27 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj index 6006b9f2b4b..8b8a381e844 100644 --- a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj @@ -376,7 +376,7 @@ 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; - buildActionMask = 2147483647; + buildActionMask = 12; files = ( ); inputPaths = ( @@ -386,7 +386,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; 9872F2A25E8A171A111468CD /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; @@ -495,7 +495,11 @@ GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = RunnerTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "dev.flutter.plugins.cameraExample.camera-exampleTests"; @@ -521,7 +525,11 @@ GCC_C_LANGUAGE_STANDARD = gnu11; INFOPLIST_FILE = RunnerTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 11.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + "@loader_path/Frameworks", + ); MTL_FAST_MATH = YES; PRODUCT_BUNDLE_IDENTIFIER = "dev.flutter.plugins.cameraExample.camera-exampleTests"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -648,7 +656,10 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", @@ -670,7 +681,10 @@ "$(PROJECT_DIR)/Flutter", ); INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(PROJECT_DIR)/Flutter", diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 5daf7d405ba..62bde5f9cb5 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -94,4 +94,54 @@ - (void)testCaptureToFile_mustReportPathToResultIfSavePhotoDelegateCompletionsWi [self waitForExpectationsWithTimeout:1 handler:nil]; } -@end \ No newline at end of file +- (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContainsHEVC { + // This test is only valid on iOS 11 or later. + if (@available(iOS 11.0, *)) { + XCTestExpectation *expectation = + [self expectationWithDescription: + @"Test must set extension to heic if availablePhotoCodecTypes contains HEVC."]; + + dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); + dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, + (void *)FLTCaptureSessionQueueSpecific, NULL); + FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); + [cam setImageExtension:ImageExtensionHEIC]; + + // Set photo settings to HEVC + AVCapturePhotoSettings *settings = + [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + + id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); + OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings);; + + NSString *filePath = @"test"; + id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); + OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { + [expectation fulfill]; + }); + + id mockOutput = OCMClassMock([AVCapturePhotoOutput class]); + // Set availablePhotoCodecTypes to HEVC + NSArray *codecTypes = @[AVVideoCodecTypeHEVC]; + OCMStub([mockOutput availablePhotoCodecTypes]).andReturn(codecTypes); + + OCMStub([mockOutput capturePhotoWithSettings:OCMOCK_ANY delegate:OCMOCK_ANY]) + .andDo(^(NSInvocation *invocation) { + FLTSavePhotoDelegate *delegate = cam.inProgressSavePhotoDelegates[@(settings.uniqueID)]; + // Completion runs on IO queue. + dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); + dispatch_async(ioQueue, ^{ + delegate.completionHandler(filePath, nil); + }); + }); + cam.capturePhotoOutput = mockOutput; + + // `FLTCam::captureToFile` runs on capture session queue. + dispatch_async(captureSessionQueue, ^{ + [cam captureToFile:mockResult]; + }); + + [self waitForExpectationsWithTimeout:1 handler:nil]; + } +} +@end diff --git a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart index 36b9ac68cfd..c29db976f09 100644 --- a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart +++ b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart @@ -176,6 +176,7 @@ class CameraController extends ValueNotifier { this.resolutionPreset, { this.enableAudio = true, this.imageFormatGroup, + this.imageExtension, }) : super(CameraValue.uninitialized(cameraDescription)); /// The properties of the camera device controlled by this controller. @@ -197,6 +198,11 @@ class CameraController extends ValueNotifier { /// When null the imageFormat will fallback to the platforms default. final ImageFormatGroup? imageFormatGroup; + /// The [ImageExtension] describes the output of the raw image format. + /// + /// When null the imageFormat will fallback to the platforms default. + final ImageExtension? imageExtension; + late int _cameraId; bool _isDisposed = false; @@ -239,6 +245,7 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.initializeCamera( _cameraId, imageFormatGroup: imageFormatGroup ?? ImageFormatGroup.unknown, + imageExtension: imageExtension ?? ImageExtension.jpeg, ); value = value.copyWith( diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index d21c0f4a24c..c6cb5db61e2 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN @property(assign, nonatomic) FLTFlashMode flashMode; // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; -@property(assign, nonatomic, readonly) ImageExtension imageExtension; +@property(assign, nonatomic) ImageExtension imageExtension; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. @@ -51,6 +51,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)captureToFile:(FLTThreadSafeFlutterResult *)result; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; +- (void)setImageExtension:(ImageExtension)imageExtension; /** * Starts recording a video with an optional streaming messenger. * If the messenger is non-null then it will be called for each @@ -107,7 +108,6 @@ NS_ASSUME_NONNULL_BEGIN - (void)getMinZoomLevelWithResult:(FLTThreadSafeFlutterResult *)result; - (void)setZoomLevel:(CGFloat)zoom Result:(FLTThreadSafeFlutterResult *)result; - (void)setUpCaptureSessionForAudio; -- (void)setImageExtension:(ImageExtension)imageExtension; @end diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 6c8f0ce12aa..b621e9be70a 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -264,11 +264,13 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setHighResolutionPhotoEnabled:YES]; } - if (_imageExtension == ImageExtensionHEIC && @available(iOS 11.0, *)) { - if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { - settings = [AVCapturePhotoSettings - photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - extension = @"heic"; + if (_imageExtension == ImageExtensionHEIC) { + if (@available(iOS 11.0, *)) { + if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { + settings = [AVCapturePhotoSettings + photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + extension = @"heic"; + } } } diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h index 467c7c4844a..acc64846cb2 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam_Test.h @@ -30,9 +30,6 @@ /// True when images from the camera are being streamed. @property(assign, nonatomic) BOOL isStreamingImages; -/// The output format image capturing. -@property(assign, nonatomic) ImageExtension imageExtension; - /// A dictionary to retain all in-progress FLTSavePhotoDelegates. The key of the dictionary is the /// AVCapturePhotoSettings's uniqueID for each photo capture operation, and the value is the /// FLTSavePhotoDelegate that handles the result of each photo capture operation. Note that photo diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 5f8eb796cda..7ba1285f7e4 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -61,6 +61,10 @@ abstract class CameraPlatform extends PlatformInterface { /// On Android this defaults to ImageFormat.YUV_420_888 and applies only to the imageStream. /// On iOS this defaults to kCVPixelFormatType_32BGRA. /// On Web this parameter is currently not supported. + /// + /// [imageExtension] is used to specify the image extension used. + /// [ImageExtension.jpeg] and [ImageExtension.heic] are availables + /// only in iOS 11.0+. Future initializeCamera( int cameraId, { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, @@ -100,13 +104,11 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError( - 'onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation( - int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -143,8 +145,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -172,8 +173,7 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -272,8 +272,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError( - 'setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. From 305c3b485929533bb3ab0c1ca00301898c959636 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sat, 14 Oct 2023 18:23:34 -0300 Subject: [PATCH 28/71] improves --- .../camera/camera/lib/src/camera_controller.dart | 12 ++++++++---- .../src/platform_interface/camera_platform.dart | 15 ++++++++++----- .../lib/src/types/image_extension.dart | 8 +++++--- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index 7cef0bc54ee..98024ea9d2d 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -237,7 +237,7 @@ class CameraController extends ValueNotifier { this.resolutionPreset, { this.enableAudio = true, this.imageFormatGroup, - this.imageExtension = ImageExtension.jpeg, + this.imageExtension, }) : super(CameraValue.uninitialized(description)); /// The properties of the camera device controlled by this controller. @@ -259,9 +259,12 @@ class CameraController extends ValueNotifier { /// When null the imageFormat will fallback to the platforms default. final ImageFormatGroup? imageFormatGroup; - /// The image extension used for the camera. - /// For now only [iOS] supports this. - final ImageExtension imageExtension; + /// The [ImageExtension] describes the compression of the image. + /// + /// When null the imageExtension will fallback to the platforms default. + /// + /// Only supported on iOS for now. + final ImageExtension? imageExtension; /// The id of a camera that hasn't been initialized. @visibleForTesting @@ -334,6 +337,7 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.initializeCamera( _cameraId, imageFormatGroup: imageFormatGroup ?? ImageFormatGroup.unknown, + imageExtension: imageExtension ?? ImageExtension.jpeg, ); value = value.copyWith( diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 7ba1285f7e4..d7a84ceb954 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -104,11 +104,13 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError( + 'onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation( + int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -145,7 +147,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -173,7 +176,8 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -272,7 +276,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError( + 'setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart b/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart index 328080e08a8..bbedd79d7cd 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart @@ -3,12 +3,14 @@ // found in the LICENSE file. /// The format in which images should be returned from the camera. -/// Will works only on iOS and only iOS 11+. enum ImageExtension { - /// The default extension for the current platform. + /// This is the default value. It will return the image in JPEG format. + /// Is the widely used format for images. jpeg, - /// The efficient extension for iOS. + /// It will return the image in HEIC format. + /// HEIC is a file format name that refers to High Efficiency Image Format (HEIF). + /// Will works only iOS 11+. heic, } From e62f6d2055aa49fb39b4546c609403b4990b3baa Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 15 Oct 2023 11:34:43 -0300 Subject: [PATCH 29/71] rename extension --- packages/camera/camera/CHANGELOG.md | 2 +- .../camera/camera_avfoundation/CHANGELOG.md | 2 +- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 4 +- .../ios/Classes/CameraProperties.h | 2 +- .../ios/Classes/CameraProperties.m | 4 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 4 +- .../lib/src/avfoundation_camera.dart | 100 ++++++------------ .../camera_platform_interface/CHANGELOG.md | 2 +- .../platform_interface/camera_platform.dart | 17 ++- .../lib/src/types/image_extension.dart | 10 +- .../test/types/image_extension_test.dart | 2 +- 11 files changed, 56 insertions(+), 93 deletions(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 24e2fd83181..a8ac70a6629 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.10.6 -* Add support to HEIC format to iOS +* Add support to HEIF format to iOS ## 0.10.5+5 diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 95b9d146d0b..a8f8e444736 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Add support to HEIC format +* Add support to HEIF format ## 0.9.13+6 diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 62bde5f9cb5..a9865782294 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -99,13 +99,13 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai if (@available(iOS 11.0, *)) { XCTestExpectation *expectation = [self expectationWithDescription: - @"Test must set extension to heic if availablePhotoCodecTypes contains HEVC."]; + @"Test must set extension to heif if availablePhotoCodecTypes contains HEVC."]; dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); - [cam setImageExtension:ImageExtensionHEIC]; + [cam setImageExtension:ImageExtensionHEIF]; // Set photo settings to HEVC AVCapturePhotoSettings *settings = diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index a9fdd0a703e..953ed3d2b32 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -132,7 +132,7 @@ extern OSType FLTGetVideoFormatFromString(NSString *videoFormatString); */ typedef NS_ENUM(NSInteger, ImageExtension) { ImageExtensionJPEG, - ImageExtensionHEIC, + ImageExtensionHEIF, }; #pragma mark - image extension diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m index fdf10c2ea3c..a0a835e5596 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m @@ -155,8 +155,8 @@ OSType FLTGetVideoFormatFromString(NSString *videoFormatString) { ImageExtension FLTGetImageExtensionFromString(NSString *extensionString) { if ([extensionString isEqualToString:@"jpg"]) { return ImageExtensionJPEG; - } else if ([extensionString isEqualToString:@"heic"]) { - return ImageExtensionHEIC; + } else if ([extensionString isEqualToString:@"heif"]) { + return ImageExtensionHEIF; } else { NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index b621e9be70a..57f43acca2f 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -264,12 +264,12 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setHighResolutionPhotoEnabled:YES]; } - if (_imageExtension == ImageExtensionHEIC) { + if (_imageExtension == ImageExtensionHEIF) { if (@available(iOS 11.0, *)) { if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - extension = @"heic"; + extension = @"heif"; } } } diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index e50ee006e75..f4284e81cab 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,8 +14,7 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = - MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -29,8 +28,7 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = - 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -40,16 +38,14 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = - _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -65,14 +61,13 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -81,8 +76,7 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -98,12 +92,9 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -120,10 +111,8 @@ class AVFoundationCamera extends CameraPlatform { ImageExtension imageExtension = ImageExtension.jpeg, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel( - 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -201,8 +190,7 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream - .whereType(); + return _deviceEventStreamController.stream.whereType(); } @override @@ -212,10 +200,7 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -245,14 +230,11 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -297,22 +279,18 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { - _frameStreamController = - _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController( - {Function()? onListen}) { + StreamController _createStreamController({Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -331,17 +309,14 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -353,13 +328,11 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -368,8 +341,7 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -437,8 +409,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -514,8 +485,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -580,8 +550,8 @@ class AVFoundationCamera extends CameraPlatform { switch (imageExtension) { case ImageExtension.jpeg: return 'jpeg'; - case ImageExtension.heic: - return 'heic'; + case ImageExtension.heif: + return 'heif'; } } @@ -590,8 +560,8 @@ class AVFoundationCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -635,9 +605,7 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index e28b981c8e6..923cbd4d0bd 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.5.3 -* Add support to HEIC format to iOS +* Add support to HEIF format to iOS ## 2.5.2 diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index d7a84ceb954..3ea2b41c16c 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -63,7 +63,7 @@ abstract class CameraPlatform extends PlatformInterface { /// On Web this parameter is currently not supported. /// /// [imageExtension] is used to specify the image extension used. - /// [ImageExtension.jpeg] and [ImageExtension.heic] are availables + /// [ImageExtension.jpeg] and [ImageExtension.heif] are availables /// only in iOS 11.0+. Future initializeCamera( int cameraId, { @@ -104,13 +104,11 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError( - 'onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation( - int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -147,8 +145,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -176,8 +173,7 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -276,8 +272,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError( - 'setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart b/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart index bbedd79d7cd..e81d33edecf 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart @@ -8,10 +8,10 @@ enum ImageExtension { /// Is the widely used format for images. jpeg, - /// It will return the image in HEIC format. - /// HEIC is a file format name that refers to High Efficiency Image Format (HEIF). + /// It will return the image in HEIF format. + /// HEIF is a file format name that refers to High Efficiency Image Format (HEIF). /// Will works only iOS 11+. - heic, + heif, } /// Extension on [ImageExtension] to stringify the enum @@ -23,8 +23,8 @@ extension ImageExtensionName on ImageExtension { switch (this) { case ImageExtension.jpeg: return 'jpeg'; - case ImageExtension.heic: - return 'heic'; + case ImageExtension.heif: + return 'heif'; } } } diff --git a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart b/packages/camera/camera_platform_interface/test/types/image_extension_test.dart index 3eb286fa6c7..8661e43843e 100644 --- a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart +++ b/packages/camera/camera_platform_interface/test/types/image_extension_test.dart @@ -9,7 +9,7 @@ void main() { group('$ImageExtension tests', () { test('ImageFormat extension returns correct values', () { expect(ImageExtension.jpeg.name(), 'jpeg'); - expect(ImageExtension.heic.name(), 'heic'); + expect(ImageExtension.heif.name(), 'heif'); }); }); } From 4fc1da03c6729852680700bdedeeeb217f7baee9 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 15 Oct 2023 11:37:58 -0300 Subject: [PATCH 30/71] format --- .../lib/src/avfoundation_camera.dart | 96 ++++++++++++------- .../platform_interface/camera_platform.dart | 15 ++- 2 files changed, 74 insertions(+), 37 deletions(-) diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index f4284e81cab..90e513be3f2 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,7 +14,8 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = + MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -28,7 +29,8 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = + 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -38,14 +40,16 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = + _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -61,13 +65,14 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -76,7 +81,8 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -92,9 +98,12 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -111,8 +120,10 @@ class AVFoundationCamera extends CameraPlatform { ImageExtension imageExtension = ImageExtension.jpeg, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel( + 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -190,7 +201,8 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream.whereType(); + return _deviceEventStreamController.stream + .whereType(); } @override @@ -200,7 +212,10 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -230,11 +245,14 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -279,18 +297,22 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { - _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { + _frameStreamController = + _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController({Function()? onListen}) { + StreamController _createStreamController( + {Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -309,14 +331,17 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -328,11 +353,13 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -341,7 +368,8 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -409,7 +437,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -485,7 +514,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -560,8 +590,8 @@ class AVFoundationCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -605,7 +635,9 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 3ea2b41c16c..252ab336817 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -104,11 +104,13 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError( + 'onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation( + int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -145,7 +147,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -173,7 +176,8 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -272,7 +276,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError( + 'setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. From 3df56b381ae39c5141ffb888798b89a110b77308 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 10:22:29 -0300 Subject: [PATCH 31/71] refactor code --- .../example/integration_test/camera_test.dart | 75 +- .../ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- packages/camera/camera/lib/camera.dart | 2 +- .../camera/lib/src/camera_controller.dart | 148 ++-- .../camera/test/camera_preview_test.dart | 56 +- packages/camera/camera/test/camera_test.dart | 780 ++++++------------ .../test/android_camera_test.dart | 343 +++----- .../example/integration_test/camera_test.dart | 93 +-- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 2 +- .../example/lib/camera_controller.dart | 122 +-- .../ios/Classes/CameraPlugin.m | 5 +- .../ios/Classes/CameraProperties.h | 12 +- .../ios/Classes/CameraProperties.m | 12 +- .../camera_avfoundation/ios/Classes/FLTCam.h | 4 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 10 +- .../lib/src/avfoundation_camera.dart | 119 +-- .../test/avfoundation_camera_test.dart | 350 +++----- .../method_channel/method_channel_camera.dart | 106 +-- .../platform_interface/camera_platform.dart | 25 +- ...mage_extension.dart => output_format.dart} | 14 +- .../lib/src/types/types.dart | 2 +- .../test/events/camera_event_test.dart | 140 ++-- .../method_channel_camera_test.dart | 385 +++------ ...sion_test.dart => output_format_test.dart} | 6 +- 25 files changed, 977 insertions(+), 1838 deletions(-) rename packages/camera/camera_platform_interface/lib/src/types/{image_extension.dart => output_format.dart} (69%) rename packages/camera/camera_platform_interface/test/types/{image_extension_test.dart => output_format_test.dart} (72%) diff --git a/packages/camera/camera/example/integration_test/camera_test.dart b/packages/camera/camera/example/integration_test/camera_test.dart index 6bef30e62c2..12e294afea1 100644 --- a/packages/camera/camera/example/integration_test/camera_test.dart +++ b/packages/camera/camera/example/integration_test/camera_test.dart @@ -27,12 +27,9 @@ void main() { await testDir.delete(recursive: true); }); - final Map presetExpectedSizes = - { - ResolutionPreset.low: - Platform.isAndroid ? const Size(240, 320) : const Size(288, 352), - ResolutionPreset.medium: - Platform.isAndroid ? const Size(480, 720) : const Size(480, 640), + final Map presetExpectedSizes = { + ResolutionPreset.low: Platform.isAndroid ? const Size(240, 320) : const Size(288, 352), + ResolutionPreset.medium: Platform.isAndroid ? const Size(480, 720) : const Size(480, 640), ResolutionPreset.high: const Size(720, 1280), ResolutionPreset.veryHigh: const Size(1080, 1920), ResolutionPreset.ultraHigh: const Size(2160, 3840), @@ -45,15 +42,13 @@ void main() { bool assertExpectedDimensions(Size expectedSize, Size actual) { expect(actual.shortestSide, lessThanOrEqualTo(expectedSize.shortestSide)); expect(actual.longestSide, lessThanOrEqualTo(expectedSize.longestSide)); - return actual.shortestSide == expectedSize.shortestSide && - actual.longestSide == expectedSize.longestSide; + return actual.shortestSide == expectedSize.shortestSide && actual.longestSide == expectedSize.longestSide; } // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. - Future testCaptureImageResolution( - CameraController controller, ResolutionPreset preset) async { + Future testCaptureImageResolution(CameraController controller, ResolutionPreset preset) async { final Size expectedSize = presetExpectedSizes[preset]!; // Take Picture @@ -65,8 +60,7 @@ void main() { // Verify image dimensions are as expected expect(image, isNotNull); - return assertExpectedDimensions( - expectedSize, Size(image.height.toDouble(), image.width.toDouble())); + return assertExpectedDimensions(expectedSize, Size(image.height.toDouble(), image.width.toDouble())); } testWidgets( @@ -78,13 +72,10 @@ void main() { } for (final CameraDescription cameraDescription in cameras) { bool previousPresetExactlySupported = true; - for (final MapEntry preset - in presetExpectedSizes.entries) { - final CameraController controller = - CameraController(cameraDescription, preset.key); + for (final MapEntry preset in presetExpectedSizes.entries) { + final CameraController controller = CameraController(cameraDescription, preset.key); await controller.initialize(); - final bool presetExactlySupported = - await testCaptureImageResolution(controller, preset.key); + final bool presetExactlySupported = await testCaptureImageResolution(controller, preset.key); assert(!(!previousPresetExactlySupported && presetExactlySupported), 'The camera took higher resolution pictures at a lower resolution.'); previousPresetExactlySupported = presetExactlySupported; @@ -99,8 +90,7 @@ void main() { // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. - Future testCaptureVideoResolution( - CameraController controller, ResolutionPreset preset) async { + Future testCaptureVideoResolution(CameraController controller, ResolutionPreset preset) async { final Size expectedSize = presetExpectedSizes[preset]!; // Take Video @@ -110,15 +100,13 @@ void main() { // Load video metadata final File videoFile = File(file.path); - final VideoPlayerController videoController = - VideoPlayerController.file(videoFile); + final VideoPlayerController videoController = VideoPlayerController.file(videoFile); await videoController.initialize(); final Size video = videoController.value.size; // Verify image dimensions are as expected expect(video, isNotNull); - return assertExpectedDimensions( - expectedSize, Size(video.height, video.width)); + return assertExpectedDimensions(expectedSize, Size(video.height, video.width)); } testWidgets( @@ -130,14 +118,11 @@ void main() { } for (final CameraDescription cameraDescription in cameras) { bool previousPresetExactlySupported = true; - for (final MapEntry preset - in presetExpectedSizes.entries) { - final CameraController controller = - CameraController(cameraDescription, preset.key); + for (final MapEntry preset in presetExpectedSizes.entries) { + final CameraController controller = CameraController(cameraDescription, preset.key); await controller.initialize(); await controller.prepareForVideoRecording(); - final bool presetExactlySupported = - await testCaptureVideoResolution(controller, preset.key); + final bool presetExactlySupported = await testCaptureVideoResolution(controller, preset.key); assert(!(!previousPresetExactlySupported && presetExactlySupported), 'The camera took higher resolution pictures at a lower resolution.'); previousPresetExactlySupported = presetExactlySupported; @@ -188,8 +173,7 @@ void main() { sleep(const Duration(milliseconds: 500)); final XFile file = await controller.stopVideoRecording(); - final int recordingTime = - DateTime.now().millisecondsSinceEpoch - recordingStart; + final int recordingTime = DateTime.now().millisecondsSinceEpoch - recordingStart; final File videoFile = File(file.path); final VideoPlayerController videoController = VideoPlayerController.file( @@ -240,8 +224,7 @@ void main() { ); /// Start streaming with specifying the ImageFormatGroup. - Future startStreaming(List cameras, - ImageFormatGroup? imageFormatGroup) async { + Future startStreaming(List cameras, ImageFormatGroup? imageFormatGroup) async { final CameraController controller = CameraController( cameras.first, ResolutionPreset.low, @@ -329,4 +312,28 @@ void main() { }, skip: !Platform.isIOS, ); + + //test outputFormat for image + testWidgets( + 'Capture image with outputFormat', + (WidgetTester tester) async { + final List cameras = await availableCameras(); + if (cameras.isEmpty) { + return; + } + for (final CameraDescription cameraDescription in cameras) { + final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); + + await controller.setOutputFormat(OutputFormat.heif); + await controller.initialize(); + + final XFile file = await controller.takePicture(); + final File fileImage = File(file.path); + final Image image = await decodeImageFromList(fileImage.readAsBytesSync()); + + expect(image, isNotNull); + } + }, + skip: !Platform.isIOS, + ); } diff --git a/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj index 59fa9076ed8..a9ff9e273fd 100644 --- a/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj @@ -169,7 +169,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1300; + LastUpgradeCheck = 1430; ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/packages/camera/camera/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/camera/camera/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index f4b3c109900..1ff4b573d76 100644 --- a/packages/camera/camera/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/camera/camera/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ { this.resolutionPreset, { this.enableAudio = true, this.imageFormatGroup, - this.imageExtension, + this.outputFormat, }) : super(CameraValue.uninitialized(description)); /// The properties of the camera device controlled by this controller. @@ -259,12 +254,12 @@ class CameraController extends ValueNotifier { /// When null the imageFormat will fallback to the platforms default. final ImageFormatGroup? imageFormatGroup; - /// The [ImageExtension] describes the compression of the image. + /// The [OutputFormat] describes the compression of the image. /// - /// When null the imageExtension will fallback to the platforms default. + /// When null the outputFormat will fallback to the platforms default. /// /// Only supported on iOS for now. - final ImageExtension? imageExtension; + final OutputFormat? outputFormat; /// The id of a camera that hasn't been initialized. @visibleForTesting @@ -277,8 +272,7 @@ class CameraController extends ValueNotifier { // just called). If the controller has not been initialized at least once, // this value is null. Future? _initializeFuture; - StreamSubscription? - _deviceOrientationSubscription; + StreamSubscription? _deviceOrientationSubscription; /// Checks whether [CameraController.dispose] has completed successfully. /// @@ -310,12 +304,10 @@ class CameraController extends ValueNotifier { _initializeFuture = initializeCompleter.future; try { - final Completer initializeCompleter = - Completer(); + final Completer initializeCompleter = Completer(); - _deviceOrientationSubscription ??= CameraPlatform.instance - .onDeviceOrientationChanged() - .listen((DeviceOrientationChangedEvent event) { + _deviceOrientationSubscription ??= + CameraPlatform.instance.onDeviceOrientationChanged().listen((DeviceOrientationChangedEvent event) { value = value.copyWith( deviceOrientation: event.orientation, ); @@ -327,35 +319,28 @@ class CameraController extends ValueNotifier { enableAudio: enableAudio, ); - _unawaited(CameraPlatform.instance - .onCameraInitialized(_cameraId) - .first - .then((CameraInitializedEvent event) { + _unawaited(CameraPlatform.instance.onCameraInitialized(_cameraId).first.then((CameraInitializedEvent event) { initializeCompleter.complete(event); })); await CameraPlatform.instance.initializeCamera( _cameraId, imageFormatGroup: imageFormatGroup ?? ImageFormatGroup.unknown, - imageExtension: imageExtension ?? ImageExtension.jpeg, ); value = value.copyWith( isInitialized: true, description: description, - previewSize: await initializeCompleter.future - .then((CameraInitializedEvent event) => Size( - event.previewWidth, - event.previewHeight, - )), - exposureMode: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.exposureMode), - focusMode: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.focusMode), - exposurePointSupported: await initializeCompleter.future.then( - (CameraInitializedEvent event) => event.exposurePointSupported), - focusPointSupported: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.focusPointSupported), + previewSize: await initializeCompleter.future.then((CameraInitializedEvent event) => Size( + event.previewWidth, + event.previewHeight, + )), + exposureMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposureMode), + focusMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusMode), + exposurePointSupported: + await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposurePointSupported), + focusPointSupported: + await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusPointSupported), ); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -388,8 +373,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: Optional.of( - value.lockedCaptureOrientation ?? value.deviceOrientation)); + previewPauseOrientation: + Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -402,9 +387,8 @@ class CameraController extends ValueNotifier { } try { await CameraPlatform.instance.resumePreview(_cameraId); - value = value.copyWith( - isPreviewPaused: false, - previewPauseOrientation: const Optional.absent()); + value = + value.copyWith(isPreviewPaused: false, previewPauseOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -467,8 +451,7 @@ class CameraController extends ValueNotifier { /// // TODO(bmparr): Add settings for resolution and fps. Future startImageStream(onLatestImageAvailable onAvailable) async { - assert(defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('startImageStream'); if (value.isRecordingVideo) { throw CameraException( @@ -484,9 +467,8 @@ class CameraController extends ValueNotifier { } try { - _imageStreamSubscription = CameraPlatform.instance - .onStreamedFrameAvailable(_cameraId) - .listen((CameraImageData imageData) { + _imageStreamSubscription = + CameraPlatform.instance.onStreamedFrameAvailable(_cameraId).listen((CameraImageData imageData) { onAvailable(CameraImage.fromPlatformInterface(imageData)); }); value = value.copyWith(isStreamingImages: true); @@ -503,8 +485,7 @@ class CameraController extends ValueNotifier { /// The `stopImageStream` method is only available on Android and iOS (other /// platforms won't be supported in current setup). Future stopImageStream() async { - assert(defaultTargetPlatform == TargetPlatform.android || - defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('stopImageStream'); if (!value.isStreamingImages) { throw CameraException( @@ -529,8 +510,7 @@ class CameraController extends ValueNotifier { /// /// The video is returned as a [XFile] after calling [stopVideoRecording]. /// Throws a [CameraException] if the capture fails. - Future startVideoRecording( - {onLatestImageAvailable? onAvailable}) async { + Future startVideoRecording({onLatestImageAvailable? onAvailable}) async { _throwIfNotInitialized('startVideoRecording'); if (value.isRecordingVideo) { throw CameraException( @@ -547,13 +527,12 @@ class CameraController extends ValueNotifier { } try { - await CameraPlatform.instance.startVideoCapturing( - VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); + await CameraPlatform.instance.startVideoCapturing(VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, - recordingOrientation: Optional.of( - value.lockedCaptureOrientation ?? value.deviceOrientation), + recordingOrientation: + Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation), isStreamingImages: onAvailable != null); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -577,8 +556,7 @@ class CameraController extends ValueNotifier { } try { - final XFile file = - await CameraPlatform.instance.stopVideoRecording(_cameraId); + final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); value = value.copyWith( isRecordingVideo: false, recordingOrientation: const Optional.absent(), @@ -696,10 +674,8 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the exposure point to it's default /// value. Future setExposurePoint(Offset? point) async { - if (point != null && - (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError( - 'The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); } try { @@ -763,8 +739,7 @@ class CameraController extends ValueNotifier { Future setExposureOffset(double offset) async { _throwIfNotInitialized('setExposureOffset'); // Check if offset is in range - final List range = await Future.wait( - >[getMinExposureOffset(), getMaxExposureOffset()]); + final List range = await Future.wait(>[getMinExposureOffset(), getMaxExposureOffset()]); if (offset < range[0] || offset > range[1]) { throw CameraException( 'exposureOffsetOutOfBounds', @@ -797,11 +772,9 @@ class CameraController extends ValueNotifier { /// If [orientation] is omitted, the current device orientation is used. Future lockCaptureOrientation([DeviceOrientation? orientation]) async { try { - await CameraPlatform.instance.lockCaptureOrientation( - _cameraId, orientation ?? value.deviceOrientation); + await CameraPlatform.instance.lockCaptureOrientation(_cameraId, orientation ?? value.deviceOrientation); value = value.copyWith( - lockedCaptureOrientation: Optional.of( - orientation ?? value.deviceOrientation)); + lockedCaptureOrientation: Optional.of(orientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -821,8 +794,7 @@ class CameraController extends ValueNotifier { Future unlockCaptureOrientation() async { try { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith( - lockedCaptureOrientation: const Optional.absent()); + value = value.copyWith(lockedCaptureOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -833,10 +805,8 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the focus point to it's default /// value. Future setFocusPoint(Offset? point) async { - if (point != null && - (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError( - 'The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); } try { await CameraPlatform.instance.setFocusPoint( @@ -853,6 +823,17 @@ class CameraController extends ValueNotifier { } } + /// Sets the output format for the camera. + /// + /// If [format] is omitted, the default output format is used. + Future setOutputFormat(OutputFormat format) async { + try { + await CameraPlatform.instance.setOutputFormat(_cameraId, format); + } on PlatformException catch (e) { + throw CameraException(e.code, e.message); + } + } + /// Releases the resources of this camera. @override Future dispose() async { @@ -967,9 +948,7 @@ class Optional extends IterableBase { /// /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. Optional transform(S Function(T value) transformer) { - return _value == null - ? Optional.absent() - : Optional.of(transformer(_value as T)); + return _value == null ? Optional.absent() : Optional.of(transformer(_value as T)); } /// Transforms the Optional value. @@ -978,14 +957,11 @@ class Optional extends IterableBase { /// /// Returns [absent()] if the transformer returns `null`. Optional transformNullable(S? Function(T value) transformer) { - return _value == null - ? Optional.absent() - : Optional.fromNullable(transformer(_value as T)); + return _value == null ? Optional.absent() : Optional.fromNullable(transformer(_value as T)); } @override - Iterator get iterator => - isPresent ? [_value as T].iterator : Iterable.empty().iterator; + Iterator get iterator => isPresent ? [_value as T].iterator : Iterable.empty().iterator; /// Delegates to the underlying [value] hashCode. @override @@ -997,8 +973,6 @@ class Optional extends IterableBase { @override String toString() { - return _value == null - ? 'Optional { absent }' - : 'Optional { value: $_value }'; + return _value == null ? 'Optional { absent }' : 'Optional { value: $_value }'; } } diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index 33a6d7c2dcb..b2198bd273d 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -9,12 +9,11 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; -class FakeController extends ValueNotifier - implements CameraController { +class FakeController extends ValueNotifier implements CameraController { FakeController() : super(const CameraValue.uninitialized(fakeDescription)); - static const CameraDescription fakeDescription = CameraDescription( - name: '', lensDirection: CameraLensDirection.back, sensorOrientation: 0); + static const CameraDescription fakeDescription = + CameraDescription(name: '', lensDirection: CameraLensDirection.back, sensorOrientation: 0); @override Future dispose() async { @@ -96,8 +95,7 @@ class FakeController extends ValueNotifier Future startImageStream(onLatestImageAvailable onAvailable) async {} @override - Future startVideoRecording( - {onLatestImageAvailable? onAvailable}) async {} + Future startVideoRecording({onLatestImageAvailable? onAvailable}) async {} @override Future stopImageStream() async {} @@ -124,14 +122,15 @@ class FakeController extends ValueNotifier CameraDescription get description => value.description; @override - ImageExtension get imageExtension => ImageExtension.jpeg; + OutputFormat? get outputFormat => null; + + @override + Future setOutputFormat(OutputFormat format) async {} } void main() { group('RotatedBox (Android only)', () { - testWidgets( - 'when recording rotatedBox should turn according to recording orientation', - ( + testWidgets('when recording rotatedBox should turn according to recording orientation', ( WidgetTester tester, ) async { debugDefaultTargetPlatformOverride = TargetPlatform.android; @@ -141,11 +140,8 @@ void main() { isInitialized: true, isRecordingVideo: true, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: - const Optional.fromNullable( - DeviceOrientation.landscapeRight), - recordingOrientation: const Optional.fromNullable( - DeviceOrientation.landscapeLeft), + lockedCaptureOrientation: const Optional.fromNullable(DeviceOrientation.landscapeRight), + recordingOrientation: const Optional.fromNullable(DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); @@ -157,16 +153,13 @@ void main() { ); expect(find.byType(RotatedBox), findsOneWidget); - final RotatedBox rotatedBox = - tester.widget(find.byType(RotatedBox)); + final RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); expect(rotatedBox.quarterTurns, 3); debugDefaultTargetPlatformOverride = null; }); - testWidgets( - 'when orientation locked rotatedBox should turn according to locked orientation', - ( + testWidgets('when orientation locked rotatedBox should turn according to locked orientation', ( WidgetTester tester, ) async { debugDefaultTargetPlatformOverride = TargetPlatform.android; @@ -175,11 +168,8 @@ void main() { controller.value = controller.value.copyWith( isInitialized: true, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: - const Optional.fromNullable( - DeviceOrientation.landscapeRight), - recordingOrientation: const Optional.fromNullable( - DeviceOrientation.landscapeLeft), + lockedCaptureOrientation: const Optional.fromNullable(DeviceOrientation.landscapeRight), + recordingOrientation: const Optional.fromNullable(DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); @@ -191,16 +181,13 @@ void main() { ); expect(find.byType(RotatedBox), findsOneWidget); - final RotatedBox rotatedBox = - tester.widget(find.byType(RotatedBox)); + final RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); expect(rotatedBox.quarterTurns, 1); debugDefaultTargetPlatformOverride = null; }); - testWidgets( - 'when not locked and not recording rotatedBox should turn according to device orientation', - ( + testWidgets('when not locked and not recording rotatedBox should turn according to device orientation', ( WidgetTester tester, ) async { debugDefaultTargetPlatformOverride = TargetPlatform.android; @@ -209,8 +196,7 @@ void main() { controller.value = controller.value.copyWith( isInitialized: true, deviceOrientation: DeviceOrientation.portraitUp, - recordingOrientation: const Optional.fromNullable( - DeviceOrientation.landscapeLeft), + recordingOrientation: const Optional.fromNullable(DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); @@ -222,16 +208,14 @@ void main() { ); expect(find.byType(RotatedBox), findsOneWidget); - final RotatedBox rotatedBox = - tester.widget(find.byType(RotatedBox)); + final RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); expect(rotatedBox.quarterTurns, 0); debugDefaultTargetPlatformOverride = null; }); }, skip: kIsWeb); - testWidgets('when not on Android there should not be a rotated box', - (WidgetTester tester) async { + testWidgets('when not on Android there should not be a rotated box', (WidgetTester tester) async { debugDefaultTargetPlatformOverride = TargetPlatform.iOS; final FakeController controller = FakeController(); controller.value = controller.value.copyWith( diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index 021fc17410e..e220d283289 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -15,20 +15,13 @@ import 'package:mockito/mockito.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; List get mockAvailableCameras => [ - const CameraDescription( - name: 'camBack', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), - const CameraDescription( - name: 'camFront', - lensDirection: CameraLensDirection.front, - sensorOrientation: 180), + const CameraDescription(name: 'camBack', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription(name: 'camFront', lensDirection: CameraLensDirection.front, sensorOrientation: 180), ]; int get mockInitializeCamera => 13; -CameraInitializedEvent get mockOnCameraInitializedEvent => - const CameraInitializedEvent( +CameraInitializedEvent get mockOnCameraInitializedEvent => const CameraInitializedEvent( 13, 75, 75, @@ -43,8 +36,7 @@ DeviceOrientationChangedEvent get mockOnDeviceOrientationChangedEvent => CameraClosingEvent get mockOnCameraClosingEvent => const CameraClosingEvent(13); -CameraErrorEvent get mockOnCameraErrorEvent => - const CameraErrorEvent(13, 'closing'); +CameraErrorEvent get mockOnCameraErrorEvent => const CameraErrorEvent(13, 'closing'); XFile mockTakePicture = XFile('foo/bar.png'); @@ -56,8 +48,7 @@ void main() { WidgetsFlutterBinding.ensureInitialized(); group('camera', () { - test('debugCheckIsDisposed should not throw assertion error when disposed', - () { + test('debugCheckIsDisposed should not throw assertion error when disposed', () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -69,8 +60,7 @@ void main() { expect(controller.debugCheckIsDisposed, returnsNormally); }); - test('debugCheckIsDisposed should throw assertion error when not disposed', - () { + test('debugCheckIsDisposed should throw assertion error when not disposed', () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -99,10 +89,7 @@ void main() { test('Can be initialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -113,10 +100,7 @@ void main() { test('can be disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -131,10 +115,7 @@ void main() { test('initialize() throws CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -155,13 +136,9 @@ void main() { ))); }); - test('initialize() throws $CameraException on $PlatformException ', - () async { + test('initialize() throws $CameraException on $PlatformException ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); mockPlatformException = true; @@ -179,21 +156,15 @@ void main() { test('initialize() sets imageFormat', () async { debugDefaultTargetPlatformOverride = TargetPlatform.android; final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max, imageFormatGroup: ImageFormatGroup.yuv420, ); await cameraController.initialize(); - verify(CameraPlatform.instance - .initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)) - .called(1); + verify(CameraPlatform.instance.initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)).called(1); }); - test('setDescription waits for initialize before calling dispose', - () async { + test('setDescription waits for initialize before calling dispose', () async { final CameraController cameraController = CameraController( const CameraDescription( name: 'cam', @@ -215,10 +186,7 @@ void main() { unawaited(cameraController.initialize()); final Future setDescriptionFuture = cameraController.setDescription( - const CameraDescription( - name: 'cam2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 90), + const CameraDescription(name: 'cam2', lensDirection: CameraLensDirection.front, sensorOrientation: 90), ); verifyNever(CameraPlatform.instance.dispose(mockInitializeCamera)); @@ -230,10 +198,7 @@ void main() { test('prepareForVideoRecording() calls $CameraPlatform ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -244,10 +209,7 @@ void main() { test('takePicture() throws $CameraException when uninitialized ', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( cameraController.takePicture(), @@ -267,18 +229,13 @@ void main() { ); }); - test('takePicture() throws $CameraException when takePicture is true', - () async { + test('takePicture() throws $CameraException when takePicture is true', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isTakingPicture: true); + cameraController.value = cameraController.value.copyWith(isTakingPicture: true); expect( cameraController.takePicture(), throwsA(isA().having( @@ -290,10 +247,7 @@ void main() { test('takePicture() returns $XFile', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); final XFile xFile = await cameraController.takePicture(); @@ -301,13 +255,9 @@ void main() { expect(xFile.path, mockTakePicture.path); }); - test('takePicture() throws $CameraException on $PlatformException', - () async { + test('takePicture() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -322,13 +272,9 @@ void main() { mockPlatformException = false; }); - test('startVideoRecording() throws $CameraException when uninitialized', - () async { + test('startVideoRecording() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -348,19 +294,14 @@ void main() { ), ); }); - test('startVideoRecording() throws $CameraException when recording videos', - () async { + test('startVideoRecording() throws $CameraException when recording videos', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isRecordingVideo: true); + cameraController.value = cameraController.value.copyWith(isRecordingVideo: true); expect( cameraController.startVideoRecording(), @@ -371,13 +312,9 @@ void main() { ))); }); - test('getMaxZoomLevel() throws $CameraException when uninitialized', - () async { + test('getMaxZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -400,10 +337,7 @@ void main() { test('getMaxZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -427,29 +361,20 @@ void main() { ); }); - test( - 'getMaxZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('getMaxZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) - .thenThrow(CameraException( + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMaxZoomLevel, - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -458,27 +383,19 @@ void main() { test('getMaxZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) - .thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMaxZoomLevel(); expect(maxZoomLevel, 42.0); }); - test('getMinZoomLevel() throws $CameraException when uninitialized', - () async { + test('getMinZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -501,10 +418,7 @@ void main() { test('getMinZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -528,29 +442,20 @@ void main() { ); }); - test( - 'getMinZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('getMinZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) - .thenThrow(CameraException( + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMinZoomLevel, - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -559,15 +464,11 @@ void main() { test('getMinZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) - .thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMinZoomLevel(); expect(maxZoomLevel, 42.0); @@ -575,10 +476,7 @@ void main() { test('setZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); expect( @@ -601,10 +499,7 @@ void main() { test('setZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -628,29 +523,20 @@ void main() { ); }); - test( - 'setZoomLevel() throws $CameraException when a platform exception occured.', - () async { + test('setZoomLevel() throws $CameraException when a platform exception occured.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) - .thenThrow(CameraException( + when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( () => cameraController.setZoomLevel(42), - throwsA(isA() - .having( - (CameraException error) => error.code, 'code', 'TEST_ERROR') - .having( + throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -659,52 +545,35 @@ void main() { reset(CameraPlatform.instance); }); - test( - 'setZoomLevel() completes and calls method channel with correct value.', - () async { + test('setZoomLevel() completes and calls method channel with correct value.', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setZoomLevel(42.0); - verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) - .called(1); + verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).called(1); }); test('setFlashMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setFlashMode(FlashMode.always); - verify(CameraPlatform.instance - .setFlashMode(cameraController.cameraId, FlashMode.always)) - .called(1); + verify(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).called(1); }); - test('setFlashMode() throws $CameraException on $PlatformException', - () async { + test('setFlashMode() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .setFlashMode(cameraController.cameraId, FlashMode.always)) - .thenThrow( + when(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -722,33 +591,22 @@ void main() { test('setExposureMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposureMode(ExposureMode.auto); - verify(CameraPlatform.instance - .setExposureMode(cameraController.cameraId, ExposureMode.auto)) - .called(1); + verify(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).called(1); }); - test('setExposureMode() throws $CameraException on $PlatformException', - () async { + test('setExposureMode() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .setExposureMode(cameraController.cameraId, ExposureMode.auto)) - .thenThrow( + when(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -766,32 +624,23 @@ void main() { test('setExposurePoint() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposurePoint(const Offset(0.5, 0.5)); - verify(CameraPlatform.instance.setExposurePoint( - cameraController.cameraId, const Point(0.5, 0.5))) + verify(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) .called(1); }); - test('setExposurePoint() throws $CameraException on $PlatformException', - () async { + test('setExposurePoint() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposurePoint( - cameraController.cameraId, const Point(0.5, 0.5))) + when(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -810,37 +659,25 @@ void main() { test('getMinExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getMinExposureOffset(); - verify(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).called(1); }); - test('getMinExposureOffset() throws $CameraException on $PlatformException', - () async { + test('getMinExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -858,37 +695,25 @@ void main() { test('getMaxExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(1.0)); await cameraController.getMaxExposureOffset(); - verify(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).called(1); }); - test('getMaxExposureOffset() throws $CameraException on $PlatformException', - () async { + test('getMaxExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -906,38 +731,25 @@ void main() { test('getExposureOffsetStepSize() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getExposureOffsetStepSize(); - verify(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).called(1); }); - test( - 'getExposureOffsetStepSize() throws $CameraException on $PlatformException', - () async { + test('getExposureOffsetStepSize() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -955,53 +767,28 @@ void main() { test('setExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenAnswer((_) async => 1.0); await cameraController.setExposureOffset(1.0); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).called(1); }); - test('setExposureOffset() throws $CameraException on $PlatformException', - () async { + test('setExposureOffset() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.0)) - .thenThrow( + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -1017,34 +804,17 @@ void main() { ))); }); - test( - 'setExposureOffset() throws $CameraException when offset is out of bounds', - () async { + test('setExposureOffset() throws $CameraException when offset is out of bounds', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.0); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 2.0); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 1.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 2.0)) - .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).thenAnswer((_) async => 0.0); expect( cameraController.setExposureOffset(3.0), @@ -1065,56 +835,27 @@ void main() { await cameraController.setExposureOffset(-1.0); await cameraController.setExposureOffset(2.0); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .called(1); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.0)) - .called(1); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 2.0)) - .called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).called(1); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).called(1); }); test('setExposureOffset() rounds offset to nearest step', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .getMinExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => -1.2); - when(CameraPlatform.instance - .getMaxExposureOffset(cameraController.cameraId)) - .thenAnswer((_) async => 1.2); - when(CameraPlatform.instance - .getExposureOffsetStepSize(cameraController.cameraId)) - .thenAnswer((_) async => 0.4); - - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -1.2)) - .thenAnswer((_) async => -1.2); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.8)) - .thenAnswer((_) async => -0.8); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.4)) - .thenAnswer((_) async => -0.4); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .thenAnswer((_) async => 0.0); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.4)) - .thenAnswer((_) async => 0.4); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.8)) - .thenAnswer((_) async => 0.8); - when(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 1.2)) - .thenAnswer((_) async => 1.2); + when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.2); + when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 1.2); + when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 0.4); + + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.2)).thenAnswer((_) async => -1.2); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).thenAnswer((_) async => -0.8); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).thenAnswer((_) async => -0.4); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).thenAnswer((_) async => 0.4); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).thenAnswer((_) async => 0.8); + when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.2)).thenAnswer((_) async => 1.2); await cameraController.setExposureOffset(1.2); await cameraController.setExposureOffset(-1.2); @@ -1133,97 +874,62 @@ void main() { await cameraController.setExposureOffset(-0.6); await cameraController.setExposureOffset(-0.7); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.8)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.8)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.0)) - .called(2); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, 0.4)) - .called(4); - verify(CameraPlatform.instance - .setExposureOffset(cameraController.cameraId, -0.4)) - .called(4); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(2); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).called(4); + verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).called(4); }); test('pausePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value - .copyWith(deviceOrientation: DeviceOrientation.portraitUp); + cameraController.value = cameraController.value.copyWith(deviceOrientation: DeviceOrientation.portraitUp); await cameraController.pausePreview(); - verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)).called(1); expect(cameraController.value.isPreviewPaused, equals(true)); - expect(cameraController.value.previewPauseOrientation, - DeviceOrientation.portraitUp); + expect(cameraController.value.previewPauseOrientation, DeviceOrientation.portraitUp); }); - test('pausePreview() does not call $CameraPlatform when already paused', - () async { + test('pausePreview() does not call $CameraPlatform when already paused', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); await cameraController.pausePreview(); - verifyNever( - CameraPlatform.instance.pausePreview(cameraController.cameraId)); + verifyNever(CameraPlatform.instance.pausePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(true)); }); - test( - 'pausePreview() sets previewPauseOrientation according to locked orientation', - () async { + test('pausePreview() sets previewPauseOrientation according to locked orientation', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); cameraController.value = cameraController.value.copyWith( isPreviewPaused: false, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: - Optional.of(DeviceOrientation.landscapeRight)); + lockedCaptureOrientation: Optional.of(DeviceOrientation.landscapeRight)); await cameraController.pausePreview(); - expect(cameraController.value.deviceOrientation, - equals(DeviceOrientation.portraitUp)); - expect(cameraController.value.previewPauseOrientation, - equals(DeviceOrientation.landscapeRight)); + expect(cameraController.value.deviceOrientation, equals(DeviceOrientation.portraitUp)); + expect(cameraController.value.previewPauseOrientation, equals(DeviceOrientation.landscapeRight)); }); - test('pausePreview() throws $CameraException on $PlatformException', - () async { + test('pausePreview() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.pausePreview(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.pausePreview(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1241,54 +947,37 @@ void main() { test('resumePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); await cameraController.resumePreview(); - verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)).called(1); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() does not call $CameraPlatform when not paused', - () async { + test('resumePreview() does not call $CameraPlatform when not paused', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: false); + cameraController.value = cameraController.value.copyWith(isPreviewPaused: false); await cameraController.resumePreview(); - verifyNever( - CameraPlatform.instance.resumePreview(cameraController.cameraId)); + verifyNever(CameraPlatform.instance.resumePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() throws $CameraException on $PlatformException', - () async { + test('resumePreview() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = - cameraController.value.copyWith(isPreviewPaused: true); - when(CameraPlatform.instance.resumePreview(cameraController.cameraId)) - .thenThrow( + cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + when(CameraPlatform.instance.resumePreview(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1306,41 +995,28 @@ void main() { test('lockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.lockCaptureOrientation(); - expect(cameraController.value.lockedCaptureOrientation, - equals(DeviceOrientation.portraitUp)); - await cameraController - .lockCaptureOrientation(DeviceOrientation.landscapeRight); - expect(cameraController.value.lockedCaptureOrientation, - equals(DeviceOrientation.landscapeRight)); - - verify(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.portraitUp)) + expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.portraitUp)); + await cameraController.lockCaptureOrientation(DeviceOrientation.landscapeRight); + expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.landscapeRight)); + + verify(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) .called(1); - verify(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.landscapeRight)) + verify(CameraPlatform.instance + .lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.landscapeRight)) .called(1); }); - test( - 'lockCaptureOrientation() throws $CameraException on $PlatformException', - () async { + test('lockCaptureOrientation() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.lockCaptureOrientation( - cameraController.cameraId, DeviceOrientation.portraitUp)) + when(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -1359,34 +1035,22 @@ void main() { test('unlockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.unlockCaptureOrientation(); expect(cameraController.value.lockedCaptureOrientation, equals(null)); - verify(CameraPlatform.instance - .unlockCaptureOrientation(cameraController.cameraId)) - .called(1); + verify(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).called(1); }); - test( - 'unlockCaptureOrientation() throws $CameraException on $PlatformException', - () async { + test('unlockCaptureOrientation() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.back, - sensorOrientation: 90), + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance - .unlockCaptureOrientation(cameraController.cameraId)) - .thenThrow( + when(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1401,17 +1065,47 @@ void main() { 'This is a test error message', ))); }); + + test('setOutputFormat() calls $CameraPlatform', () async { + final CameraController cameraController = CameraController( + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.front, sensorOrientation: 90), + ResolutionPreset.max); + await cameraController.initialize(); + + await cameraController.setOutputFormat(OutputFormat.jpeg); + + verify(CameraPlatform.instance.setOutputFormat(cameraController.cameraId, OutputFormat.jpeg)).called(1); + }); + + test('setOutputFormat() throws $CameraException on $PlatformException', () async { + final CameraController cameraController = CameraController( + const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.front, sensorOrientation: 90), + ResolutionPreset.max); + await cameraController.initialize(); + + when(CameraPlatform.instance.setOutputFormat(cameraController.cameraId, OutputFormat.jpeg)).thenThrow( + PlatformException( + code: 'TEST_ERROR', + message: 'This is a test error message', + ), + ); + + expect( + cameraController.setOutputFormat(OutputFormat.jpeg), + throwsA(isA().having( + (CameraException error) => error.description, + 'TEST_ERROR', + 'This is a test error message', + ))); + }); }); } -class MockCameraPlatform extends Mock - with MockPlatformInterfaceMixin - implements CameraPlatform { +class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements CameraPlatform { @override Future initializeCamera( int? cameraId, { ImageFormatGroup? imageFormatGroup = ImageFormatGroup.unknown, - ImageExtension imageExtension = ImageExtension.jpeg, }) async => super.noSuchMethod(Invocation.method( #initializeCamera, @@ -1427,8 +1121,7 @@ class MockCameraPlatform extends Mock } @override - Future> availableCameras() => - Future>.value(mockAvailableCameras); + Future> availableCameras() => Future>.value(mockAvailableCameras); @override Future createCamera( @@ -1449,54 +1142,45 @@ class MockCameraPlatform extends Mock Stream.value(mockOnCameraClosingEvent); @override - Stream onCameraError(int cameraId) => - Stream.value(mockOnCameraErrorEvent); + Stream onCameraError(int cameraId) => Stream.value(mockOnCameraErrorEvent); @override Stream onDeviceOrientationChanged() => - Stream.value( - mockOnDeviceOrientationChangedEvent); + Stream.value(mockOnDeviceOrientationChangedEvent); @override - Future takePicture(int cameraId, - {ImageExtension imageExtension = ImageExtension.jpeg}) => - mockPlatformException - ? throw PlatformException(code: 'foo', message: 'bar') - : Future.value(mockTakePicture); + Future takePicture(int cameraId) => mockPlatformException + ? throw PlatformException(code: 'foo', message: 'bar') + : Future.value(mockTakePicture); @override Future prepareForVideoRecording() async => super.noSuchMethod(Invocation.method(#prepareForVideoRecording, null)); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) => + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) => Future.value(mockVideoRecordingXFile); @override Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } @override - Future lockCaptureOrientation( - int? cameraId, DeviceOrientation? orientation) async => - super.noSuchMethod(Invocation.method( - #lockCaptureOrientation, [cameraId, orientation])); + Future lockCaptureOrientation(int? cameraId, DeviceOrientation? orientation) async => + super.noSuchMethod(Invocation.method(#lockCaptureOrientation, [cameraId, orientation])); @override Future unlockCaptureOrientation(int? cameraId) async => - super.noSuchMethod( - Invocation.method(#unlockCaptureOrientation, [cameraId])); + super.noSuchMethod(Invocation.method(#unlockCaptureOrientation, [cameraId])); @override Future pausePreview(int? cameraId) async => super.noSuchMethod(Invocation.method(#pausePreview, [cameraId])); @override - Future resumePreview(int? cameraId) async => super - .noSuchMethod(Invocation.method(#resumePreview, [cameraId])); + Future resumePreview(int? cameraId) async => + super.noSuchMethod(Invocation.method(#resumePreview, [cameraId])); @override Future getMaxZoomLevel(int? cameraId) async => super.noSuchMethod( @@ -1512,51 +1196,47 @@ class MockCameraPlatform extends Mock @override Future setZoomLevel(int? cameraId, double? zoom) async => - super.noSuchMethod( - Invocation.method(#setZoomLevel, [cameraId, zoom])); + super.noSuchMethod(Invocation.method(#setZoomLevel, [cameraId, zoom])); @override Future setFlashMode(int? cameraId, FlashMode? mode) async => - super.noSuchMethod( - Invocation.method(#setFlashMode, [cameraId, mode])); + super.noSuchMethod(Invocation.method(#setFlashMode, [cameraId, mode])); @override Future setExposureMode(int? cameraId, ExposureMode? mode) async => - super.noSuchMethod( - Invocation.method(#setExposureMode, [cameraId, mode])); + super.noSuchMethod(Invocation.method(#setExposureMode, [cameraId, mode])); @override Future setExposurePoint(int? cameraId, Point? point) async => - super.noSuchMethod( - Invocation.method(#setExposurePoint, [cameraId, point])); + super.noSuchMethod(Invocation.method(#setExposurePoint, [cameraId, point])); @override - Future getMinExposureOffset(int? cameraId) async => - super.noSuchMethod( + Future getMinExposureOffset(int? cameraId) async => super.noSuchMethod( Invocation.method(#getMinExposureOffset, [cameraId]), returnValue: Future.value(0.0), ) as Future; @override - Future getMaxExposureOffset(int? cameraId) async => - super.noSuchMethod( + Future getMaxExposureOffset(int? cameraId) async => super.noSuchMethod( Invocation.method(#getMaxExposureOffset, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future getExposureOffsetStepSize(int? cameraId) async => - super.noSuchMethod( + Future getExposureOffsetStepSize(int? cameraId) async => super.noSuchMethod( Invocation.method(#getExposureOffsetStepSize, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future setExposureOffset(int? cameraId, double? offset) async => - super.noSuchMethod( + Future setExposureOffset(int? cameraId, double? offset) async => super.noSuchMethod( Invocation.method(#setExposureOffset, [cameraId, offset]), returnValue: Future.value(1.0), ) as Future; + + @override + Future setOutputFormat(int cameraId, OutputFormat format) async => + super.noSuchMethod(Invocation.method(#setOutputFormat, [cameraId, format])); } class MockCameraDescription extends CameraDescription { diff --git a/packages/camera/camera_android/test/android_camera_test.dart b/packages/camera/camera_android/test/android_camera_test.dart index 8ffc901be7c..88055a0cacf 100644 --- a/packages/camera/camera_android/test/android_camera_test.dart +++ b/packages/camera/camera_android/test/android_camera_test.dart @@ -32,13 +32,11 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await TestDefaultBinaryMessengerBinding - .instance.defaultBinaryMessenger + final ByteData? response = await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger .handlePlatformMessage( AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(const MethodCall( - 'orientation_changed', - {'orientation': 'portraitDown'})), + const StandardMethodCodec().encodeMethodCall( + const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), (ByteData? data) {}); expect(response, null); }); @@ -46,22 +44,18 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AndroidCamera camera = AndroidCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -69,18 +63,13 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -102,16 +91,13 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -133,10 +119,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -160,10 +144,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -175,15 +156,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -216,7 +196,6 @@ void main() { arguments: { 'cameraId': 1, 'imageFormatGroup': 'unknown', - 'imageExtension': 'jpeg', }, ), ]); @@ -224,13 +203,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( @@ -304,10 +282,8 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -319,8 +295,7 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -331,24 +306,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -362,19 +330,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -387,20 +350,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -413,21 +370,17 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger - .handlePlatformMessage( - AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - MethodCall('orientation_changed', event.toJson())), - null); + await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage( + AndroidCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -476,20 +429,11 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -505,21 +449,17 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -533,27 +473,23 @@ void main() { camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); // Assert expect(channel.log, [ - isMethodCall('takePicture', - arguments: {'cameraId': cameraId}), + isMethodCall('takePicture', arguments: {'cameraId': cameraId}), ]); expect(file.path, '/test/path.jpg'); }); @@ -594,8 +530,7 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -618,9 +553,7 @@ void main() { ]); }); - test( - 'Should pass enableStream if callback is passed when starting recording a video', - () async { + test('Should pass enableStream if callback is passed when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -629,8 +562,7 @@ void main() { // Act await camera.startVideoCapturing( - VideoCaptureOptions(cameraId, - streamCallback: (CameraImageData imageData) {}), + VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {}), ); // Assert @@ -704,20 +636,17 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = CameraDescription( - name: 'Test2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 0); + const CameraDescription camera2Description = + CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -736,18 +665,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -764,12 +685,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -786,18 +703,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -809,8 +718,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -829,8 +737,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -893,12 +800,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -915,18 +818,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -939,13 +834,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final AndroidCamera camera = AndroidCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -999,13 +891,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -1022,8 +912,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1034,15 +923,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1058,8 +944,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1075,8 +960,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1092,8 +976,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1108,9 +991,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1131,9 +1013,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart index 315a34e9f9b..de87d5a8a65 100644 --- a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart +++ b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart @@ -30,8 +30,7 @@ void main() { await testDir.delete(recursive: true); }); - final Map presetExpectedSizes = - { + final Map presetExpectedSizes = { ResolutionPreset.low: const Size(288, 352), ResolutionPreset.medium: const Size(480, 640), ResolutionPreset.high: const Size(720, 1280), @@ -46,15 +45,13 @@ void main() { bool assertExpectedDimensions(Size expectedSize, Size actual) { expect(actual.shortestSide, lessThanOrEqualTo(expectedSize.shortestSide)); expect(actual.longestSide, lessThanOrEqualTo(expectedSize.longestSide)); - return actual.shortestSide == expectedSize.shortestSide && - actual.longestSide == expectedSize.longestSide; + return actual.shortestSide == expectedSize.shortestSide && actual.longestSide == expectedSize.longestSide; } // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. - Future testCaptureImageResolution( - CameraController controller, ResolutionPreset preset) async { + Future testCaptureImageResolution(CameraController controller, ResolutionPreset preset) async { final Size expectedSize = presetExpectedSizes[preset]!; // Take Picture @@ -66,26 +63,20 @@ void main() { // Verify image dimensions are as expected expect(image, isNotNull); - return assertExpectedDimensions( - expectedSize, Size(image.height.toDouble(), image.width.toDouble())); + return assertExpectedDimensions(expectedSize, Size(image.height.toDouble(), image.width.toDouble())); } - testWidgets('Capture specific image resolutions', - (WidgetTester tester) async { - final List cameras = - await CameraPlatform.instance.availableCameras(); + testWidgets('Capture specific image resolutions', (WidgetTester tester) async { + final List cameras = await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } for (final CameraDescription cameraDescription in cameras) { bool previousPresetExactlySupported = true; - for (final MapEntry preset - in presetExpectedSizes.entries) { - final CameraController controller = - CameraController(cameraDescription, preset.key); + for (final MapEntry preset in presetExpectedSizes.entries) { + final CameraController controller = CameraController(cameraDescription, preset.key); await controller.initialize(); - final bool presetExactlySupported = - await testCaptureImageResolution(controller, preset.key); + final bool presetExactlySupported = await testCaptureImageResolution(controller, preset.key); assert(!(!previousPresetExactlySupported && presetExactlySupported), 'The camera took higher resolution pictures at a lower resolution.'); previousPresetExactlySupported = presetExactlySupported; @@ -97,8 +88,7 @@ void main() { // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. - Future testCaptureVideoResolution( - CameraController controller, ResolutionPreset preset) async { + Future testCaptureVideoResolution(CameraController controller, ResolutionPreset preset) async { final Size expectedSize = presetExpectedSizes[preset]!; // Take Video @@ -108,34 +98,27 @@ void main() { // Load video metadata final File videoFile = File(file.path); - final VideoPlayerController videoController = - VideoPlayerController.file(videoFile); + final VideoPlayerController videoController = VideoPlayerController.file(videoFile); await videoController.initialize(); final Size video = videoController.value.size; // Verify image dimensions are as expected expect(video, isNotNull); - return assertExpectedDimensions( - expectedSize, Size(video.height, video.width)); + return assertExpectedDimensions(expectedSize, Size(video.height, video.width)); } - testWidgets('Capture specific video resolutions', - (WidgetTester tester) async { - final List cameras = - await CameraPlatform.instance.availableCameras(); + testWidgets('Capture specific video resolutions', (WidgetTester tester) async { + final List cameras = await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } for (final CameraDescription cameraDescription in cameras) { bool previousPresetExactlySupported = true; - for (final MapEntry preset - in presetExpectedSizes.entries) { - final CameraController controller = - CameraController(cameraDescription, preset.key); + for (final MapEntry preset in presetExpectedSizes.entries) { + final CameraController controller = CameraController(cameraDescription, preset.key); await controller.initialize(); await controller.prepareForVideoRecording(); - final bool presetExactlySupported = - await testCaptureVideoResolution(controller, preset.key); + final bool presetExactlySupported = await testCaptureVideoResolution(controller, preset.key); assert(!(!previousPresetExactlySupported && presetExactlySupported), 'The camera took higher resolution pictures at a lower resolution.'); previousPresetExactlySupported = presetExactlySupported; @@ -145,8 +128,7 @@ void main() { }); testWidgets('Pause and resume video recording', (WidgetTester tester) async { - final List cameras = - await CameraPlatform.instance.availableCameras(); + final List cameras = await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } @@ -184,8 +166,7 @@ void main() { sleep(const Duration(milliseconds: 500)); final XFile file = await controller.stopVideoRecording(); - final int recordingTime = - DateTime.now().millisecondsSinceEpoch - recordingStart; + final int recordingTime = DateTime.now().millisecondsSinceEpoch - recordingStart; final File videoFile = File(file.path); final VideoPlayerController videoController = VideoPlayerController.file( @@ -199,8 +180,7 @@ void main() { }); testWidgets('Set description while recording', (WidgetTester tester) async { - final List cameras = - await CameraPlatform.instance.availableCameras(); + final List cameras = await CameraPlatform.instance.availableCameras(); if (cameras.length < 2) { return; } @@ -221,8 +201,7 @@ void main() { }); testWidgets('Set description', (WidgetTester tester) async { - final List cameras = - await CameraPlatform.instance.availableCameras(); + final List cameras = await CameraPlatform.instance.availableCameras(); if (cameras.length < 2) { return; } @@ -240,8 +219,7 @@ void main() { }); /// Start streaming with specifying the ImageFormatGroup. - Future startStreaming(List cameras, - ImageFormatGroup? imageFormatGroup) async { + Future startStreaming(List cameras, ImageFormatGroup? imageFormatGroup) async { final CameraController controller = CameraController( cameras.first, ResolutionPreset.low, @@ -268,8 +246,7 @@ void main() { testWidgets( 'image streaming with imageFormatGroup', (WidgetTester tester) async { - final List cameras = - await CameraPlatform.instance.availableCameras(); + final List cameras = await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } @@ -292,8 +269,7 @@ void main() { ); testWidgets('Recording with video streaming', (WidgetTester tester) async { - final List cameras = - await CameraPlatform.instance.availableCameras(); + final List cameras = await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } @@ -307,8 +283,7 @@ void main() { await controller.initialize(); await controller.prepareForVideoRecording(); final Completer completer = Completer(); - await controller.startVideoRecording( - streamCallback: (CameraImageData image) { + await controller.startVideoRecording(streamCallback: (CameraImageData image) { if (!completer.isCompleted) { completer.complete(image); } @@ -319,4 +294,22 @@ void main() { expect(await completer.future, isNotNull); }); + + // Test outputFormat is respected when taking a picture. + testWidgets('Capture specific image output formats', (WidgetTester tester) async { + final List cameras = await CameraPlatform.instance.availableCameras(); + if (cameras.isEmpty) { + return; + } + for (final CameraDescription cameraDescription in cameras) { + for (final OutputFormat outputFormat in OutputFormat.values) { + final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); + await controller.initialize(); + await controller.setOutputFormat(outputFormat); + final XFile file = await controller.takePicture(); + await controller.dispose(); + expect(file.path.endsWith(outputFormat.name()), true); + } + } + }); } diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index a9865782294..9d22670b5a0 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -105,7 +105,7 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); - [cam setImageExtension:ImageExtensionHEIF]; + [cam setOutputFormat:OutputFormatHEIF]; // Set photo settings to HEVC AVCapturePhotoSettings *settings = diff --git a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart index c29db976f09..8347ff5e2cd 100644 --- a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart +++ b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart @@ -131,17 +131,13 @@ class CameraValue { exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: lockedCaptureOrientation == null - ? this.lockedCaptureOrientation - : lockedCaptureOrientation.orNull, - recordingOrientation: recordingOrientation == null - ? this.recordingOrientation - : recordingOrientation.orNull, + lockedCaptureOrientation: + lockedCaptureOrientation == null ? this.lockedCaptureOrientation : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null ? this.recordingOrientation : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, description: description ?? this.description, - previewPauseOrientation: previewPauseOrientation == null - ? this.previewPauseOrientation - : previewPauseOrientation.orNull, + previewPauseOrientation: + previewPauseOrientation == null ? this.previewPauseOrientation : previewPauseOrientation.orNull, ); } @@ -176,7 +172,6 @@ class CameraController extends ValueNotifier { this.resolutionPreset, { this.enableAudio = true, this.imageFormatGroup, - this.imageExtension, }) : super(CameraValue.uninitialized(cameraDescription)); /// The properties of the camera device controlled by this controller. @@ -198,18 +193,12 @@ class CameraController extends ValueNotifier { /// When null the imageFormat will fallback to the platforms default. final ImageFormatGroup? imageFormatGroup; - /// The [ImageExtension] describes the output of the raw image format. - /// - /// When null the imageFormat will fallback to the platforms default. - final ImageExtension? imageExtension; - late int _cameraId; bool _isDisposed = false; StreamSubscription? _imageStreamSubscription; FutureOr? _initCalled; - StreamSubscription? - _deviceOrientationSubscription; + StreamSubscription? _deviceOrientationSubscription; /// The camera identifier with which the controller is associated. int get cameraId => _cameraId; @@ -218,12 +207,10 @@ class CameraController extends ValueNotifier { Future initialize() => _initializeWithDescription(description); Future _initializeWithDescription(CameraDescription description) async { - final Completer initializeCompleter = - Completer(); + final Completer initializeCompleter = Completer(); - _deviceOrientationSubscription = CameraPlatform.instance - .onDeviceOrientationChanged() - .listen((DeviceOrientationChangedEvent event) { + _deviceOrientationSubscription = + CameraPlatform.instance.onDeviceOrientationChanged().listen((DeviceOrientationChangedEvent event) { value = value.copyWith( deviceOrientation: event.orientation, ); @@ -235,35 +222,28 @@ class CameraController extends ValueNotifier { enableAudio: enableAudio, ); - unawaited(CameraPlatform.instance - .onCameraInitialized(_cameraId) - .first - .then((CameraInitializedEvent event) { + unawaited(CameraPlatform.instance.onCameraInitialized(_cameraId).first.then((CameraInitializedEvent event) { initializeCompleter.complete(event); })); await CameraPlatform.instance.initializeCamera( _cameraId, imageFormatGroup: imageFormatGroup ?? ImageFormatGroup.unknown, - imageExtension: imageExtension ?? ImageExtension.jpeg, ); value = value.copyWith( isInitialized: true, description: description, - previewSize: await initializeCompleter.future - .then((CameraInitializedEvent event) => Size( - event.previewWidth, - event.previewHeight, - )), - exposureMode: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.exposureMode), - focusMode: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.focusMode), - exposurePointSupported: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.exposurePointSupported), - focusPointSupported: await initializeCompleter.future - .then((CameraInitializedEvent event) => event.focusPointSupported), + previewSize: await initializeCompleter.future.then((CameraInitializedEvent event) => Size( + event.previewWidth, + event.previewHeight, + )), + exposureMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposureMode), + focusMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusMode), + exposurePointSupported: + await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposurePointSupported), + focusPointSupported: + await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusPointSupported), ); _initCalled = true; @@ -279,16 +259,14 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: Optional.of( - value.lockedCaptureOrientation ?? value.deviceOrientation)); + previewPauseOrientation: + Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); } /// Resumes the current camera preview Future resumePreview() async { await CameraPlatform.instance.resumePreview(_cameraId); - value = value.copyWith( - isPreviewPaused: false, - previewPauseOrientation: const Optional.absent()); + value = value.copyWith(isPreviewPaused: false, previewPauseOrientation: const Optional.absent()); } /// Sets the description of the camera @@ -312,11 +290,9 @@ class CameraController extends ValueNotifier { } /// Start streaming images from platform camera. - Future startImageStream( - Function(CameraImageData image) onAvailable) async { - _imageStreamSubscription = CameraPlatform.instance - .onStreamedFrameAvailable(_cameraId) - .listen((CameraImageData imageData) { + Future startImageStream(Function(CameraImageData image) onAvailable) async { + _imageStreamSubscription = + CameraPlatform.instance.onStreamedFrameAvailable(_cameraId).listen((CameraImageData imageData) { onAvailable(imageData); }); value = value.copyWith(isStreamingImages: true); @@ -333,16 +309,14 @@ class CameraController extends ValueNotifier { /// /// The video is returned as a [XFile] after calling [stopVideoRecording]. /// Throws a [CameraException] if the capture fails. - Future startVideoRecording( - {Function(CameraImageData image)? streamCallback}) async { - await CameraPlatform.instance.startVideoCapturing( - VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); + Future startVideoRecording({Function(CameraImageData image)? streamCallback}) async { + await CameraPlatform.instance.startVideoCapturing(VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, isStreamingImages: streamCallback != null, - recordingOrientation: Optional.of( - value.lockedCaptureOrientation ?? value.deviceOrientation)); + recordingOrientation: + Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); } /// Stops the video recording and returns the file where it was saved. @@ -353,8 +327,7 @@ class CameraController extends ValueNotifier { await stopImageStream(); } - final XFile file = - await CameraPlatform.instance.stopVideoRecording(_cameraId); + final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); value = value.copyWith( isRecordingVideo: false, recordingOrientation: const Optional.absent(), @@ -404,8 +377,7 @@ class CameraController extends ValueNotifier { ]); // Round to the closest step if needed - final double stepSize = - await CameraPlatform.instance.getExposureOffsetStepSize(_cameraId); + final double stepSize = await CameraPlatform.instance.getExposureOffsetStepSize(_cameraId); if (stepSize > 0) { final double inv = 1.0 / stepSize; double roundedOffset = (offset * inv).roundToDouble() / inv; @@ -424,18 +396,14 @@ class CameraController extends ValueNotifier { /// /// If [orientation] is omitted, the current device orientation is used. Future lockCaptureOrientation() async { - await CameraPlatform.instance - .lockCaptureOrientation(_cameraId, value.deviceOrientation); - value = value.copyWith( - lockedCaptureOrientation: - Optional.of(value.deviceOrientation)); + await CameraPlatform.instance.lockCaptureOrientation(_cameraId, value.deviceOrientation); + value = value.copyWith(lockedCaptureOrientation: Optional.of(value.deviceOrientation)); } /// Unlocks the capture orientation. Future unlockCaptureOrientation() async { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith( - lockedCaptureOrientation: const Optional.absent()); + value = value.copyWith(lockedCaptureOrientation: const Optional.absent()); } /// Sets the focus mode for taking pictures. @@ -444,6 +412,11 @@ class CameraController extends ValueNotifier { value = value.copyWith(focusMode: mode); } + /// Sets the output format for taking pictures. + Future setOutputFormat(OutputFormat format) async { + await CameraPlatform.instance.setOutputFormat(_cameraId, format); + } + /// Releases the resources of this camera. @override Future dispose() async { @@ -543,9 +516,7 @@ class Optional extends IterableBase { /// /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. Optional transform(S Function(T value) transformer) { - return _value == null - ? Optional.absent() - : Optional.of(transformer(_value as T)); + return _value == null ? Optional.absent() : Optional.of(transformer(_value as T)); } /// Transforms the Optional value. @@ -554,14 +525,11 @@ class Optional extends IterableBase { /// /// Returns [absent()] if the transformer returns `null`. Optional transformNullable(S? Function(T value) transformer) { - return _value == null - ? Optional.absent() - : Optional.fromNullable(transformer(_value as T)); + return _value == null ? Optional.absent() : Optional.fromNullable(transformer(_value as T)); } @override - Iterator get iterator => - isPresent ? [_value as T].iterator : Iterable.empty().iterator; + Iterator get iterator => isPresent ? [_value as T].iterator : Iterable.empty().iterator; /// Delegates to the underlying [value] hashCode. @override @@ -573,8 +541,6 @@ class Optional extends IterableBase { @override String toString() { - return _value == null - ? 'Optional { absent }' - : 'Optional { value: $_value }'; + return _value == null ? 'Optional { absent }' : 'Optional { value: $_value }'; } } diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index 9cfdf0df039..3777de26492 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -153,10 +153,8 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call NSUInteger cameraId = ((NSNumber *)argsMap[@"cameraId"]).unsignedIntegerValue; if ([@"initialize" isEqualToString:call.method]) { NSString *videoFormatValue = ((NSString *)argsMap[@"imageFormatGroup"]); - NSString *imageExtension = ((NSString *)argsMap[@"imageExtension"]); [_camera setVideoFormat:FLTGetVideoFormatFromString(videoFormatValue)]; - [_camera setImageExtension:FLTGetImageExtensionFromString(imageExtension)]; __weak CameraPlugin *weakSelf = self; _camera.onFrameAvailable = ^{ @@ -258,6 +256,9 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call [_camera resumePreviewWithResult:result]; } else if ([@"setDescriptionWhileRecording" isEqualToString:call.method]) { [_camera setDescriptionWhileRecording:(call.arguments[@"cameraName"]) result:result]; + } else if ([@"setOutputFormat" isEqualToString:call.method]) { + NSString *outputFormat = ((NSString *)argsMap[@"outputFormat"]); + [_camera setOutputFormat:FLTGetOutputFormatFromString(outputFormat)]; } else { [result sendNotImplemented]; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index 953ed3d2b32..b8ac2834709 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -128,18 +128,18 @@ extern FLTResolutionPreset FLTGetFLTResolutionPresetForString(NSString *preset); extern OSType FLTGetVideoFormatFromString(NSString *videoFormatString); /** - * Represents image format. Mirrors ImageExtension in camera.dart. + * Represents image format. Mirrors OutputFormat in camera.dart. */ -typedef NS_ENUM(NSInteger, ImageExtension) { - ImageExtensionJPEG, - ImageExtensionHEIF, +typedef NS_ENUM(NSInteger, OutputFormat) { + OutputFormatJPEG, + OutputFormatHEIF, }; #pragma mark - image extension /** - * Gets ImageExtension from its string representation. + * Gets a string representation of OutputFormat. */ -extern ImageExtension FLTGetImageExtensionFromString(NSString *imageExtensionString); +extern OutputFormat FLTGetOutputFormatFromString(NSString *outputFormatString); NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m index a0a835e5596..fb1d617f9e2 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m @@ -152,18 +152,18 @@ OSType FLTGetVideoFormatFromString(NSString *videoFormatString) { #pragma mark - video codec -ImageExtension FLTGetImageExtensionFromString(NSString *extensionString) { - if ([extensionString isEqualToString:@"jpg"]) { - return ImageExtensionJPEG; - } else if ([extensionString isEqualToString:@"heif"]) { - return ImageExtensionHEIF; +OutputFormat FLTGetOutputFormatFromString(NSString *outputFormatString) { + if ([outputFormatString isEqualToString:@"jpg"]) { + return OutputFormatJPEG; + } else if ([outputFormatString isEqualToString:@"heif"]) { + return OutputFormatHEIF; } else { NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSURLErrorUnknown userInfo:@{ NSLocalizedDescriptionKey : - [NSString stringWithFormat:@"Unknown image extension %@", extensionString] + [NSString stringWithFormat:@"Unknown image extension %@", outputFormatString] }]; @throw error; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index c6cb5db61e2..24513b7ef75 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN @property(assign, nonatomic) FLTFlashMode flashMode; // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; -@property(assign, nonatomic) ImageExtension imageExtension; +@property(assign, nonatomic) OutputFormat outputFormat; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. @@ -51,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)captureToFile:(FLTThreadSafeFlutterResult *)result; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; -- (void)setImageExtension:(ImageExtension)imageExtension; +- (void)setOutputFormat:(OutputFormat)outputFormat; /** * Starts recording a video with an optional streaming messenger. * If the messenger is non-null then it will be called for each diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 57f43acca2f..b77beb41a92 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -144,7 +144,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName _deviceOrientation = orientation; _videoFormat = kCVPixelFormatType_32BGRA; _inProgressSavePhotoDelegates = [NSMutableDictionary dictionary]; - _imageExtension = ImageExtensionJPEG; + _outputFormat = OutputFormatJPEG; // To limit memory consumption, limit the number of frames pending processing. // After some testing, 4 was determined to be the best maximum value. @@ -219,8 +219,8 @@ - (void)setVideoFormat:(OSType)videoFormat { @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)}; } -- (void)setImageExtension:(ImageExtension)imageExtension { - _imageExtension = imageExtension; +- (void)setOutputFormat:(OutputFormat)outputFormat { + _outputFormat = outputFormat; } - (void)setDeviceOrientation:(UIDeviceOrientation)orientation { @@ -264,9 +264,9 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setHighResolutionPhotoEnabled:YES]; } - if (_imageExtension == ImageExtensionHEIF) { + if (_outputFormat == OutputFormatHEIF) { if (@available(iOS 11.0, *)) { - if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { + if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; extension = @"heif"; diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 90e513be3f2..978ab656a50 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,8 +14,7 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = - MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -29,8 +28,7 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = - 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -40,16 +38,14 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = - _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -65,14 +61,13 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -81,8 +76,7 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -98,12 +92,9 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -117,13 +108,10 @@ class AVFoundationCamera extends CameraPlatform { Future initializeCamera( int cameraId, { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, - ImageExtension imageExtension = ImageExtension.jpeg, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel( - 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -138,7 +126,6 @@ class AVFoundationCamera extends CameraPlatform { { 'cameraId': cameraId, 'imageFormatGroup': imageFormatGroup.name(), - 'imageExtension': _serializeImageExtension(imageExtension), }, ).catchError( // TODO(srawlins): This should return a value of the future's type. This @@ -201,8 +188,7 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream - .whereType(); + return _deviceEventStreamController.stream.whereType(); } @override @@ -212,10 +198,7 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -245,14 +228,11 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -297,22 +277,18 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { - _frameStreamController = - _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController( - {Function()? onListen}) { + StreamController _createStreamController({Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -331,17 +307,14 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -353,13 +326,11 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -368,8 +339,7 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -437,8 +407,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -514,8 +483,7 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -524,6 +492,17 @@ class AVFoundationCamera extends CameraPlatform { ); } + @override + Future setOutputFormat(int cameraId, OutputFormat format) { + return _channel.invokeMethod( + 'setOutputFormat', + { + 'cameraId': cameraId, + 'outputFormat': format.name(), + }, + ); + } + @override Widget buildPreview(int cameraId) { return Texture(textureId: cameraId); @@ -575,23 +554,13 @@ class AVFoundationCamera extends CameraPlatform { return 'max'; } - /// Returns the format of the image as a String. - String _serializeImageExtension(ImageExtension imageExtension) { - switch (imageExtension) { - case ImageExtension.jpeg: - return 'jpeg'; - case ImageExtension.heif: - return 'heif'; - } - } - /// Converts messages received from the native platform into device events. Future _handleDeviceMethodCall(MethodCall call) async { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -635,9 +604,7 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index e1ae682c04d..071795f371b 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -32,37 +32,31 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(const MethodCall( - 'orientation_changed', - {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AVFoundationCamera camera = AVFoundationCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -70,18 +64,13 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -103,16 +92,13 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -134,10 +120,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -161,10 +145,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -176,16 +157,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - 'imageExtension': 'jpeg', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -218,7 +197,6 @@ void main() { arguments: { 'cameraId': 1, 'imageFormatGroup': 'unknown', - 'imageExtension': 'jpeg', }, ), ]); @@ -226,13 +204,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: _channelName, - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: _channelName, methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( @@ -306,10 +283,8 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -321,8 +296,7 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -333,24 +307,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -364,19 +331,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -389,20 +351,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -415,22 +371,17 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -479,23 +430,14 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange // This deliberately uses 'dynamic' since that's what actual platform // channel results will be, so using typed mock data could mask type // handling bugs in the code under test. final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -511,21 +453,17 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -539,19 +477,16 @@ void main() { camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = MethodChannelMock( - channelName: _channelName, - methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = + MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -601,8 +536,7 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -625,9 +559,7 @@ void main() { ]); }); - test( - 'Should pass enableStream if callback is passed when starting recording a video', - () async { + test('Should pass enableStream if callback is passed when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -635,8 +567,7 @@ void main() { ); // Act - await camera.startVideoCapturing(VideoCaptureOptions(cameraId, - streamCallback: (CameraImageData imageData) {})); + await camera.startVideoCapturing(VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {})); // Assert expect(channel.log, [ @@ -709,20 +640,17 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = CameraDescription( - name: 'Test2', - lensDirection: CameraLensDirection.front, - sensorOrientation: 0); + const CameraDescription camera2Description = + CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -741,18 +669,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', - arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -769,12 +689,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -791,18 +707,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -814,8 +722,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -834,8 +741,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -898,12 +804,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', - arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -920,18 +822,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -944,13 +838,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final AVFoundationCamera camera = AVFoundationCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -1004,13 +895,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -1027,8 +916,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1039,15 +927,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1063,8 +948,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1080,8 +964,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1097,8 +980,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1113,9 +995,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1136,9 +1017,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 14a1dfe6c3a..9b575761761 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,10 +20,8 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler( - (MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -36,8 +34,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = - StreamController.broadcast(); + final StreamController cameraEventStreamController = StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -47,8 +44,7 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = - StreamController.broadcast(); + final StreamController deviceEventStreamController = StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -57,14 +53,13 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream - .where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = await _channel - .invokeListMethod>('availableCameras'); + final List>? cameras = + await _channel.invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -73,8 +68,7 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: - parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -90,12 +84,9 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel - .invokeMapMethod('create', { + final Map? reply = await _channel.invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null - ? _serializeResolutionPreset(resolutionPreset) - : null, + 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, 'enableAudio': enableAudio, }); @@ -109,13 +100,10 @@ class MethodChannelCamera extends CameraPlatform { Future initializeCamera( int cameraId, { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, - ImageExtension imageExtension = ImageExtension.jpeg, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = - MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler( - (MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -130,7 +118,6 @@ class MethodChannelCamera extends CameraPlatform { { 'cameraId': cameraId, 'imageFormatGroup': imageFormatGroup.name(), - 'imageExtension': imageExtension.name(), }, ).catchError( // TODO(srawlins): This should return a value of the future's type. This @@ -193,8 +180,7 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream - .whereType(); + return deviceEventStreamController.stream.whereType(); } @override @@ -204,10 +190,7 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - { - 'cameraId': cameraId, - 'orientation': serializeDeviceOrientation(orientation) - }, + {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, ); } @@ -237,14 +220,11 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => - _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, - {Duration? maxVideoDuration}) async { - return startVideoCapturing( - VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { + return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -288,21 +268,18 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => - _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController( - {Function()? onListen}) { + StreamController _installStreamController({Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -322,10 +299,8 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = - EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = - cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -333,8 +308,7 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController! - .add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -346,13 +320,11 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', - 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => - _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -361,8 +333,7 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => - _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -430,8 +401,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => - _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -507,8 +477,7 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording( - CameraDescription description) async { + Future setDescriptionWhileRecording(CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -517,6 +486,17 @@ class MethodChannelCamera extends CameraPlatform { ); } + @override + Future setOutputFormat(int cameraId, OutputFormat format) { + return _channel.invokeMethod( + 'setOutputFormat', + { + 'cameraId': cameraId, + 'outputFormat': format.name(), + }, + ); + } + @override Widget buildPreview(int cameraId) { return Texture(textureId: cameraId); @@ -562,8 +542,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController.add(DeviceOrientationChangedEvent( - deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController + .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -607,9 +587,7 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null - ? Duration(milliseconds: arguments['maxVideoDuration']! as int) - : null, + arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 252ab336817..c6e037d45e8 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -61,14 +61,9 @@ abstract class CameraPlatform extends PlatformInterface { /// On Android this defaults to ImageFormat.YUV_420_888 and applies only to the imageStream. /// On iOS this defaults to kCVPixelFormatType_32BGRA. /// On Web this parameter is currently not supported. - /// - /// [imageExtension] is used to specify the image extension used. - /// [ImageExtension.jpeg] and [ImageExtension.heif] are availables - /// only in iOS 11.0+. Future initializeCamera( int cameraId, { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, - ImageExtension imageExtension = ImageExtension.jpeg, }) { throw UnimplementedError('initializeCamera() is not implemented.'); } @@ -104,13 +99,11 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError( - 'onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation( - int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -147,8 +140,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -176,8 +168,7 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -276,8 +267,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError( - 'setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. @@ -289,4 +279,9 @@ abstract class CameraPlatform extends PlatformInterface { Future dispose(int cameraId) { throw UnimplementedError('dispose() is not implemented.'); } + + /// Sets the output format for the selected camera. + Future setOutputFormat(int cameraId, OutputFormat format) { + throw UnimplementedError('setOutputFormat() is not implemented.'); + } } diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart b/packages/camera/camera_platform_interface/lib/src/types/output_format.dart similarity index 69% rename from packages/camera/camera_platform_interface/lib/src/types/image_extension.dart rename to packages/camera/camera_platform_interface/lib/src/types/output_format.dart index e81d33edecf..df56ec5465a 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/image_extension.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/output_format.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. /// The format in which images should be returned from the camera. -enum ImageExtension { +enum OutputFormat { /// This is the default value. It will return the image in JPEG format. /// Is the widely used format for images. jpeg, @@ -14,16 +14,16 @@ enum ImageExtension { heif, } -/// Extension on [ImageExtension] to stringify the enum -extension ImageExtensionName on ImageExtension { - /// returns a String value for [ImageExtension] +/// Extension on [OutputFormat] to stringify the enum +extension OutputFormatName on OutputFormat { + /// returns a String value for [OutputFormat] /// returns 'jpeg' if platform is not supported - /// or if [ImageExtension] is not supported for the platform + /// or if [OutputFormat] is not supported for the platform String name() { switch (this) { - case ImageExtension.jpeg: + case OutputFormat.jpeg: return 'jpeg'; - case ImageExtension.heif: + case OutputFormat.heif: return 'heif'; } } diff --git a/packages/camera/camera_platform_interface/lib/src/types/types.dart b/packages/camera/camera_platform_interface/lib/src/types/types.dart index d52e0a83db1..73001dafc5d 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/types.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/types.dart @@ -8,7 +8,7 @@ export 'camera_image_data.dart'; export 'exposure_mode.dart'; export 'flash_mode.dart'; export 'focus_mode.dart'; -export 'image_extension.dart'; export 'image_format_group.dart'; +export 'output_format.dart'; export 'resolution_preset.dart'; export 'video_capture_options.dart'; diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 6b73ce20175..8a112fe06e2 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -23,8 +23,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraInitializedEvent event = - CameraInitializedEvent.fromJson(const { + final CameraInitializedEvent event = CameraInitializedEvent.fromJson(const { 'cameraId': 1, 'previewWidth': 1024.0, 'previewHeight': 640.0, @@ -68,97 +67,80 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); - test('equals should return false if exposurePointSupported is different', - () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); + test('equals should return false if exposurePointSupported is different', () { + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); - - expect(firstEvent == secondEvent, false); - }); - - test('equals should return true if imageExtension is different', () { - const CameraInitializedEvent firstEvent = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ); + const CameraInitializedEvent firstEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = CameraInitializedEvent( - 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = + CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.previewWidth, @@ -175,8 +157,7 @@ void main() { group('CameraResolutionChangesEvent tests', () { test('Constructor should initialize all properties', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); expect(event.cameraId, 1); expect(event.captureWidth, 1024); @@ -184,8 +165,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraResolutionChangedEvent event = - CameraResolutionChangedEvent.fromJson(const { + final CameraResolutionChangedEvent event = CameraResolutionChangedEvent.fromJson(const { 'cameraId': 1, 'captureWidth': 1024.0, 'captureHeight': 640.0, @@ -197,8 +177,7 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); final Map jsonMap = event.toJson(); @@ -209,44 +188,35 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 640); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(2, 1024, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(2, 1024, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureWidth is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 2048, 640); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 2048, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureHeight is different', () { - const CameraResolutionChangedEvent firstEvent = - CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = - CameraResolutionChangedEvent(1, 1024, 980); + const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 980); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraResolutionChangedEvent event = - CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.captureWidth, @@ -265,8 +235,7 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraClosingEvent event = - CameraClosingEvent.fromJson(const { + final CameraClosingEvent event = CameraClosingEvent.fromJson(const { 'cameraId': 1, }); @@ -313,8 +282,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraErrorEvent event = CameraErrorEvent.fromJson( - const {'cameraId': 1, 'description': 'Error'}); + final CameraErrorEvent event = + CameraErrorEvent.fromJson(const {'cameraId': 1, 'description': 'Error'}); expect(event.cameraId, 1); expect(event.description, 'Error'); @@ -353,8 +322,7 @@ void main() { test('hashCode should match hashCode of all properties', () { const CameraErrorEvent event = CameraErrorEvent(1, 'Error'); - final int expectedHashCode = - Object.hash(event.cameraId.hashCode, event.description); + final int expectedHashCode = Object.hash(event.cameraId.hashCode, event.description); expect(event.hashCode, expectedHashCode); }); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index a2e80907747..7bb119d66fc 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -22,22 +22,18 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0), + const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), ResolutionPreset.high, ); @@ -45,28 +41,20 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: { - 'cameraName': 'Test', - 'resolutionPreset': 'high', - 'enableAudio': false - }, + arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, ), ]); expect(cameraId, 1); }); - test( - 'Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -81,26 +69,20 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); - test( - 'Should throw CameraException when create throws a PlatformException', - () { + test('Should throw CameraException when create throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -115,10 +97,8 @@ void main() { ), throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -142,10 +122,7 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA() - .having((CameraException e) => e.code, 'code', - 'TESTING_ERROR_CODE') - .having( + isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,16 +134,14 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - 'imageExtension': 'jpeg', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -199,7 +174,6 @@ void main() { arguments: { 'cameraId': 1, 'imageFormatGroup': 'unknown', - 'imageExtension': 'jpeg', }, ), ]); @@ -207,13 +181,12 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( @@ -287,10 +260,8 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = - camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -302,8 +273,7 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall( - MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -314,24 +284,17 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = - camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = - CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = - CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -345,19 +308,14 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = - camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = - StreamQueue(eventStream); + final Stream eventStream = camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -370,20 +328,14 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = - camera.onCameraError(cameraId); - final StreamQueue streamQueue = - StreamQueue(errorStream); + final Stream errorStream = camera.onCameraError(cameraId); + final StreamQueue streamQueue = StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = - CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall( - MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -396,20 +348,15 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = - camera.onDeviceOrientationChanged(); + final Stream eventStream = camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = - DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall( - MethodCall('orientation_changed', event.toJson())); + const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); // Assert expect(await streamQueue.next, event); @@ -457,20 +404,11 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', - () async { + test('Should fetch CameraDescription instances for available cameras', () async { // Arrange final List returnData = [ - { - 'name': 'Test 1', - 'lensFacing': 'front', - 'sensorOrientation': 1 - }, - { - 'name': 'Test 2', - 'lensFacing': 'back', - 'sensorOrientation': 2 - } + {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, + {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} ]; final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -486,40 +424,32 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = - (returnData[i] as Map).cast(); + final Map typedData = (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: - parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test( - 'Should throw CameraException when availableCameras throws a PlatformException', - () { + test('Should throw CameraException when availableCameras throws a PlatformException', () { // Arrange - MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: { - 'availableCameras': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { + 'availableCameras': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); // Act expect( camera.availableCameras, throwsA( isA() - .having( - (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', - 'Mock error message used during testing.'), + .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), ), ); }); @@ -527,8 +457,7 @@ void main() { test('Should take a picture and return an XFile instance', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', - methods: {'takePicture': '/test/path.jpg'}); + channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -586,23 +515,18 @@ void main() { ); // Act - const CameraDescription cameraDescription = CameraDescription( - name: 'Test', - lensDirection: CameraLensDirection.back, - sensorOrientation: 0); + const CameraDescription cameraDescription = + CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0); await camera.setDescriptionWhileRecording(cameraDescription); // Assert expect(channel.log, [ isMethodCall('setDescriptionWhileRecording', - arguments: { - 'cameraName': cameraDescription.name - }), + arguments: {'cameraName': cameraDescription.name}), ]); }); - test('Should pass maxVideoDuration when starting recording a video', - () async { + test('Should pass maxVideoDuration when starting recording a video', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -695,22 +619,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'torch' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'always' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setFlashMode', arguments: { - 'cameraId': cameraId, - 'mode': 'off' - }), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -727,14 +639,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setExposureMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -751,18 +657,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setExposurePoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setExposurePoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -774,8 +672,7 @@ void main() { ); // Act - final double minExposureOffset = - await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -794,8 +691,7 @@ void main() { ); // Act - final double maxExposureOffset = - await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -814,16 +710,14 @@ void main() { ); // Act - final double stepSize = - await camera.getExposureOffsetStepSize(cameraId); + final double stepSize = await camera.getExposureOffsetStepSize(cameraId); // Assert expect(stepSize, 0.25); expect(channel.log, [ - isMethodCall('getExposureOffsetStepSize', - arguments: { - 'cameraId': cameraId, - }), + isMethodCall('getExposureOffsetStepSize', arguments: { + 'cameraId': cameraId, + }), ]); }); @@ -835,8 +729,7 @@ void main() { ); // Act - final double actualOffset = - await camera.setExposureOffset(cameraId, 0.5); + final double actualOffset = await camera.setExposureOffset(cameraId, 0.5); // Assert expect(actualOffset, 0.6); @@ -861,14 +754,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'auto' - }), - isMethodCall('setFocusMode', arguments: { - 'cameraId': cameraId, - 'mode': 'locked' - }), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), ]); }); @@ -885,18 +772,10 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': 0.5, - 'y': 0.5, - 'reset': false - }), - isMethodCall('setFocusPoint', arguments: { - 'cameraId': cameraId, - 'x': null, - 'y': null, - 'reset': true - }), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), + isMethodCall('setFocusPoint', + arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), ]); }); @@ -909,13 +788,10 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', - () { + test('Should throw MissingPluginException when handling unknown method', () { final MethodChannelCamera camera = MethodChannelCamera(); - expect( - () => camera.handleCameraMethodCall( - const MethodCall('unknown_method'), 1), + expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -969,13 +845,11 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', - arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', - () async { + test('Should throw CameraException when illegal zoom level is supplied', () async { // Arrange MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -992,8 +866,7 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', - 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -1004,15 +877,12 @@ void main() { ); // Act - await camera.lockCaptureOrientation( - cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', arguments: { - 'cameraId': cameraId, - 'orientation': 'portraitUp' - }), + isMethodCall('lockCaptureOrientation', + arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), ]); }); @@ -1028,8 +898,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', - arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), ]); }); @@ -1045,8 +914,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1062,8 +930,7 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', - arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), ]); }); @@ -1078,9 +945,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1101,9 +967,8 @@ void main() { ); // Act - final StreamSubscription subscription = camera - .onStreamedFrameAvailable(cameraId) - .listen((CameraImageData imageData) {}); + final StreamSubscription subscription = + camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart b/packages/camera/camera_platform_interface/test/types/output_format_test.dart similarity index 72% rename from packages/camera/camera_platform_interface/test/types/image_extension_test.dart rename to packages/camera/camera_platform_interface/test/types/output_format_test.dart index 8661e43843e..29829789e8c 100644 --- a/packages/camera/camera_platform_interface/test/types/image_extension_test.dart +++ b/packages/camera/camera_platform_interface/test/types/output_format_test.dart @@ -6,10 +6,10 @@ import 'package:camera_platform_interface/src/types/types.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - group('$ImageExtension tests', () { + group('$OutputFormat tests', () { test('ImageFormat extension returns correct values', () { - expect(ImageExtension.jpeg.name(), 'jpeg'); - expect(ImageExtension.heif.name(), 'heif'); + expect(OutputFormat.jpeg.name(), 'jpeg'); + expect(OutputFormat.heif.name(), 'heif'); }); }); } From 3cb6af324322a28f97c52fd20324e818025e5cc5 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 10:31:59 -0300 Subject: [PATCH 32/71] fix tests --- .../example/integration_test/camera_test.dart | 84 +++-- .../example/lib/camera_controller.dart | 110 ++++-- .../lib/src/avfoundation_camera.dart | 96 +++-- .../test/avfoundation_camera_test.dart | 348 ++++++++++++------ .../test/events/camera_event_test.dart | 1 - 5 files changed, 424 insertions(+), 215 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart index de87d5a8a65..dbb6a51929c 100644 --- a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart +++ b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart @@ -30,7 +30,8 @@ void main() { await testDir.delete(recursive: true); }); - final Map presetExpectedSizes = { + final Map presetExpectedSizes = + { ResolutionPreset.low: const Size(288, 352), ResolutionPreset.medium: const Size(480, 640), ResolutionPreset.high: const Size(720, 1280), @@ -45,13 +46,15 @@ void main() { bool assertExpectedDimensions(Size expectedSize, Size actual) { expect(actual.shortestSide, lessThanOrEqualTo(expectedSize.shortestSide)); expect(actual.longestSide, lessThanOrEqualTo(expectedSize.longestSide)); - return actual.shortestSide == expectedSize.shortestSide && actual.longestSide == expectedSize.longestSide; + return actual.shortestSide == expectedSize.shortestSide && + actual.longestSide == expectedSize.longestSide; } // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. - Future testCaptureImageResolution(CameraController controller, ResolutionPreset preset) async { + Future testCaptureImageResolution( + CameraController controller, ResolutionPreset preset) async { final Size expectedSize = presetExpectedSizes[preset]!; // Take Picture @@ -63,20 +66,26 @@ void main() { // Verify image dimensions are as expected expect(image, isNotNull); - return assertExpectedDimensions(expectedSize, Size(image.height.toDouble(), image.width.toDouble())); + return assertExpectedDimensions( + expectedSize, Size(image.height.toDouble(), image.width.toDouble())); } - testWidgets('Capture specific image resolutions', (WidgetTester tester) async { - final List cameras = await CameraPlatform.instance.availableCameras(); + testWidgets('Capture specific image resolutions', + (WidgetTester tester) async { + final List cameras = + await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } for (final CameraDescription cameraDescription in cameras) { bool previousPresetExactlySupported = true; - for (final MapEntry preset in presetExpectedSizes.entries) { - final CameraController controller = CameraController(cameraDescription, preset.key); + for (final MapEntry preset + in presetExpectedSizes.entries) { + final CameraController controller = + CameraController(cameraDescription, preset.key); await controller.initialize(); - final bool presetExactlySupported = await testCaptureImageResolution(controller, preset.key); + final bool presetExactlySupported = + await testCaptureImageResolution(controller, preset.key); assert(!(!previousPresetExactlySupported && presetExactlySupported), 'The camera took higher resolution pictures at a lower resolution.'); previousPresetExactlySupported = presetExactlySupported; @@ -88,7 +97,8 @@ void main() { // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. - Future testCaptureVideoResolution(CameraController controller, ResolutionPreset preset) async { + Future testCaptureVideoResolution( + CameraController controller, ResolutionPreset preset) async { final Size expectedSize = presetExpectedSizes[preset]!; // Take Video @@ -98,27 +108,34 @@ void main() { // Load video metadata final File videoFile = File(file.path); - final VideoPlayerController videoController = VideoPlayerController.file(videoFile); + final VideoPlayerController videoController = + VideoPlayerController.file(videoFile); await videoController.initialize(); final Size video = videoController.value.size; // Verify image dimensions are as expected expect(video, isNotNull); - return assertExpectedDimensions(expectedSize, Size(video.height, video.width)); + return assertExpectedDimensions( + expectedSize, Size(video.height, video.width)); } - testWidgets('Capture specific video resolutions', (WidgetTester tester) async { - final List cameras = await CameraPlatform.instance.availableCameras(); + testWidgets('Capture specific video resolutions', + (WidgetTester tester) async { + final List cameras = + await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } for (final CameraDescription cameraDescription in cameras) { bool previousPresetExactlySupported = true; - for (final MapEntry preset in presetExpectedSizes.entries) { - final CameraController controller = CameraController(cameraDescription, preset.key); + for (final MapEntry preset + in presetExpectedSizes.entries) { + final CameraController controller = + CameraController(cameraDescription, preset.key); await controller.initialize(); await controller.prepareForVideoRecording(); - final bool presetExactlySupported = await testCaptureVideoResolution(controller, preset.key); + final bool presetExactlySupported = + await testCaptureVideoResolution(controller, preset.key); assert(!(!previousPresetExactlySupported && presetExactlySupported), 'The camera took higher resolution pictures at a lower resolution.'); previousPresetExactlySupported = presetExactlySupported; @@ -128,7 +145,8 @@ void main() { }); testWidgets('Pause and resume video recording', (WidgetTester tester) async { - final List cameras = await CameraPlatform.instance.availableCameras(); + final List cameras = + await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } @@ -166,7 +184,8 @@ void main() { sleep(const Duration(milliseconds: 500)); final XFile file = await controller.stopVideoRecording(); - final int recordingTime = DateTime.now().millisecondsSinceEpoch - recordingStart; + final int recordingTime = + DateTime.now().millisecondsSinceEpoch - recordingStart; final File videoFile = File(file.path); final VideoPlayerController videoController = VideoPlayerController.file( @@ -180,7 +199,8 @@ void main() { }); testWidgets('Set description while recording', (WidgetTester tester) async { - final List cameras = await CameraPlatform.instance.availableCameras(); + final List cameras = + await CameraPlatform.instance.availableCameras(); if (cameras.length < 2) { return; } @@ -201,7 +221,8 @@ void main() { }); testWidgets('Set description', (WidgetTester tester) async { - final List cameras = await CameraPlatform.instance.availableCameras(); + final List cameras = + await CameraPlatform.instance.availableCameras(); if (cameras.length < 2) { return; } @@ -219,7 +240,8 @@ void main() { }); /// Start streaming with specifying the ImageFormatGroup. - Future startStreaming(List cameras, ImageFormatGroup? imageFormatGroup) async { + Future startStreaming(List cameras, + ImageFormatGroup? imageFormatGroup) async { final CameraController controller = CameraController( cameras.first, ResolutionPreset.low, @@ -246,7 +268,8 @@ void main() { testWidgets( 'image streaming with imageFormatGroup', (WidgetTester tester) async { - final List cameras = await CameraPlatform.instance.availableCameras(); + final List cameras = + await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } @@ -269,7 +292,8 @@ void main() { ); testWidgets('Recording with video streaming', (WidgetTester tester) async { - final List cameras = await CameraPlatform.instance.availableCameras(); + final List cameras = + await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } @@ -283,7 +307,8 @@ void main() { await controller.initialize(); await controller.prepareForVideoRecording(); final Completer completer = Completer(); - await controller.startVideoRecording(streamCallback: (CameraImageData image) { + await controller.startVideoRecording( + streamCallback: (CameraImageData image) { if (!completer.isCompleted) { completer.complete(image); } @@ -296,14 +321,17 @@ void main() { }); // Test outputFormat is respected when taking a picture. - testWidgets('Capture specific image output formats', (WidgetTester tester) async { - final List cameras = await CameraPlatform.instance.availableCameras(); + testWidgets('Capture specific image output formats', + (WidgetTester tester) async { + final List cameras = + await CameraPlatform.instance.availableCameras(); if (cameras.isEmpty) { return; } for (final CameraDescription cameraDescription in cameras) { for (final OutputFormat outputFormat in OutputFormat.values) { - final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); + final CameraController controller = + CameraController(cameraDescription, ResolutionPreset.low); await controller.initialize(); await controller.setOutputFormat(outputFormat); final XFile file = await controller.takePicture(); diff --git a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart index 8347ff5e2cd..7e28907c27f 100644 --- a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart +++ b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart @@ -131,13 +131,17 @@ class CameraValue { exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: - lockedCaptureOrientation == null ? this.lockedCaptureOrientation : lockedCaptureOrientation.orNull, - recordingOrientation: recordingOrientation == null ? this.recordingOrientation : recordingOrientation.orNull, + lockedCaptureOrientation: lockedCaptureOrientation == null + ? this.lockedCaptureOrientation + : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null + ? this.recordingOrientation + : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, description: description ?? this.description, - previewPauseOrientation: - previewPauseOrientation == null ? this.previewPauseOrientation : previewPauseOrientation.orNull, + previewPauseOrientation: previewPauseOrientation == null + ? this.previewPauseOrientation + : previewPauseOrientation.orNull, ); } @@ -198,7 +202,8 @@ class CameraController extends ValueNotifier { bool _isDisposed = false; StreamSubscription? _imageStreamSubscription; FutureOr? _initCalled; - StreamSubscription? _deviceOrientationSubscription; + StreamSubscription? + _deviceOrientationSubscription; /// The camera identifier with which the controller is associated. int get cameraId => _cameraId; @@ -207,10 +212,12 @@ class CameraController extends ValueNotifier { Future initialize() => _initializeWithDescription(description); Future _initializeWithDescription(CameraDescription description) async { - final Completer initializeCompleter = Completer(); + final Completer initializeCompleter = + Completer(); - _deviceOrientationSubscription = - CameraPlatform.instance.onDeviceOrientationChanged().listen((DeviceOrientationChangedEvent event) { + _deviceOrientationSubscription = CameraPlatform.instance + .onDeviceOrientationChanged() + .listen((DeviceOrientationChangedEvent event) { value = value.copyWith( deviceOrientation: event.orientation, ); @@ -222,7 +229,10 @@ class CameraController extends ValueNotifier { enableAudio: enableAudio, ); - unawaited(CameraPlatform.instance.onCameraInitialized(_cameraId).first.then((CameraInitializedEvent event) { + unawaited(CameraPlatform.instance + .onCameraInitialized(_cameraId) + .first + .then((CameraInitializedEvent event) { initializeCompleter.complete(event); })); @@ -234,16 +244,19 @@ class CameraController extends ValueNotifier { value = value.copyWith( isInitialized: true, description: description, - previewSize: await initializeCompleter.future.then((CameraInitializedEvent event) => Size( - event.previewWidth, - event.previewHeight, - )), - exposureMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposureMode), - focusMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusMode), - exposurePointSupported: - await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposurePointSupported), - focusPointSupported: - await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusPointSupported), + previewSize: await initializeCompleter.future + .then((CameraInitializedEvent event) => Size( + event.previewWidth, + event.previewHeight, + )), + exposureMode: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.exposureMode), + focusMode: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.focusMode), + exposurePointSupported: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.exposurePointSupported), + focusPointSupported: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.focusPointSupported), ); _initCalled = true; @@ -259,14 +272,16 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: - Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); + previewPauseOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } /// Resumes the current camera preview Future resumePreview() async { await CameraPlatform.instance.resumePreview(_cameraId); - value = value.copyWith(isPreviewPaused: false, previewPauseOrientation: const Optional.absent()); + value = value.copyWith( + isPreviewPaused: false, + previewPauseOrientation: const Optional.absent()); } /// Sets the description of the camera @@ -290,9 +305,11 @@ class CameraController extends ValueNotifier { } /// Start streaming images from platform camera. - Future startImageStream(Function(CameraImageData image) onAvailable) async { - _imageStreamSubscription = - CameraPlatform.instance.onStreamedFrameAvailable(_cameraId).listen((CameraImageData imageData) { + Future startImageStream( + Function(CameraImageData image) onAvailable) async { + _imageStreamSubscription = CameraPlatform.instance + .onStreamedFrameAvailable(_cameraId) + .listen((CameraImageData imageData) { onAvailable(imageData); }); value = value.copyWith(isStreamingImages: true); @@ -309,14 +326,16 @@ class CameraController extends ValueNotifier { /// /// The video is returned as a [XFile] after calling [stopVideoRecording]. /// Throws a [CameraException] if the capture fails. - Future startVideoRecording({Function(CameraImageData image)? streamCallback}) async { - await CameraPlatform.instance.startVideoCapturing(VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); + Future startVideoRecording( + {Function(CameraImageData image)? streamCallback}) async { + await CameraPlatform.instance.startVideoCapturing( + VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, isStreamingImages: streamCallback != null, - recordingOrientation: - Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); + recordingOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } /// Stops the video recording and returns the file where it was saved. @@ -327,7 +346,8 @@ class CameraController extends ValueNotifier { await stopImageStream(); } - final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); + final XFile file = + await CameraPlatform.instance.stopVideoRecording(_cameraId); value = value.copyWith( isRecordingVideo: false, recordingOrientation: const Optional.absent(), @@ -377,7 +397,8 @@ class CameraController extends ValueNotifier { ]); // Round to the closest step if needed - final double stepSize = await CameraPlatform.instance.getExposureOffsetStepSize(_cameraId); + final double stepSize = + await CameraPlatform.instance.getExposureOffsetStepSize(_cameraId); if (stepSize > 0) { final double inv = 1.0 / stepSize; double roundedOffset = (offset * inv).roundToDouble() / inv; @@ -396,14 +417,18 @@ class CameraController extends ValueNotifier { /// /// If [orientation] is omitted, the current device orientation is used. Future lockCaptureOrientation() async { - await CameraPlatform.instance.lockCaptureOrientation(_cameraId, value.deviceOrientation); - value = value.copyWith(lockedCaptureOrientation: Optional.of(value.deviceOrientation)); + await CameraPlatform.instance + .lockCaptureOrientation(_cameraId, value.deviceOrientation); + value = value.copyWith( + lockedCaptureOrientation: + Optional.of(value.deviceOrientation)); } /// Unlocks the capture orientation. Future unlockCaptureOrientation() async { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith(lockedCaptureOrientation: const Optional.absent()); + value = value.copyWith( + lockedCaptureOrientation: const Optional.absent()); } /// Sets the focus mode for taking pictures. @@ -516,7 +541,9 @@ class Optional extends IterableBase { /// /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. Optional transform(S Function(T value) transformer) { - return _value == null ? Optional.absent() : Optional.of(transformer(_value as T)); + return _value == null + ? Optional.absent() + : Optional.of(transformer(_value as T)); } /// Transforms the Optional value. @@ -525,11 +552,14 @@ class Optional extends IterableBase { /// /// Returns [absent()] if the transformer returns `null`. Optional transformNullable(S? Function(T value) transformer) { - return _value == null ? Optional.absent() : Optional.fromNullable(transformer(_value as T)); + return _value == null + ? Optional.absent() + : Optional.fromNullable(transformer(_value as T)); } @override - Iterator get iterator => isPresent ? [_value as T].iterator : Iterable.empty().iterator; + Iterator get iterator => + isPresent ? [_value as T].iterator : Iterable.empty().iterator; /// Delegates to the underlying [value] hashCode. @override @@ -541,6 +571,8 @@ class Optional extends IterableBase { @override String toString() { - return _value == null ? 'Optional { absent }' : 'Optional { value: $_value }'; + return _value == null + ? 'Optional { absent }' + : 'Optional { value: $_value }'; } } diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 978ab656a50..3b07be79ffe 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -14,7 +14,8 @@ import 'package:stream_transform/stream_transform.dart'; import 'type_conversion.dart'; import 'utils.dart'; -const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera_avfoundation'); +const MethodChannel _channel = + MethodChannel('plugins.flutter.io/camera_avfoundation'); /// An iOS implementation of [CameraPlatform] based on AVFoundation. class AVFoundationCamera extends CameraPlatform { @@ -28,7 +29,8 @@ class AVFoundationCamera extends CameraPlatform { /// The name of the channel that device events from the platform side are /// sent on. @visibleForTesting - static const String deviceEventChannelName = 'plugins.flutter.io/camera_avfoundation/fromPlatform'; + static const String deviceEventChannelName = + 'plugins.flutter.io/camera_avfoundation/fromPlatform'; /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to camera events. @@ -38,14 +40,16 @@ class AVFoundationCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. /// /// It is a `broadcast` because multiple controllers will connect to /// different stream views of this Controller. - late final StreamController _deviceEventStreamController = _createDeviceEventStreamController(); + late final StreamController _deviceEventStreamController = + _createDeviceEventStreamController(); StreamController _createDeviceEventStreamController() { // Set up the method handler lazily. @@ -61,13 +65,14 @@ class AVFoundationCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -76,7 +81,8 @@ class AVFoundationCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -92,9 +98,12 @@ class AVFoundationCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -110,8 +119,10 @@ class AVFoundationCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('plugins.flutter.io/camera_avfoundation/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = MethodChannel( + 'plugins.flutter.io/camera_avfoundation/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -188,7 +199,8 @@ class AVFoundationCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return _deviceEventStreamController.stream.whereType(); + return _deviceEventStreamController.stream + .whereType(); } @override @@ -198,7 +210,10 @@ class AVFoundationCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -228,11 +243,14 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -277,18 +295,22 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { - _frameStreamController = _createStreamController(onListen: _onFrameStreamListen); + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { + _frameStreamController = + _createStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _createStreamController({Function()? onListen}) { + StreamController _createStreamController( + {Function()? onListen}) { return StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -307,14 +329,17 @@ class AVFoundationCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera_avfoundation/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { try { _channel.invokeMethod('receivedImageStreamData'); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -326,11 +351,13 @@ class AVFoundationCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -339,7 +366,8 @@ class AVFoundationCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -407,7 +435,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -483,7 +512,8 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -559,8 +589,8 @@ class AVFoundationCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - _deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + _deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -604,7 +634,9 @@ class AVFoundationCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 071795f371b..17b06cddc1a 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -32,31 +32,37 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! - .defaultBinaryMessenger - .handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), - (ByteData? data) {}); + final ByteData? response = + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall(const MethodCall( + 'orientation_changed', + {'orientation': 'portraitDown'})), + (ByteData? data) {}); expect(response, null); }); group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AVFoundationCamera camera = AVFoundationCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -64,13 +70,18 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -92,13 +103,16 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -120,8 +134,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -145,7 +161,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -157,14 +176,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -204,12 +224,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AVFoundationCamera camera = AVFoundationCamera(); final int cameraId = await camera.createCamera( @@ -283,8 +304,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -296,7 +319,8 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -307,17 +331,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -331,14 +362,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -351,14 +387,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -371,17 +413,22 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await _ambiguate(TestDefaultBinaryMessengerBinding.instance)!.defaultBinaryMessenger.handlePlatformMessage( - AVFoundationCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), - null); + await _ambiguate(TestDefaultBinaryMessengerBinding.instance)! + .defaultBinaryMessenger + .handlePlatformMessage( + AVFoundationCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -430,14 +477,23 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange // This deliberately uses 'dynamic' since that's what actual platform // channel results will be, so using typed mock data could mask type // handling bugs in the code under test. final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -453,17 +509,21 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -477,16 +537,19 @@ void main() { camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -536,7 +599,8 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -559,7 +623,9 @@ void main() { ]); }); - test('Should pass enableStream if callback is passed when starting recording a video', () async { + test( + 'Should pass enableStream if callback is passed when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -567,7 +633,8 @@ void main() { ); // Act - await camera.startVideoCapturing(VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {})); + await camera.startVideoCapturing(VideoCaptureOptions(cameraId, + streamCallback: (CameraImageData imageData) {})); // Assert expect(channel.log, [ @@ -640,17 +707,20 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = - CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); + const CameraDescription camera2Description = CameraDescription( + name: 'Test2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', + arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -669,10 +739,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -689,8 +767,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -707,10 +789,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -722,7 +812,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -741,7 +832,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -804,8 +896,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -822,10 +918,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -838,10 +942,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final AVFoundationCamera camera = AVFoundationCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -895,11 +1002,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -916,7 +1025,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -927,12 +1037,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -948,7 +1061,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -964,7 +1078,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -980,7 +1095,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -995,8 +1111,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1017,8 +1134,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 8a112fe06e2..a4948ca7b09 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -31,7 +31,6 @@ void main() { 'exposurePointSupported': true, 'focusMode': 'auto', 'focusPointSupported': true, - 'imageFormat': 'jpeg', }); expect(event.cameraId, 1); From 8564f1c1c2b02073a781d0021e9de43ddb6a9f3c Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 10:37:04 -0300 Subject: [PATCH 33/71] fix test --- .../test/events/camera_event_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index a4948ca7b09..6b9e9f6ca9f 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -55,7 +55,7 @@ void main() { final Map jsonMap = event.toJson(); - expect(jsonMap.length, 8); + expect(jsonMap.length, 7); expect(jsonMap['cameraId'], 1); expect(jsonMap['previewWidth'], 1024); expect(jsonMap['previewHeight'], 640); From cf53b1c1e52551a2e457a9916e54fe127c347432 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 14:17:59 -0300 Subject: [PATCH 34/71] remove comment --- packages/camera/camera/example/integration_test/camera_test.dart | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/camera/camera/example/integration_test/camera_test.dart b/packages/camera/camera/example/integration_test/camera_test.dart index 12e294afea1..38160827456 100644 --- a/packages/camera/camera/example/integration_test/camera_test.dart +++ b/packages/camera/camera/example/integration_test/camera_test.dart @@ -313,7 +313,6 @@ void main() { skip: !Platform.isIOS, ); - //test outputFormat for image testWidgets( 'Capture image with outputFormat', (WidgetTester tester) async { From dc2fb219fae23d010077651316b9b0186e440155 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 15:56:46 -0300 Subject: [PATCH 35/71] code format --- .../example/integration_test/camera_test.dart | 57 +- .../camera/lib/src/camera_controller.dart | 128 +-- .../camera/test/camera_preview_test.dart | 51 +- packages/camera/camera/test/camera_test.dart | 758 +++++++++++++----- .../test/android_camera_test.dart | 342 +++++--- .../method_channel/method_channel_camera.dart | 93 ++- .../platform_interface/camera_platform.dart | 15 +- .../test/events/camera_event_test.dart | 124 +-- .../method_channel_camera_test.dart | 383 ++++++--- 9 files changed, 1347 insertions(+), 604 deletions(-) diff --git a/packages/camera/camera/example/integration_test/camera_test.dart b/packages/camera/camera/example/integration_test/camera_test.dart index 38160827456..86654abf85d 100644 --- a/packages/camera/camera/example/integration_test/camera_test.dart +++ b/packages/camera/camera/example/integration_test/camera_test.dart @@ -27,9 +27,12 @@ void main() { await testDir.delete(recursive: true); }); - final Map presetExpectedSizes = { - ResolutionPreset.low: Platform.isAndroid ? const Size(240, 320) : const Size(288, 352), - ResolutionPreset.medium: Platform.isAndroid ? const Size(480, 720) : const Size(480, 640), + final Map presetExpectedSizes = + { + ResolutionPreset.low: + Platform.isAndroid ? const Size(240, 320) : const Size(288, 352), + ResolutionPreset.medium: + Platform.isAndroid ? const Size(480, 720) : const Size(480, 640), ResolutionPreset.high: const Size(720, 1280), ResolutionPreset.veryHigh: const Size(1080, 1920), ResolutionPreset.ultraHigh: const Size(2160, 3840), @@ -42,13 +45,15 @@ void main() { bool assertExpectedDimensions(Size expectedSize, Size actual) { expect(actual.shortestSide, lessThanOrEqualTo(expectedSize.shortestSide)); expect(actual.longestSide, lessThanOrEqualTo(expectedSize.longestSide)); - return actual.shortestSide == expectedSize.shortestSide && actual.longestSide == expectedSize.longestSide; + return actual.shortestSide == expectedSize.shortestSide && + actual.longestSide == expectedSize.longestSide; } // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. - Future testCaptureImageResolution(CameraController controller, ResolutionPreset preset) async { + Future testCaptureImageResolution( + CameraController controller, ResolutionPreset preset) async { final Size expectedSize = presetExpectedSizes[preset]!; // Take Picture @@ -60,7 +65,8 @@ void main() { // Verify image dimensions are as expected expect(image, isNotNull); - return assertExpectedDimensions(expectedSize, Size(image.height.toDouble(), image.width.toDouble())); + return assertExpectedDimensions( + expectedSize, Size(image.height.toDouble(), image.width.toDouble())); } testWidgets( @@ -72,10 +78,13 @@ void main() { } for (final CameraDescription cameraDescription in cameras) { bool previousPresetExactlySupported = true; - for (final MapEntry preset in presetExpectedSizes.entries) { - final CameraController controller = CameraController(cameraDescription, preset.key); + for (final MapEntry preset + in presetExpectedSizes.entries) { + final CameraController controller = + CameraController(cameraDescription, preset.key); await controller.initialize(); - final bool presetExactlySupported = await testCaptureImageResolution(controller, preset.key); + final bool presetExactlySupported = + await testCaptureImageResolution(controller, preset.key); assert(!(!previousPresetExactlySupported && presetExactlySupported), 'The camera took higher resolution pictures at a lower resolution.'); previousPresetExactlySupported = presetExactlySupported; @@ -90,7 +99,8 @@ void main() { // This tests that the capture is no bigger than the preset, since we have // automatic code to fall back to smaller sizes when we need to. Returns // whether the image is exactly the desired resolution. - Future testCaptureVideoResolution(CameraController controller, ResolutionPreset preset) async { + Future testCaptureVideoResolution( + CameraController controller, ResolutionPreset preset) async { final Size expectedSize = presetExpectedSizes[preset]!; // Take Video @@ -100,13 +110,15 @@ void main() { // Load video metadata final File videoFile = File(file.path); - final VideoPlayerController videoController = VideoPlayerController.file(videoFile); + final VideoPlayerController videoController = + VideoPlayerController.file(videoFile); await videoController.initialize(); final Size video = videoController.value.size; // Verify image dimensions are as expected expect(video, isNotNull); - return assertExpectedDimensions(expectedSize, Size(video.height, video.width)); + return assertExpectedDimensions( + expectedSize, Size(video.height, video.width)); } testWidgets( @@ -118,11 +130,14 @@ void main() { } for (final CameraDescription cameraDescription in cameras) { bool previousPresetExactlySupported = true; - for (final MapEntry preset in presetExpectedSizes.entries) { - final CameraController controller = CameraController(cameraDescription, preset.key); + for (final MapEntry preset + in presetExpectedSizes.entries) { + final CameraController controller = + CameraController(cameraDescription, preset.key); await controller.initialize(); await controller.prepareForVideoRecording(); - final bool presetExactlySupported = await testCaptureVideoResolution(controller, preset.key); + final bool presetExactlySupported = + await testCaptureVideoResolution(controller, preset.key); assert(!(!previousPresetExactlySupported && presetExactlySupported), 'The camera took higher resolution pictures at a lower resolution.'); previousPresetExactlySupported = presetExactlySupported; @@ -173,7 +188,8 @@ void main() { sleep(const Duration(milliseconds: 500)); final XFile file = await controller.stopVideoRecording(); - final int recordingTime = DateTime.now().millisecondsSinceEpoch - recordingStart; + final int recordingTime = + DateTime.now().millisecondsSinceEpoch - recordingStart; final File videoFile = File(file.path); final VideoPlayerController videoController = VideoPlayerController.file( @@ -224,7 +240,8 @@ void main() { ); /// Start streaming with specifying the ImageFormatGroup. - Future startStreaming(List cameras, ImageFormatGroup? imageFormatGroup) async { + Future startStreaming(List cameras, + ImageFormatGroup? imageFormatGroup) async { final CameraController controller = CameraController( cameras.first, ResolutionPreset.low, @@ -321,14 +338,16 @@ void main() { return; } for (final CameraDescription cameraDescription in cameras) { - final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); + final CameraController controller = + CameraController(cameraDescription, ResolutionPreset.low); await controller.setOutputFormat(OutputFormat.heif); await controller.initialize(); final XFile file = await controller.takePicture(); final File fileImage = File(file.path); - final Image image = await decodeImageFromList(fileImage.readAsBytesSync()); + final Image image = + await decodeImageFromList(fileImage.readAsBytesSync()); expect(image, isNotNull); } diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index cdc40ea76d3..f7eb386a5b8 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -183,16 +183,21 @@ class CameraValue { flashMode: flashMode ?? this.flashMode, exposureMode: exposureMode ?? this.exposureMode, focusMode: focusMode ?? this.focusMode, - exposurePointSupported: exposurePointSupported ?? this.exposurePointSupported, + exposurePointSupported: + exposurePointSupported ?? this.exposurePointSupported, focusPointSupported: focusPointSupported ?? this.focusPointSupported, deviceOrientation: deviceOrientation ?? this.deviceOrientation, - lockedCaptureOrientation: - lockedCaptureOrientation == null ? this.lockedCaptureOrientation : lockedCaptureOrientation.orNull, - recordingOrientation: recordingOrientation == null ? this.recordingOrientation : recordingOrientation.orNull, + lockedCaptureOrientation: lockedCaptureOrientation == null + ? this.lockedCaptureOrientation + : lockedCaptureOrientation.orNull, + recordingOrientation: recordingOrientation == null + ? this.recordingOrientation + : recordingOrientation.orNull, isPreviewPaused: isPreviewPaused ?? this.isPreviewPaused, description: description ?? this.description, - previewPauseOrientation: - previewPauseOrientation == null ? this.previewPauseOrientation : previewPauseOrientation.orNull, + previewPauseOrientation: previewPauseOrientation == null + ? this.previewPauseOrientation + : previewPauseOrientation.orNull, ); } @@ -272,7 +277,8 @@ class CameraController extends ValueNotifier { // just called). If the controller has not been initialized at least once, // this value is null. Future? _initializeFuture; - StreamSubscription? _deviceOrientationSubscription; + StreamSubscription? + _deviceOrientationSubscription; /// Checks whether [CameraController.dispose] has completed successfully. /// @@ -304,10 +310,12 @@ class CameraController extends ValueNotifier { _initializeFuture = initializeCompleter.future; try { - final Completer initializeCompleter = Completer(); + final Completer initializeCompleter = + Completer(); - _deviceOrientationSubscription ??= - CameraPlatform.instance.onDeviceOrientationChanged().listen((DeviceOrientationChangedEvent event) { + _deviceOrientationSubscription ??= CameraPlatform.instance + .onDeviceOrientationChanged() + .listen((DeviceOrientationChangedEvent event) { value = value.copyWith( deviceOrientation: event.orientation, ); @@ -319,7 +327,10 @@ class CameraController extends ValueNotifier { enableAudio: enableAudio, ); - _unawaited(CameraPlatform.instance.onCameraInitialized(_cameraId).first.then((CameraInitializedEvent event) { + _unawaited(CameraPlatform.instance + .onCameraInitialized(_cameraId) + .first + .then((CameraInitializedEvent event) { initializeCompleter.complete(event); })); @@ -331,16 +342,19 @@ class CameraController extends ValueNotifier { value = value.copyWith( isInitialized: true, description: description, - previewSize: await initializeCompleter.future.then((CameraInitializedEvent event) => Size( - event.previewWidth, - event.previewHeight, - )), - exposureMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposureMode), - focusMode: await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusMode), - exposurePointSupported: - await initializeCompleter.future.then((CameraInitializedEvent event) => event.exposurePointSupported), - focusPointSupported: - await initializeCompleter.future.then((CameraInitializedEvent event) => event.focusPointSupported), + previewSize: await initializeCompleter.future + .then((CameraInitializedEvent event) => Size( + event.previewWidth, + event.previewHeight, + )), + exposureMode: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.exposureMode), + focusMode: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.focusMode), + exposurePointSupported: await initializeCompleter.future.then( + (CameraInitializedEvent event) => event.exposurePointSupported), + focusPointSupported: await initializeCompleter.future + .then((CameraInitializedEvent event) => event.focusPointSupported), ); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -373,8 +387,8 @@ class CameraController extends ValueNotifier { await CameraPlatform.instance.pausePreview(_cameraId); value = value.copyWith( isPreviewPaused: true, - previewPauseOrientation: - Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation)); + previewPauseOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -387,8 +401,9 @@ class CameraController extends ValueNotifier { } try { await CameraPlatform.instance.resumePreview(_cameraId); - value = - value.copyWith(isPreviewPaused: false, previewPauseOrientation: const Optional.absent()); + value = value.copyWith( + isPreviewPaused: false, + previewPauseOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -451,7 +466,8 @@ class CameraController extends ValueNotifier { /// // TODO(bmparr): Add settings for resolution and fps. Future startImageStream(onLatestImageAvailable onAvailable) async { - assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('startImageStream'); if (value.isRecordingVideo) { throw CameraException( @@ -467,8 +483,9 @@ class CameraController extends ValueNotifier { } try { - _imageStreamSubscription = - CameraPlatform.instance.onStreamedFrameAvailable(_cameraId).listen((CameraImageData imageData) { + _imageStreamSubscription = CameraPlatform.instance + .onStreamedFrameAvailable(_cameraId) + .listen((CameraImageData imageData) { onAvailable(CameraImage.fromPlatformInterface(imageData)); }); value = value.copyWith(isStreamingImages: true); @@ -485,7 +502,8 @@ class CameraController extends ValueNotifier { /// The `stopImageStream` method is only available on Android and iOS (other /// platforms won't be supported in current setup). Future stopImageStream() async { - assert(defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS); + assert(defaultTargetPlatform == TargetPlatform.android || + defaultTargetPlatform == TargetPlatform.iOS); _throwIfNotInitialized('stopImageStream'); if (!value.isStreamingImages) { throw CameraException( @@ -510,7 +528,8 @@ class CameraController extends ValueNotifier { /// /// The video is returned as a [XFile] after calling [stopVideoRecording]. /// Throws a [CameraException] if the capture fails. - Future startVideoRecording({onLatestImageAvailable? onAvailable}) async { + Future startVideoRecording( + {onLatestImageAvailable? onAvailable}) async { _throwIfNotInitialized('startVideoRecording'); if (value.isRecordingVideo) { throw CameraException( @@ -527,12 +546,13 @@ class CameraController extends ValueNotifier { } try { - await CameraPlatform.instance.startVideoCapturing(VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); + await CameraPlatform.instance.startVideoCapturing( + VideoCaptureOptions(_cameraId, streamCallback: streamCallback)); value = value.copyWith( isRecordingVideo: true, isRecordingPaused: false, - recordingOrientation: - Optional.of(value.lockedCaptureOrientation ?? value.deviceOrientation), + recordingOrientation: Optional.of( + value.lockedCaptureOrientation ?? value.deviceOrientation), isStreamingImages: onAvailable != null); } on PlatformException catch (e) { throw CameraException(e.code, e.message); @@ -556,7 +576,8 @@ class CameraController extends ValueNotifier { } try { - final XFile file = await CameraPlatform.instance.stopVideoRecording(_cameraId); + final XFile file = + await CameraPlatform.instance.stopVideoRecording(_cameraId); value = value.copyWith( isRecordingVideo: false, recordingOrientation: const Optional.absent(), @@ -674,8 +695,10 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the exposure point to it's default /// value. Future setExposurePoint(Offset? point) async { - if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && + (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError( + 'The values of point should be anywhere between (0,0) and (1,1).'); } try { @@ -739,7 +762,8 @@ class CameraController extends ValueNotifier { Future setExposureOffset(double offset) async { _throwIfNotInitialized('setExposureOffset'); // Check if offset is in range - final List range = await Future.wait(>[getMinExposureOffset(), getMaxExposureOffset()]); + final List range = await Future.wait( + >[getMinExposureOffset(), getMaxExposureOffset()]); if (offset < range[0] || offset > range[1]) { throw CameraException( 'exposureOffsetOutOfBounds', @@ -772,9 +796,11 @@ class CameraController extends ValueNotifier { /// If [orientation] is omitted, the current device orientation is used. Future lockCaptureOrientation([DeviceOrientation? orientation]) async { try { - await CameraPlatform.instance.lockCaptureOrientation(_cameraId, orientation ?? value.deviceOrientation); + await CameraPlatform.instance.lockCaptureOrientation( + _cameraId, orientation ?? value.deviceOrientation); value = value.copyWith( - lockedCaptureOrientation: Optional.of(orientation ?? value.deviceOrientation)); + lockedCaptureOrientation: Optional.of( + orientation ?? value.deviceOrientation)); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -794,7 +820,8 @@ class CameraController extends ValueNotifier { Future unlockCaptureOrientation() async { try { await CameraPlatform.instance.unlockCaptureOrientation(_cameraId); - value = value.copyWith(lockedCaptureOrientation: const Optional.absent()); + value = value.copyWith( + lockedCaptureOrientation: const Optional.absent()); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } @@ -805,8 +832,10 @@ class CameraController extends ValueNotifier { /// Supplying a `null` value will reset the focus point to it's default /// value. Future setFocusPoint(Offset? point) async { - if (point != null && (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { - throw ArgumentError('The values of point should be anywhere between (0,0) and (1,1).'); + if (point != null && + (point.dx < 0 || point.dx > 1 || point.dy < 0 || point.dy > 1)) { + throw ArgumentError( + 'The values of point should be anywhere between (0,0) and (1,1).'); } try { await CameraPlatform.instance.setFocusPoint( @@ -948,7 +977,9 @@ class Optional extends IterableBase { /// /// The transformer must not return `null`. If it does, an [ArgumentError] is thrown. Optional transform(S Function(T value) transformer) { - return _value == null ? Optional.absent() : Optional.of(transformer(_value as T)); + return _value == null + ? Optional.absent() + : Optional.of(transformer(_value as T)); } /// Transforms the Optional value. @@ -957,11 +988,14 @@ class Optional extends IterableBase { /// /// Returns [absent()] if the transformer returns `null`. Optional transformNullable(S? Function(T value) transformer) { - return _value == null ? Optional.absent() : Optional.fromNullable(transformer(_value as T)); + return _value == null + ? Optional.absent() + : Optional.fromNullable(transformer(_value as T)); } @override - Iterator get iterator => isPresent ? [_value as T].iterator : Iterable.empty().iterator; + Iterator get iterator => + isPresent ? [_value as T].iterator : Iterable.empty().iterator; /// Delegates to the underlying [value] hashCode. @override @@ -973,6 +1007,8 @@ class Optional extends IterableBase { @override String toString() { - return _value == null ? 'Optional { absent }' : 'Optional { value: $_value }'; + return _value == null + ? 'Optional { absent }' + : 'Optional { value: $_value }'; } } diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index b2198bd273d..5e822f4e794 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -9,11 +9,12 @@ import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart'; -class FakeController extends ValueNotifier implements CameraController { +class FakeController extends ValueNotifier + implements CameraController { FakeController() : super(const CameraValue.uninitialized(fakeDescription)); - static const CameraDescription fakeDescription = - CameraDescription(name: '', lensDirection: CameraLensDirection.back, sensorOrientation: 0); + static const CameraDescription fakeDescription = CameraDescription( + name: '', lensDirection: CameraLensDirection.back, sensorOrientation: 0); @override Future dispose() async { @@ -95,7 +96,8 @@ class FakeController extends ValueNotifier implements CameraControl Future startImageStream(onLatestImageAvailable onAvailable) async {} @override - Future startVideoRecording({onLatestImageAvailable? onAvailable}) async {} + Future startVideoRecording( + {onLatestImageAvailable? onAvailable}) async {} @override Future stopImageStream() async {} @@ -130,7 +132,9 @@ class FakeController extends ValueNotifier implements CameraControl void main() { group('RotatedBox (Android only)', () { - testWidgets('when recording rotatedBox should turn according to recording orientation', ( + testWidgets( + 'when recording rotatedBox should turn according to recording orientation', + ( WidgetTester tester, ) async { debugDefaultTargetPlatformOverride = TargetPlatform.android; @@ -140,8 +144,11 @@ void main() { isInitialized: true, isRecordingVideo: true, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: const Optional.fromNullable(DeviceOrientation.landscapeRight), - recordingOrientation: const Optional.fromNullable(DeviceOrientation.landscapeLeft), + lockedCaptureOrientation: + const Optional.fromNullable( + DeviceOrientation.landscapeRight), + recordingOrientation: const Optional.fromNullable( + DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); @@ -153,13 +160,16 @@ void main() { ); expect(find.byType(RotatedBox), findsOneWidget); - final RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); + final RotatedBox rotatedBox = + tester.widget(find.byType(RotatedBox)); expect(rotatedBox.quarterTurns, 3); debugDefaultTargetPlatformOverride = null; }); - testWidgets('when orientation locked rotatedBox should turn according to locked orientation', ( + testWidgets( + 'when orientation locked rotatedBox should turn according to locked orientation', + ( WidgetTester tester, ) async { debugDefaultTargetPlatformOverride = TargetPlatform.android; @@ -168,8 +178,11 @@ void main() { controller.value = controller.value.copyWith( isInitialized: true, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: const Optional.fromNullable(DeviceOrientation.landscapeRight), - recordingOrientation: const Optional.fromNullable(DeviceOrientation.landscapeLeft), + lockedCaptureOrientation: + const Optional.fromNullable( + DeviceOrientation.landscapeRight), + recordingOrientation: const Optional.fromNullable( + DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); @@ -181,13 +194,16 @@ void main() { ); expect(find.byType(RotatedBox), findsOneWidget); - final RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); + final RotatedBox rotatedBox = + tester.widget(find.byType(RotatedBox)); expect(rotatedBox.quarterTurns, 1); debugDefaultTargetPlatformOverride = null; }); - testWidgets('when not locked and not recording rotatedBox should turn according to device orientation', ( + testWidgets( + 'when not locked and not recording rotatedBox should turn according to device orientation', + ( WidgetTester tester, ) async { debugDefaultTargetPlatformOverride = TargetPlatform.android; @@ -196,7 +212,8 @@ void main() { controller.value = controller.value.copyWith( isInitialized: true, deviceOrientation: DeviceOrientation.portraitUp, - recordingOrientation: const Optional.fromNullable(DeviceOrientation.landscapeLeft), + recordingOrientation: const Optional.fromNullable( + DeviceOrientation.landscapeLeft), previewSize: const Size(480, 640), ); @@ -208,14 +225,16 @@ void main() { ); expect(find.byType(RotatedBox), findsOneWidget); - final RotatedBox rotatedBox = tester.widget(find.byType(RotatedBox)); + final RotatedBox rotatedBox = + tester.widget(find.byType(RotatedBox)); expect(rotatedBox.quarterTurns, 0); debugDefaultTargetPlatformOverride = null; }); }, skip: kIsWeb); - testWidgets('when not on Android there should not be a rotated box', (WidgetTester tester) async { + testWidgets('when not on Android there should not be a rotated box', + (WidgetTester tester) async { debugDefaultTargetPlatformOverride = TargetPlatform.iOS; final FakeController controller = FakeController(); controller.value = controller.value.copyWith( diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index e220d283289..e512f6a25bd 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -15,13 +15,20 @@ import 'package:mockito/mockito.dart'; import 'package:plugin_platform_interface/plugin_platform_interface.dart'; List get mockAvailableCameras => [ - const CameraDescription(name: 'camBack', lensDirection: CameraLensDirection.back, sensorOrientation: 90), - const CameraDescription(name: 'camFront', lensDirection: CameraLensDirection.front, sensorOrientation: 180), + const CameraDescription( + name: 'camBack', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), + const CameraDescription( + name: 'camFront', + lensDirection: CameraLensDirection.front, + sensorOrientation: 180), ]; int get mockInitializeCamera => 13; -CameraInitializedEvent get mockOnCameraInitializedEvent => const CameraInitializedEvent( +CameraInitializedEvent get mockOnCameraInitializedEvent => + const CameraInitializedEvent( 13, 75, 75, @@ -36,7 +43,8 @@ DeviceOrientationChangedEvent get mockOnDeviceOrientationChangedEvent => CameraClosingEvent get mockOnCameraClosingEvent => const CameraClosingEvent(13); -CameraErrorEvent get mockOnCameraErrorEvent => const CameraErrorEvent(13, 'closing'); +CameraErrorEvent get mockOnCameraErrorEvent => + const CameraErrorEvent(13, 'closing'); XFile mockTakePicture = XFile('foo/bar.png'); @@ -48,7 +56,8 @@ void main() { WidgetsFlutterBinding.ensureInitialized(); group('camera', () { - test('debugCheckIsDisposed should not throw assertion error when disposed', () { + test('debugCheckIsDisposed should not throw assertion error when disposed', + () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -60,7 +69,8 @@ void main() { expect(controller.debugCheckIsDisposed, returnsNormally); }); - test('debugCheckIsDisposed should throw assertion error when not disposed', () { + test('debugCheckIsDisposed should throw assertion error when not disposed', + () { const MockCameraDescription description = MockCameraDescription(); final CameraController controller = CameraController( description, @@ -89,7 +99,10 @@ void main() { test('Can be initialized', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -100,7 +113,10 @@ void main() { test('can be disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -115,7 +131,10 @@ void main() { test('initialize() throws CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -136,9 +155,13 @@ void main() { ))); }); - test('initialize() throws $CameraException on $PlatformException ', () async { + test('initialize() throws $CameraException on $PlatformException ', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); mockPlatformException = true; @@ -156,15 +179,21 @@ void main() { test('initialize() sets imageFormat', () async { debugDefaultTargetPlatformOverride = TargetPlatform.android; final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max, imageFormatGroup: ImageFormatGroup.yuv420, ); await cameraController.initialize(); - verify(CameraPlatform.instance.initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)).called(1); + verify(CameraPlatform.instance + .initializeCamera(13, imageFormatGroup: ImageFormatGroup.yuv420)) + .called(1); }); - test('setDescription waits for initialize before calling dispose', () async { + test('setDescription waits for initialize before calling dispose', + () async { final CameraController cameraController = CameraController( const CameraDescription( name: 'cam', @@ -186,7 +215,10 @@ void main() { unawaited(cameraController.initialize()); final Future setDescriptionFuture = cameraController.setDescription( - const CameraDescription(name: 'cam2', lensDirection: CameraLensDirection.front, sensorOrientation: 90), + const CameraDescription( + name: 'cam2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 90), ); verifyNever(CameraPlatform.instance.dispose(mockInitializeCamera)); @@ -198,7 +230,10 @@ void main() { test('prepareForVideoRecording() calls $CameraPlatform ', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -209,7 +244,10 @@ void main() { test('takePicture() throws $CameraException when uninitialized ', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( cameraController.takePicture(), @@ -229,13 +267,18 @@ void main() { ); }); - test('takePicture() throws $CameraException when takePicture is true', () async { + test('takePicture() throws $CameraException when takePicture is true', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isTakingPicture: true); + cameraController.value = + cameraController.value.copyWith(isTakingPicture: true); expect( cameraController.takePicture(), throwsA(isA().having( @@ -247,7 +290,10 @@ void main() { test('takePicture() returns $XFile', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); final XFile xFile = await cameraController.takePicture(); @@ -255,9 +301,13 @@ void main() { expect(xFile.path, mockTakePicture.path); }); - test('takePicture() throws $CameraException on $PlatformException', () async { + test('takePicture() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -272,9 +322,13 @@ void main() { mockPlatformException = false; }); - test('startVideoRecording() throws $CameraException when uninitialized', () async { + test('startVideoRecording() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -294,14 +348,19 @@ void main() { ), ); }); - test('startVideoRecording() throws $CameraException when recording videos', () async { + test('startVideoRecording() throws $CameraException when recording videos', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isRecordingVideo: true); + cameraController.value = + cameraController.value.copyWith(isRecordingVideo: true); expect( cameraController.startVideoRecording(), @@ -312,9 +371,13 @@ void main() { ))); }); - test('getMaxZoomLevel() throws $CameraException when uninitialized', () async { + test('getMaxZoomLevel() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -337,7 +400,10 @@ void main() { test('getMaxZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -361,20 +427,29 @@ void main() { ); }); - test('getMaxZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'getMaxZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenThrow(CameraException( + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMaxZoomLevel, - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -383,19 +458,27 @@ void main() { test('getMaxZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMaxZoomLevel(mockInitializeCamera)) + .thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMaxZoomLevel(); expect(maxZoomLevel, 42.0); }); - test('getMinZoomLevel() throws $CameraException when uninitialized', () async { + test('getMinZoomLevel() throws $CameraException when uninitialized', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -418,7 +501,10 @@ void main() { test('getMinZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -442,20 +528,29 @@ void main() { ); }); - test('getMinZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'getMinZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenThrow(CameraException( + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( cameraController.getMinZoomLevel, - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -464,11 +559,15 @@ void main() { test('getMinZoomLevel() returns max zoom level.', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)).thenAnswer((_) => Future.value(42.0)); + when(CameraPlatform.instance.getMinZoomLevel(mockInitializeCamera)) + .thenAnswer((_) => Future.value(42.0)); final double maxZoomLevel = await cameraController.getMinZoomLevel(); expect(maxZoomLevel, 42.0); @@ -476,7 +575,10 @@ void main() { test('setZoomLevel() throws $CameraException when uninitialized', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); expect( @@ -499,7 +601,10 @@ void main() { test('setZoomLevel() throws $CameraException when disposed', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); @@ -523,20 +628,29 @@ void main() { ); }); - test('setZoomLevel() throws $CameraException when a platform exception occured.', () async { + test( + 'setZoomLevel() throws $CameraException when a platform exception occured.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).thenThrow(CameraException( + when(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) + .thenThrow(CameraException( 'TEST_ERROR', 'This is a test error messge', )); expect( () => cameraController.setZoomLevel(42), - throwsA(isA().having((CameraException error) => error.code, 'code', 'TEST_ERROR').having( + throwsA(isA() + .having( + (CameraException error) => error.code, 'code', 'TEST_ERROR') + .having( (CameraException error) => error.description, 'description', 'This is a test error messge', @@ -545,35 +659,52 @@ void main() { reset(CameraPlatform.instance); }); - test('setZoomLevel() completes and calls method channel with correct value.', () async { + test( + 'setZoomLevel() completes and calls method channel with correct value.', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setZoomLevel(42.0); - verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)).called(1); + verify(CameraPlatform.instance.setZoomLevel(mockInitializeCamera, 42.0)) + .called(1); }); test('setFlashMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setFlashMode(FlashMode.always); - verify(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).called(1); + verify(CameraPlatform.instance + .setFlashMode(cameraController.cameraId, FlashMode.always)) + .called(1); }); - test('setFlashMode() throws $CameraException on $PlatformException', () async { + test('setFlashMode() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setFlashMode(cameraController.cameraId, FlashMode.always)).thenThrow( + when(CameraPlatform.instance + .setFlashMode(cameraController.cameraId, FlashMode.always)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -591,22 +722,33 @@ void main() { test('setExposureMode() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposureMode(ExposureMode.auto); - verify(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).called(1); + verify(CameraPlatform.instance + .setExposureMode(cameraController.cameraId, ExposureMode.auto)) + .called(1); }); - test('setExposureMode() throws $CameraException on $PlatformException', () async { + test('setExposureMode() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposureMode(cameraController.cameraId, ExposureMode.auto)).thenThrow( + when(CameraPlatform.instance + .setExposureMode(cameraController.cameraId, ExposureMode.auto)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -624,23 +766,32 @@ void main() { test('setExposurePoint() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setExposurePoint(const Offset(0.5, 0.5)); - verify(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) + verify(CameraPlatform.instance.setExposurePoint( + cameraController.cameraId, const Point(0.5, 0.5))) .called(1); }); - test('setExposurePoint() throws $CameraException on $PlatformException', () async { + test('setExposurePoint() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setExposurePoint(cameraController.cameraId, const Point(0.5, 0.5))) + when(CameraPlatform.instance.setExposurePoint( + cameraController.cameraId, const Point(0.5, 0.5))) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -659,25 +810,37 @@ void main() { test('getMinExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getMinExposureOffset(); - verify(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .called(1); }); - test('getMinExposureOffset() throws $CameraException on $PlatformException', () async { + test('getMinExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -695,25 +858,37 @@ void main() { test('getMaxExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)) + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) .thenAnswer((_) => Future.value(1.0)); await cameraController.getMaxExposureOffset(); - verify(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .called(1); }); - test('getMaxExposureOffset() throws $CameraException on $PlatformException', () async { + test('getMaxExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -731,25 +906,38 @@ void main() { test('getExposureOffsetStepSize() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)) + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) .thenAnswer((_) => Future.value(0.0)); await cameraController.getExposureOffsetStepSize(); - verify(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .called(1); }); - test('getExposureOffsetStepSize() throws $CameraException on $PlatformException', () async { + test( + 'getExposureOffsetStepSize() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -767,28 +955,53 @@ void main() { test('setExposureOffset() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .thenAnswer((_) async => 1.0); await cameraController.setExposureOffset(1.0); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .called(1); }); - test('setExposureOffset() throws $CameraException on $PlatformException', () async { + test('setExposureOffset() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.0)).thenThrow( + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.0)) + .thenThrow( CameraException( 'TEST_ERROR', 'This is a test error message', @@ -804,17 +1017,34 @@ void main() { ))); }); - test('setExposureOffset() throws $CameraException when offset is out of bounds', () async { + test( + 'setExposureOffset() throws $CameraException when offset is out of bounds', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.0); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 2.0); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 1.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.0); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 2.0); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 1.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 2.0)) + .thenAnswer((_) async => 0.0); expect( cameraController.setExposureOffset(3.0), @@ -835,27 +1065,56 @@ void main() { await cameraController.setExposureOffset(-1.0); await cameraController.setExposureOffset(2.0); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(1); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.0)).called(1); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 2.0)).called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.0)) + .called(1); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 2.0)) + .called(1); }); test('setExposureOffset() rounds offset to nearest step', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.getMinExposureOffset(cameraController.cameraId)).thenAnswer((_) async => -1.2); - when(CameraPlatform.instance.getMaxExposureOffset(cameraController.cameraId)).thenAnswer((_) async => 1.2); - when(CameraPlatform.instance.getExposureOffsetStepSize(cameraController.cameraId)).thenAnswer((_) async => 0.4); - - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -1.2)).thenAnswer((_) async => -1.2); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).thenAnswer((_) async => -0.8); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).thenAnswer((_) async => -0.4); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).thenAnswer((_) async => 0.0); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).thenAnswer((_) async => 0.4); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).thenAnswer((_) async => 0.8); - when(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 1.2)).thenAnswer((_) async => 1.2); + when(CameraPlatform.instance + .getMinExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => -1.2); + when(CameraPlatform.instance + .getMaxExposureOffset(cameraController.cameraId)) + .thenAnswer((_) async => 1.2); + when(CameraPlatform.instance + .getExposureOffsetStepSize(cameraController.cameraId)) + .thenAnswer((_) async => 0.4); + + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -1.2)) + .thenAnswer((_) async => -1.2); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.8)) + .thenAnswer((_) async => -0.8); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.4)) + .thenAnswer((_) async => -0.4); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .thenAnswer((_) async => 0.0); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.4)) + .thenAnswer((_) async => 0.4); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.8)) + .thenAnswer((_) async => 0.8); + when(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 1.2)) + .thenAnswer((_) async => 1.2); await cameraController.setExposureOffset(1.2); await cameraController.setExposureOffset(-1.2); @@ -874,62 +1133,97 @@ void main() { await cameraController.setExposureOffset(-0.6); await cameraController.setExposureOffset(-0.7); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.8)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.8)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.0)).called(2); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, 0.4)).called(4); - verify(CameraPlatform.instance.setExposureOffset(cameraController.cameraId, -0.4)).called(4); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.8)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.8)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.0)) + .called(2); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, 0.4)) + .called(4); + verify(CameraPlatform.instance + .setExposureOffset(cameraController.cameraId, -0.4)) + .called(4); }); test('pausePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(deviceOrientation: DeviceOrientation.portraitUp); + cameraController.value = cameraController.value + .copyWith(deviceOrientation: DeviceOrientation.portraitUp); await cameraController.pausePreview(); - verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance.pausePreview(cameraController.cameraId)) + .called(1); expect(cameraController.value.isPreviewPaused, equals(true)); - expect(cameraController.value.previewPauseOrientation, DeviceOrientation.portraitUp); + expect(cameraController.value.previewPauseOrientation, + DeviceOrientation.portraitUp); }); - test('pausePreview() does not call $CameraPlatform when already paused', () async { + test('pausePreview() does not call $CameraPlatform when already paused', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); await cameraController.pausePreview(); - verifyNever(CameraPlatform.instance.pausePreview(cameraController.cameraId)); + verifyNever( + CameraPlatform.instance.pausePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(true)); }); - test('pausePreview() sets previewPauseOrientation according to locked orientation', () async { + test( + 'pausePreview() sets previewPauseOrientation according to locked orientation', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); cameraController.value = cameraController.value.copyWith( isPreviewPaused: false, deviceOrientation: DeviceOrientation.portraitUp, - lockedCaptureOrientation: Optional.of(DeviceOrientation.landscapeRight)); + lockedCaptureOrientation: + Optional.of(DeviceOrientation.landscapeRight)); await cameraController.pausePreview(); - expect(cameraController.value.deviceOrientation, equals(DeviceOrientation.portraitUp)); - expect(cameraController.value.previewPauseOrientation, equals(DeviceOrientation.landscapeRight)); + expect(cameraController.value.deviceOrientation, + equals(DeviceOrientation.portraitUp)); + expect(cameraController.value.previewPauseOrientation, + equals(DeviceOrientation.landscapeRight)); }); - test('pausePreview() throws $CameraException on $PlatformException', () async { + test('pausePreview() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.pausePreview(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance.pausePreview(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -947,37 +1241,54 @@ void main() { test('resumePreview() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); await cameraController.resumePreview(); - verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance.resumePreview(cameraController.cameraId)) + .called(1); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() does not call $CameraPlatform when not paused', () async { + test('resumePreview() does not call $CameraPlatform when not paused', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: false); + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: false); await cameraController.resumePreview(); - verifyNever(CameraPlatform.instance.resumePreview(cameraController.cameraId)); + verifyNever( + CameraPlatform.instance.resumePreview(cameraController.cameraId)); expect(cameraController.value.isPreviewPaused, equals(false)); }); - test('resumePreview() throws $CameraException on $PlatformException', () async { + test('resumePreview() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - cameraController.value = cameraController.value.copyWith(isPreviewPaused: true); - when(CameraPlatform.instance.resumePreview(cameraController.cameraId)).thenThrow( + cameraController.value = + cameraController.value.copyWith(isPreviewPaused: true); + when(CameraPlatform.instance.resumePreview(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -995,28 +1306,41 @@ void main() { test('lockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.lockCaptureOrientation(); - expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.portraitUp)); - await cameraController.lockCaptureOrientation(DeviceOrientation.landscapeRight); - expect(cameraController.value.lockedCaptureOrientation, equals(DeviceOrientation.landscapeRight)); - - verify(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) + expect(cameraController.value.lockedCaptureOrientation, + equals(DeviceOrientation.portraitUp)); + await cameraController + .lockCaptureOrientation(DeviceOrientation.landscapeRight); + expect(cameraController.value.lockedCaptureOrientation, + equals(DeviceOrientation.landscapeRight)); + + verify(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.portraitUp)) .called(1); - verify(CameraPlatform.instance - .lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.landscapeRight)) + verify(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.landscapeRight)) .called(1); }); - test('lockCaptureOrientation() throws $CameraException on $PlatformException', () async { + test( + 'lockCaptureOrientation() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.lockCaptureOrientation(cameraController.cameraId, DeviceOrientation.portraitUp)) + when(CameraPlatform.instance.lockCaptureOrientation( + cameraController.cameraId, DeviceOrientation.portraitUp)) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -1035,22 +1359,34 @@ void main() { test('unlockCaptureOrientation() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.unlockCaptureOrientation(); expect(cameraController.value.lockedCaptureOrientation, equals(null)); - verify(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).called(1); + verify(CameraPlatform.instance + .unlockCaptureOrientation(cameraController.cameraId)) + .called(1); }); - test('unlockCaptureOrientation() throws $CameraException on $PlatformException', () async { + test( + 'unlockCaptureOrientation() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.back, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.back, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.unlockCaptureOrientation(cameraController.cameraId)).thenThrow( + when(CameraPlatform.instance + .unlockCaptureOrientation(cameraController.cameraId)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1068,22 +1404,33 @@ void main() { test('setOutputFormat() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.front, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.front, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); await cameraController.setOutputFormat(OutputFormat.jpeg); - verify(CameraPlatform.instance.setOutputFormat(cameraController.cameraId, OutputFormat.jpeg)).called(1); + verify(CameraPlatform.instance + .setOutputFormat(cameraController.cameraId, OutputFormat.jpeg)) + .called(1); }); - test('setOutputFormat() throws $CameraException on $PlatformException', () async { + test('setOutputFormat() throws $CameraException on $PlatformException', + () async { final CameraController cameraController = CameraController( - const CameraDescription(name: 'cam', lensDirection: CameraLensDirection.front, sensorOrientation: 90), + const CameraDescription( + name: 'cam', + lensDirection: CameraLensDirection.front, + sensorOrientation: 90), ResolutionPreset.max); await cameraController.initialize(); - when(CameraPlatform.instance.setOutputFormat(cameraController.cameraId, OutputFormat.jpeg)).thenThrow( + when(CameraPlatform.instance + .setOutputFormat(cameraController.cameraId, OutputFormat.jpeg)) + .thenThrow( PlatformException( code: 'TEST_ERROR', message: 'This is a test error message', @@ -1101,7 +1448,9 @@ void main() { }); } -class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements CameraPlatform { +class MockCameraPlatform extends Mock + with MockPlatformInterfaceMixin + implements CameraPlatform { @override Future initializeCamera( int? cameraId, { @@ -1121,7 +1470,8 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements } @override - Future> availableCameras() => Future>.value(mockAvailableCameras); + Future> availableCameras() => + Future>.value(mockAvailableCameras); @override Future createCamera( @@ -1142,11 +1492,13 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements Stream.value(mockOnCameraClosingEvent); @override - Stream onCameraError(int cameraId) => Stream.value(mockOnCameraErrorEvent); + Stream onCameraError(int cameraId) => + Stream.value(mockOnCameraErrorEvent); @override Stream onDeviceOrientationChanged() => - Stream.value(mockOnDeviceOrientationChangedEvent); + Stream.value( + mockOnDeviceOrientationChangedEvent); @override Future takePicture(int cameraId) => mockPlatformException @@ -1158,29 +1510,34 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements super.noSuchMethod(Invocation.method(#prepareForVideoRecording, null)); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) => + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) => Future.value(mockVideoRecordingXFile); @override Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } @override - Future lockCaptureOrientation(int? cameraId, DeviceOrientation? orientation) async => - super.noSuchMethod(Invocation.method(#lockCaptureOrientation, [cameraId, orientation])); + Future lockCaptureOrientation( + int? cameraId, DeviceOrientation? orientation) async => + super.noSuchMethod(Invocation.method( + #lockCaptureOrientation, [cameraId, orientation])); @override Future unlockCaptureOrientation(int? cameraId) async => - super.noSuchMethod(Invocation.method(#unlockCaptureOrientation, [cameraId])); + super.noSuchMethod( + Invocation.method(#unlockCaptureOrientation, [cameraId])); @override Future pausePreview(int? cameraId) async => super.noSuchMethod(Invocation.method(#pausePreview, [cameraId])); @override - Future resumePreview(int? cameraId) async => - super.noSuchMethod(Invocation.method(#resumePreview, [cameraId])); + Future resumePreview(int? cameraId) async => super + .noSuchMethod(Invocation.method(#resumePreview, [cameraId])); @override Future getMaxZoomLevel(int? cameraId) async => super.noSuchMethod( @@ -1196,47 +1553,56 @@ class MockCameraPlatform extends Mock with MockPlatformInterfaceMixin implements @override Future setZoomLevel(int? cameraId, double? zoom) async => - super.noSuchMethod(Invocation.method(#setZoomLevel, [cameraId, zoom])); + super.noSuchMethod( + Invocation.method(#setZoomLevel, [cameraId, zoom])); @override Future setFlashMode(int? cameraId, FlashMode? mode) async => - super.noSuchMethod(Invocation.method(#setFlashMode, [cameraId, mode])); + super.noSuchMethod( + Invocation.method(#setFlashMode, [cameraId, mode])); @override Future setExposureMode(int? cameraId, ExposureMode? mode) async => - super.noSuchMethod(Invocation.method(#setExposureMode, [cameraId, mode])); + super.noSuchMethod( + Invocation.method(#setExposureMode, [cameraId, mode])); @override Future setExposurePoint(int? cameraId, Point? point) async => - super.noSuchMethod(Invocation.method(#setExposurePoint, [cameraId, point])); + super.noSuchMethod( + Invocation.method(#setExposurePoint, [cameraId, point])); @override - Future getMinExposureOffset(int? cameraId) async => super.noSuchMethod( + Future getMinExposureOffset(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getMinExposureOffset, [cameraId]), returnValue: Future.value(0.0), ) as Future; @override - Future getMaxExposureOffset(int? cameraId) async => super.noSuchMethod( + Future getMaxExposureOffset(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getMaxExposureOffset, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future getExposureOffsetStepSize(int? cameraId) async => super.noSuchMethod( + Future getExposureOffsetStepSize(int? cameraId) async => + super.noSuchMethod( Invocation.method(#getExposureOffsetStepSize, [cameraId]), returnValue: Future.value(1.0), ) as Future; @override - Future setExposureOffset(int? cameraId, double? offset) async => super.noSuchMethod( + Future setExposureOffset(int? cameraId, double? offset) async => + super.noSuchMethod( Invocation.method(#setExposureOffset, [cameraId, offset]), returnValue: Future.value(1.0), ) as Future; @override Future setOutputFormat(int cameraId, OutputFormat format) async => - super.noSuchMethod(Invocation.method(#setOutputFormat, [cameraId, format])); + super.noSuchMethod( + Invocation.method(#setOutputFormat, [cameraId, format])); } class MockCameraDescription extends CameraDescription { diff --git a/packages/camera/camera_android/test/android_camera_test.dart b/packages/camera/camera_android/test/android_camera_test.dart index 88055a0cacf..175ccd485b5 100644 --- a/packages/camera/camera_android/test/android_camera_test.dart +++ b/packages/camera/camera_android/test/android_camera_test.dart @@ -32,11 +32,13 @@ void main() { // registerWith is called very early in initialization the bindings won't // have been initialized. While registerWith could intialize them, that // could slow down startup, so instead the handler should be set up lazily. - final ByteData? response = await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + final ByteData? response = await TestDefaultBinaryMessengerBinding + .instance.defaultBinaryMessenger .handlePlatformMessage( AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall( - const MethodCall('orientation_changed', {'orientation': 'portraitDown'})), + const StandardMethodCodec().encodeMethodCall(const MethodCall( + 'orientation_changed', + {'orientation': 'portraitDown'})), (ByteData? data) {}); expect(response, null); }); @@ -44,18 +46,22 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final AndroidCamera camera = AndroidCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -63,13 +69,18 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -91,13 +102,16 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test('Should throw CameraException when create throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'create': PlatformException( @@ -119,8 +133,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -144,7 +160,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -156,14 +175,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -203,12 +223,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: _channelName, methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: _channelName, + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final AndroidCamera camera = AndroidCamera(); final int cameraId = await camera.createCamera( @@ -282,8 +303,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -295,7 +318,8 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -306,17 +330,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -330,14 +361,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -350,14 +386,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -370,17 +412,21 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); for (int i = 0; i < 3; i++) { - await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger.handlePlatformMessage( - AndroidCamera.deviceEventChannelName, - const StandardMethodCodec().encodeMethodCall(MethodCall('orientation_changed', event.toJson())), - null); + await TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .handlePlatformMessage( + AndroidCamera.deviceEventChannelName, + const StandardMethodCodec().encodeMethodCall( + MethodCall('orientation_changed', event.toJson())), + null); } // Assert @@ -429,11 +475,20 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -449,17 +504,21 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange MethodChannelMock(channelName: _channelName, methods: { 'availableCameras': PlatformException( @@ -473,23 +532,27 @@ void main() { camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); test('Should take a picture and return an XFile instance', () async { // Arrange - final MethodChannelMock channel = - MethodChannelMock(channelName: _channelName, methods: {'takePicture': '/test/path.jpg'}); + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); // Assert expect(channel.log, [ - isMethodCall('takePicture', arguments: {'cameraId': cameraId}), + isMethodCall('takePicture', + arguments: {'cameraId': cameraId}), ]); expect(file.path, '/test/path.jpg'); }); @@ -530,7 +593,8 @@ void main() { ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -553,7 +617,9 @@ void main() { ]); }); - test('Should pass enableStream if callback is passed when starting recording a video', () async { + test( + 'Should pass enableStream if callback is passed when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: _channelName, @@ -562,7 +628,8 @@ void main() { // Act await camera.startVideoCapturing( - VideoCaptureOptions(cameraId, streamCallback: (CameraImageData imageData) {}), + VideoCaptureOptions(cameraId, + streamCallback: (CameraImageData imageData) {}), ); // Assert @@ -636,17 +703,20 @@ void main() { channelName: _channelName, methods: {'setDescriptionWhileRecording': null}, ); - const CameraDescription camera2Description = - CameraDescription(name: 'Test2', lensDirection: CameraLensDirection.front, sensorOrientation: 0); + const CameraDescription camera2Description = CameraDescription( + name: 'Test2', + lensDirection: CameraLensDirection.front, + sensorOrientation: 0); // Act await camera.setDescriptionWhileRecording(camera2Description); // Assert expect(channel.log, [ - isMethodCall('setDescriptionWhileRecording', arguments: { - 'cameraName': camera2Description.name, - }), + isMethodCall('setDescriptionWhileRecording', + arguments: { + 'cameraName': camera2Description.name, + }), ]); }); @@ -665,10 +735,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFlashMode', + arguments: {'cameraId': cameraId, 'mode': 'off'}), ]); }); @@ -685,8 +763,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -703,10 +785,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -718,7 +808,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -737,7 +828,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -800,8 +892,12 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', + arguments: {'cameraId': cameraId, 'mode': 'auto'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -818,10 +914,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -834,10 +938,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final AndroidCamera camera = AndroidCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -891,11 +998,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: _channelName, @@ -912,7 +1021,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -923,12 +1033,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -944,7 +1057,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -960,7 +1074,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -976,7 +1091,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -991,8 +1107,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -1013,8 +1130,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 9b575761761..7f083c759d1 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -20,8 +20,10 @@ const MethodChannel _channel = MethodChannel('plugins.flutter.io/camera'); class MethodChannelCamera extends CameraPlatform { /// Construct a new method channel camera instance. MethodChannelCamera() { - const MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/device'); - channel.setMethodCallHandler((MethodCall call) => handleDeviceMethodCall(call)); + const MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/device'); + channel.setMethodCallHandler( + (MethodCall call) => handleDeviceMethodCall(call)); } final Map _channels = {}; @@ -34,7 +36,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController cameraEventStreamController = StreamController.broadcast(); + final StreamController cameraEventStreamController = + StreamController.broadcast(); /// The controller we need to broadcast the different events coming /// from handleMethodCall, specific to general device events. @@ -44,7 +47,8 @@ class MethodChannelCamera extends CameraPlatform { /// This is only exposed for test purposes. It shouldn't be used by clients of /// the plugin as it may break or change at any time. @visibleForTesting - final StreamController deviceEventStreamController = StreamController.broadcast(); + final StreamController deviceEventStreamController = + StreamController.broadcast(); // The stream to receive frames from the native code. StreamSubscription? _platformImageStreamSubscription; @@ -53,13 +57,14 @@ class MethodChannelCamera extends CameraPlatform { StreamController? _frameStreamController; Stream _cameraEvents(int cameraId) => - cameraEventStreamController.stream.where((CameraEvent event) => event.cameraId == cameraId); + cameraEventStreamController.stream + .where((CameraEvent event) => event.cameraId == cameraId); @override Future> availableCameras() async { try { - final List>? cameras = - await _channel.invokeListMethod>('availableCameras'); + final List>? cameras = await _channel + .invokeListMethod>('availableCameras'); if (cameras == null) { return []; @@ -68,7 +73,8 @@ class MethodChannelCamera extends CameraPlatform { return cameras.map((Map camera) { return CameraDescription( name: camera['name']! as String, - lensDirection: parseCameraLensDirection(camera['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(camera['lensFacing']! as String), sensorOrientation: camera['sensorOrientation']! as int, ); }).toList(); @@ -84,9 +90,12 @@ class MethodChannelCamera extends CameraPlatform { bool enableAudio = false, }) async { try { - final Map? reply = await _channel.invokeMapMethod('create', { + final Map? reply = await _channel + .invokeMapMethod('create', { 'cameraName': cameraDescription.name, - 'resolutionPreset': resolutionPreset != null ? _serializeResolutionPreset(resolutionPreset) : null, + 'resolutionPreset': resolutionPreset != null + ? _serializeResolutionPreset(resolutionPreset) + : null, 'enableAudio': enableAudio, }); @@ -102,8 +111,10 @@ class MethodChannelCamera extends CameraPlatform { ImageFormatGroup imageFormatGroup = ImageFormatGroup.unknown, }) { _channels.putIfAbsent(cameraId, () { - final MethodChannel channel = MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); - channel.setMethodCallHandler((MethodCall call) => handleCameraMethodCall(call, cameraId)); + final MethodChannel channel = + MethodChannel('flutter.io/cameraPlugin/camera$cameraId'); + channel.setMethodCallHandler( + (MethodCall call) => handleCameraMethodCall(call, cameraId)); return channel; }); @@ -180,7 +191,8 @@ class MethodChannelCamera extends CameraPlatform { @override Stream onDeviceOrientationChanged() { - return deviceEventStreamController.stream.whereType(); + return deviceEventStreamController.stream + .whereType(); } @override @@ -190,7 +202,10 @@ class MethodChannelCamera extends CameraPlatform { ) async { await _channel.invokeMethod( 'lockCaptureOrientation', - {'cameraId': cameraId, 'orientation': serializeDeviceOrientation(orientation)}, + { + 'cameraId': cameraId, + 'orientation': serializeDeviceOrientation(orientation) + }, ); } @@ -220,11 +235,14 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future prepareForVideoRecording() => _channel.invokeMethod('prepareForVideoRecording'); + Future prepareForVideoRecording() => + _channel.invokeMethod('prepareForVideoRecording'); @override - Future startVideoRecording(int cameraId, {Duration? maxVideoDuration}) async { - return startVideoCapturing(VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); + Future startVideoRecording(int cameraId, + {Duration? maxVideoDuration}) async { + return startVideoCapturing( + VideoCaptureOptions(cameraId, maxDuration: maxVideoDuration)); } @override @@ -268,18 +286,21 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future resumeVideoRecording(int cameraId) => _channel.invokeMethod( + Future resumeVideoRecording(int cameraId) => + _channel.invokeMethod( 'resumeVideoRecording', {'cameraId': cameraId}, ); @override - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { _installStreamController(onListen: _onFrameStreamListen); return _frameStreamController!.stream; } - StreamController _installStreamController({Function()? onListen}) { + StreamController _installStreamController( + {Function()? onListen}) { _frameStreamController = StreamController( onListen: onListen ?? () {}, onPause: _onFrameStreamPauseResume, @@ -299,8 +320,10 @@ class MethodChannelCamera extends CameraPlatform { } void _startStreamListener() { - const EventChannel cameraEventChannel = EventChannel('plugins.flutter.io/camera/imageStream'); - _platformImageStreamSubscription = cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { + const EventChannel cameraEventChannel = + EventChannel('plugins.flutter.io/camera/imageStream'); + _platformImageStreamSubscription = + cameraEventChannel.receiveBroadcastStream().listen((dynamic imageData) { if (defaultTargetPlatform == TargetPlatform.iOS) { try { _channel.invokeMethod('receivedImageStreamData'); @@ -308,7 +331,8 @@ class MethodChannelCamera extends CameraPlatform { throw CameraException(e.code, e.message); } } - _frameStreamController!.add(cameraImageFromPlatformData(imageData as Map)); + _frameStreamController! + .add(cameraImageFromPlatformData(imageData as Map)); }); } @@ -320,11 +344,13 @@ class MethodChannelCamera extends CameraPlatform { } void _onFrameStreamPauseResume() { - throw CameraException('InvalidCall', 'Pause and resume are not supported for onStreamedFrameAvailable'); + throw CameraException('InvalidCall', + 'Pause and resume are not supported for onStreamedFrameAvailable'); } @override - Future setFlashMode(int cameraId, FlashMode mode) => _channel.invokeMethod( + Future setFlashMode(int cameraId, FlashMode mode) => + _channel.invokeMethod( 'setFlashMode', { 'cameraId': cameraId, @@ -333,7 +359,8 @@ class MethodChannelCamera extends CameraPlatform { ); @override - Future setExposureMode(int cameraId, ExposureMode mode) => _channel.invokeMethod( + Future setExposureMode(int cameraId, ExposureMode mode) => + _channel.invokeMethod( 'setExposureMode', { 'cameraId': cameraId, @@ -401,7 +428,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFocusMode(int cameraId, FocusMode mode) => _channel.invokeMethod( + Future setFocusMode(int cameraId, FocusMode mode) => + _channel.invokeMethod( 'setFocusMode', { 'cameraId': cameraId, @@ -477,7 +505,8 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setDescriptionWhileRecording(CameraDescription description) async { + Future setDescriptionWhileRecording( + CameraDescription description) async { await _channel.invokeMethod( 'setDescriptionWhileRecording', { @@ -542,8 +571,8 @@ class MethodChannelCamera extends CameraPlatform { switch (call.method) { case 'orientation_changed': final Map arguments = _getArgumentDictionary(call); - deviceEventStreamController - .add(DeviceOrientationChangedEvent(deserializeDeviceOrientation(arguments['orientation']! as String))); + deviceEventStreamController.add(DeviceOrientationChangedEvent( + deserializeDeviceOrientation(arguments['orientation']! as String))); break; default: throw MissingPluginException(); @@ -587,7 +616,9 @@ class MethodChannelCamera extends CameraPlatform { cameraEventStreamController.add(VideoRecordedEvent( cameraId, XFile(arguments['path']! as String), - arguments['maxVideoDuration'] != null ? Duration(milliseconds: arguments['maxVideoDuration']! as int) : null, + arguments['maxVideoDuration'] != null + ? Duration(milliseconds: arguments['maxVideoDuration']! as int) + : null, )); break; case 'error': diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index c6e037d45e8..630d4063ca9 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -99,11 +99,13 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError( + 'onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation( + int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -140,7 +142,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -168,7 +171,8 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -267,7 +271,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError( + 'setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 6b9e9f6ca9f..990ead12a01 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -10,8 +10,8 @@ void main() { group('CameraInitializedEvent tests', () { test('Constructor should initialize all properties', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(event.cameraId, 1); expect(event.previewWidth, 1024); @@ -23,7 +23,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraInitializedEvent event = CameraInitializedEvent.fromJson(const { + final CameraInitializedEvent event = + CameraInitializedEvent.fromJson(const { 'cameraId': 1, 'previewWidth': 1024.0, 'previewHeight': 640.0, @@ -66,80 +67,81 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 2, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewWidth is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 2048, 640, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if previewHeight is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 980, ExposureMode.auto, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if exposureMode is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.locked, true, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); - test('equals should return false if exposurePointSupported is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); + test('equals should return false if exposurePointSupported is different', + () { + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, false, FocusMode.auto, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusMode is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.locked, true); expect(firstEvent == secondEvent, false); }); test('equals should return false if focusPointSupported is different', () { - const CameraInitializedEvent firstEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); - const CameraInitializedEvent secondEvent = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); + const CameraInitializedEvent firstEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent secondEvent = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, false); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraInitializedEvent event = - CameraInitializedEvent(1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); + const CameraInitializedEvent event = CameraInitializedEvent( + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.previewWidth, @@ -156,7 +158,8 @@ void main() { group('CameraResolutionChangesEvent tests', () { test('Constructor should initialize all properties', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); expect(event.cameraId, 1); expect(event.captureWidth, 1024); @@ -164,7 +167,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraResolutionChangedEvent event = CameraResolutionChangedEvent.fromJson(const { + final CameraResolutionChangedEvent event = + CameraResolutionChangedEvent.fromJson(const { 'cameraId': 1, 'captureWidth': 1024.0, 'captureHeight': 640.0, @@ -176,7 +180,8 @@ void main() { }); test('toJson should return a map with all fields', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); final Map jsonMap = event.toJson(); @@ -187,35 +192,44 @@ void main() { }); test('equals should return true if objects are the same', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 1024, 640); expect(firstEvent == secondEvent, true); }); test('equals should return false if cameraId is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(2, 1024, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(2, 1024, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureWidth is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 2048, 640); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 2048, 640); expect(firstEvent == secondEvent, false); }); test('equals should return false if captureHeight is different', () { - const CameraResolutionChangedEvent firstEvent = CameraResolutionChangedEvent(1, 1024, 640); - const CameraResolutionChangedEvent secondEvent = CameraResolutionChangedEvent(1, 1024, 980); + const CameraResolutionChangedEvent firstEvent = + CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent secondEvent = + CameraResolutionChangedEvent(1, 1024, 980); expect(firstEvent == secondEvent, false); }); test('hashCode should match hashCode of all properties', () { - const CameraResolutionChangedEvent event = CameraResolutionChangedEvent(1, 1024, 640); + const CameraResolutionChangedEvent event = + CameraResolutionChangedEvent(1, 1024, 640); final int expectedHashCode = Object.hash( event.cameraId.hashCode, event.captureWidth, @@ -234,7 +248,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraClosingEvent event = CameraClosingEvent.fromJson(const { + final CameraClosingEvent event = + CameraClosingEvent.fromJson(const { 'cameraId': 1, }); @@ -281,8 +296,8 @@ void main() { }); test('fromJson should initialize all properties', () { - final CameraErrorEvent event = - CameraErrorEvent.fromJson(const {'cameraId': 1, 'description': 'Error'}); + final CameraErrorEvent event = CameraErrorEvent.fromJson( + const {'cameraId': 1, 'description': 'Error'}); expect(event.cameraId, 1); expect(event.description, 'Error'); @@ -321,7 +336,8 @@ void main() { test('hashCode should match hashCode of all properties', () { const CameraErrorEvent event = CameraErrorEvent(1, 'Error'); - final int expectedHashCode = Object.hash(event.cameraId.hashCode, event.description); + final int expectedHashCode = + Object.hash(event.cameraId.hashCode, event.description); expect(event.hashCode, expectedHashCode); }); diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index 7bb119d66fc..1fd6445e746 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -22,18 +22,22 @@ void main() { group('Creation, Initialization & Disposal Tests', () { test('Should send creation data and receive back a camera id', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - } - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + } + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act final int cameraId = await camera.createCamera( - const CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0), + const CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0), ResolutionPreset.high, ); @@ -41,20 +45,28 @@ void main() { expect(cameraMockChannel.log, [ isMethodCall( 'create', - arguments: {'cameraName': 'Test', 'resolutionPreset': 'high', 'enableAudio': false}, + arguments: { + 'cameraName': 'Test', + 'resolutionPreset': 'high', + 'enableAudio': false + }, ), ]); expect(cameraId, 1); }); - test('Should throw CameraException when create throws a PlatformException', () { + test( + 'Should throw CameraException when create throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -69,20 +81,26 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); - test('Should throw CameraException when create throws a PlatformException', () { + test( + 'Should throw CameraException when create throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); final MethodChannelCamera camera = MethodChannelCamera(); // Act @@ -97,8 +115,10 @@ void main() { ), throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -122,7 +142,10 @@ void main() { expect( () => camera.initializeCamera(0), throwsA( - isA().having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE').having( + isA() + .having((CameraException e) => e.code, 'code', + 'TESTING_ERROR_CODE') + .having( (CameraException e) => e.description, 'description', 'Mock error message used during testing.', @@ -134,14 +157,15 @@ void main() { test('Should send initialization data', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': { - 'cameraId': 1, - 'imageFormatGroup': 'unknown', - }, - 'initialize': null - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': { + 'cameraId': 1, + 'imageFormatGroup': 'unknown', + }, + 'initialize': null + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( const CameraDescription( @@ -181,12 +205,13 @@ void main() { test('Should send a disposal call on dispose', () async { // Arrange - final MethodChannelMock cameraMockChannel = - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'create': {'cameraId': 1}, - 'initialize': null, - 'dispose': {'cameraId': 1} - }); + final MethodChannelMock cameraMockChannel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'create': {'cameraId': 1}, + 'initialize': null, + 'dispose': {'cameraId': 1} + }); final MethodChannelCamera camera = MethodChannelCamera(); final int cameraId = await camera.createCamera( @@ -260,8 +285,10 @@ void main() { test('Should receive initialized event', () async { // Act - final Stream eventStream = camera.onCameraInitialized(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraInitialized(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraInitializedEvent event = CameraInitializedEvent( @@ -273,7 +300,8 @@ void main() { FocusMode.auto, true, ); - await camera.handleCameraMethodCall(MethodCall('initialized', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('initialized', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -284,17 +312,24 @@ void main() { test('Should receive resolution changes', () async { // Act - final Stream resolutionStream = camera.onCameraResolutionChanged(cameraId); + final Stream resolutionStream = + camera.onCameraResolutionChanged(cameraId); final StreamQueue streamQueue = StreamQueue(resolutionStream); // Emit test events - final CameraResolutionChangedEvent fhdEvent = CameraResolutionChangedEvent(cameraId, 1920, 1080); - final CameraResolutionChangedEvent uhdEvent = CameraResolutionChangedEvent(cameraId, 3840, 2160); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + final CameraResolutionChangedEvent fhdEvent = + CameraResolutionChangedEvent(cameraId, 1920, 1080); + final CameraResolutionChangedEvent uhdEvent = + CameraResolutionChangedEvent(cameraId, 3840, 2160); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', fhdEvent.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('resolution_changed', uhdEvent.toJson()), cameraId); // Assert expect(await streamQueue.next, fhdEvent); @@ -308,14 +343,19 @@ void main() { test('Should receive camera closing events', () async { // Act - final Stream eventStream = camera.onCameraClosing(cameraId); - final StreamQueue streamQueue = StreamQueue(eventStream); + final Stream eventStream = + camera.onCameraClosing(cameraId); + final StreamQueue streamQueue = + StreamQueue(eventStream); // Emit test events final CameraClosingEvent event = CameraClosingEvent(cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('camera_closing', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -328,14 +368,20 @@ void main() { test('Should receive camera error events', () async { // Act - final Stream errorStream = camera.onCameraError(cameraId); - final StreamQueue streamQueue = StreamQueue(errorStream); + final Stream errorStream = + camera.onCameraError(cameraId); + final StreamQueue streamQueue = + StreamQueue(errorStream); // Emit test events - final CameraErrorEvent event = CameraErrorEvent(cameraId, 'Error Description'); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); - await camera.handleCameraMethodCall(MethodCall('error', event.toJson()), cameraId); + final CameraErrorEvent event = + CameraErrorEvent(cameraId, 'Error Description'); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); + await camera.handleCameraMethodCall( + MethodCall('error', event.toJson()), cameraId); // Assert expect(await streamQueue.next, event); @@ -348,15 +394,20 @@ void main() { test('Should receive device orientation change events', () async { // Act - final Stream eventStream = camera.onDeviceOrientationChanged(); + final Stream eventStream = + camera.onDeviceOrientationChanged(); final StreamQueue streamQueue = StreamQueue(eventStream); // Emit test events - const DeviceOrientationChangedEvent event = DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); - await camera.handleDeviceMethodCall(MethodCall('orientation_changed', event.toJson())); + const DeviceOrientationChangedEvent event = + DeviceOrientationChangedEvent(DeviceOrientation.portraitUp); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); + await camera.handleDeviceMethodCall( + MethodCall('orientation_changed', event.toJson())); // Assert expect(await streamQueue.next, event); @@ -404,11 +455,20 @@ void main() { await initializeFuture; }); - test('Should fetch CameraDescription instances for available cameras', () async { + test('Should fetch CameraDescription instances for available cameras', + () async { // Arrange final List returnData = [ - {'name': 'Test 1', 'lensFacing': 'front', 'sensorOrientation': 1}, - {'name': 'Test 2', 'lensFacing': 'back', 'sensorOrientation': 2} + { + 'name': 'Test 1', + 'lensFacing': 'front', + 'sensorOrientation': 1 + }, + { + 'name': 'Test 2', + 'lensFacing': 'back', + 'sensorOrientation': 2 + } ]; final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -424,32 +484,40 @@ void main() { ]); expect(cameras.length, returnData.length); for (int i = 0; i < returnData.length; i++) { - final Map typedData = (returnData[i] as Map).cast(); + final Map typedData = + (returnData[i] as Map).cast(); final CameraDescription cameraDescription = CameraDescription( name: typedData['name']! as String, - lensDirection: parseCameraLensDirection(typedData['lensFacing']! as String), + lensDirection: + parseCameraLensDirection(typedData['lensFacing']! as String), sensorOrientation: typedData['sensorOrientation']! as int, ); expect(cameras[i], cameraDescription); } }); - test('Should throw CameraException when availableCameras throws a PlatformException', () { + test( + 'Should throw CameraException when availableCameras throws a PlatformException', + () { // Arrange - MethodChannelMock(channelName: 'plugins.flutter.io/camera', methods: { - 'availableCameras': PlatformException( - code: 'TESTING_ERROR_CODE', - message: 'Mock error message used during testing.', - ) - }); + MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'availableCameras': PlatformException( + code: 'TESTING_ERROR_CODE', + message: 'Mock error message used during testing.', + ) + }); // Act expect( camera.availableCameras, throwsA( isA() - .having((CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') - .having((CameraException e) => e.description, 'description', 'Mock error message used during testing.'), + .having( + (CameraException e) => e.code, 'code', 'TESTING_ERROR_CODE') + .having((CameraException e) => e.description, 'description', + 'Mock error message used during testing.'), ), ); }); @@ -457,7 +525,8 @@ void main() { test('Should take a picture and return an XFile instance', () async { // Arrange final MethodChannelMock channel = MethodChannelMock( - channelName: 'plugins.flutter.io/camera', methods: {'takePicture': '/test/path.jpg'}); + channelName: 'plugins.flutter.io/camera', + methods: {'takePicture': '/test/path.jpg'}); // Act final XFile file = await camera.takePicture(cameraId); @@ -515,18 +584,23 @@ void main() { ); // Act - const CameraDescription cameraDescription = - CameraDescription(name: 'Test', lensDirection: CameraLensDirection.back, sensorOrientation: 0); + const CameraDescription cameraDescription = CameraDescription( + name: 'Test', + lensDirection: CameraLensDirection.back, + sensorOrientation: 0); await camera.setDescriptionWhileRecording(cameraDescription); // Assert expect(channel.log, [ isMethodCall('setDescriptionWhileRecording', - arguments: {'cameraName': cameraDescription.name}), + arguments: { + 'cameraName': cameraDescription.name + }), ]); }); - test('Should pass maxVideoDuration when starting recording a video', () async { + test('Should pass maxVideoDuration when starting recording a video', + () async { // Arrange final MethodChannelMock channel = MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -619,10 +693,22 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'torch'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'always'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFlashMode', arguments: {'cameraId': cameraId, 'mode': 'off'}), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'torch' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'always' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setFlashMode', arguments: { + 'cameraId': cameraId, + 'mode': 'off' + }), ]); }); @@ -639,8 +725,14 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setExposureMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setExposureMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -657,10 +749,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setExposurePoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setExposurePoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -672,7 +772,8 @@ void main() { ); // Act - final double minExposureOffset = await camera.getMinExposureOffset(cameraId); + final double minExposureOffset = + await camera.getMinExposureOffset(cameraId); // Assert expect(minExposureOffset, 2.0); @@ -691,7 +792,8 @@ void main() { ); // Act - final double maxExposureOffset = await camera.getMaxExposureOffset(cameraId); + final double maxExposureOffset = + await camera.getMaxExposureOffset(cameraId); // Assert expect(maxExposureOffset, 2.0); @@ -710,14 +812,16 @@ void main() { ); // Act - final double stepSize = await camera.getExposureOffsetStepSize(cameraId); + final double stepSize = + await camera.getExposureOffsetStepSize(cameraId); // Assert expect(stepSize, 0.25); expect(channel.log, [ - isMethodCall('getExposureOffsetStepSize', arguments: { - 'cameraId': cameraId, - }), + isMethodCall('getExposureOffsetStepSize', + arguments: { + 'cameraId': cameraId, + }), ]); }); @@ -729,7 +833,8 @@ void main() { ); // Act - final double actualOffset = await camera.setExposureOffset(cameraId, 0.5); + final double actualOffset = + await camera.setExposureOffset(cameraId, 0.5); // Assert expect(actualOffset, 0.6); @@ -754,8 +859,14 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'auto'}), - isMethodCall('setFocusMode', arguments: {'cameraId': cameraId, 'mode': 'locked'}), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'auto' + }), + isMethodCall('setFocusMode', arguments: { + 'cameraId': cameraId, + 'mode': 'locked' + }), ]); }); @@ -772,10 +883,18 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': 0.5, 'y': 0.5, 'reset': false}), - isMethodCall('setFocusPoint', - arguments: {'cameraId': cameraId, 'x': null, 'y': null, 'reset': true}), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': 0.5, + 'y': 0.5, + 'reset': false + }), + isMethodCall('setFocusPoint', arguments: { + 'cameraId': cameraId, + 'x': null, + 'y': null, + 'reset': true + }), ]); }); @@ -788,10 +907,13 @@ void main() { expect((widget as Texture).textureId, cameraId); }); - test('Should throw MissingPluginException when handling unknown method', () { + test('Should throw MissingPluginException when handling unknown method', + () { final MethodChannelCamera camera = MethodChannelCamera(); - expect(() => camera.handleCameraMethodCall(const MethodCall('unknown_method'), 1), + expect( + () => camera.handleCameraMethodCall( + const MethodCall('unknown_method'), 1), throwsA(isA())); }); @@ -845,11 +967,13 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('setZoomLevel', arguments: {'cameraId': cameraId, 'zoom': 2.0}), + isMethodCall('setZoomLevel', + arguments: {'cameraId': cameraId, 'zoom': 2.0}), ]); }); - test('Should throw CameraException when illegal zoom level is supplied', () async { + test('Should throw CameraException when illegal zoom level is supplied', + () async { // Arrange MethodChannelMock( channelName: 'plugins.flutter.io/camera', @@ -866,7 +990,8 @@ void main() { () => camera.setZoomLevel(cameraId, -1.0), throwsA(isA() .having((CameraException e) => e.code, 'code', 'ZOOM_ERROR') - .having((CameraException e) => e.description, 'description', 'Illegal zoom error'))); + .having((CameraException e) => e.description, 'description', + 'Illegal zoom error'))); }); test('Should lock the capture orientation', () async { @@ -877,12 +1002,15 @@ void main() { ); // Act - await camera.lockCaptureOrientation(cameraId, DeviceOrientation.portraitUp); + await camera.lockCaptureOrientation( + cameraId, DeviceOrientation.portraitUp); // Assert expect(channel.log, [ - isMethodCall('lockCaptureOrientation', - arguments: {'cameraId': cameraId, 'orientation': 'portraitUp'}), + isMethodCall('lockCaptureOrientation', arguments: { + 'cameraId': cameraId, + 'orientation': 'portraitUp' + }), ]); }); @@ -898,7 +1026,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('unlockCaptureOrientation', arguments: {'cameraId': cameraId}), + isMethodCall('unlockCaptureOrientation', + arguments: {'cameraId': cameraId}), ]); }); @@ -914,7 +1043,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('pausePreview', arguments: {'cameraId': cameraId}), + isMethodCall('pausePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -930,7 +1060,8 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('resumePreview', arguments: {'cameraId': cameraId}), + isMethodCall('resumePreview', + arguments: {'cameraId': cameraId}), ]); }); @@ -945,8 +1076,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); // Assert expect(channel.log, [ @@ -967,8 +1099,9 @@ void main() { ); // Act - final StreamSubscription subscription = - camera.onStreamedFrameAvailable(cameraId).listen((CameraImageData imageData) {}); + final StreamSubscription subscription = camera + .onStreamedFrameAvailable(cameraId) + .listen((CameraImageData imageData) {}); await subscription.cancel(); // Assert From c22989eba770e4a45ccb2dda82f08bacc75dd95e Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 16:18:58 -0300 Subject: [PATCH 36/71] fix format --- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 89 +++++++++---------- .../camera_avfoundation/ios/Classes/FLTCam.m | 6 +- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 9d22670b5a0..f5dc3dab461 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -95,53 +95,50 @@ - (void)testCaptureToFile_mustReportPathToResultIfSavePhotoDelegateCompletionsWi } - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContainsHEVC { - // This test is only valid on iOS 11 or later. - if (@available(iOS 11.0, *)) { - XCTestExpectation *expectation = - [self expectationWithDescription: - @"Test must set extension to heif if availablePhotoCodecTypes contains HEVC."]; - - dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); - dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, - (void *)FLTCaptureSessionQueueSpecific, NULL); - FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); - [cam setOutputFormat:OutputFormatHEIF]; - - // Set photo settings to HEVC - AVCapturePhotoSettings *settings = - [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - - id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); - OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings);; - - NSString *filePath = @"test"; - id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); - OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { - [expectation fulfill]; - }); - - id mockOutput = OCMClassMock([AVCapturePhotoOutput class]); - // Set availablePhotoCodecTypes to HEVC - NSArray *codecTypes = @[AVVideoCodecTypeHEVC]; - OCMStub([mockOutput availablePhotoCodecTypes]).andReturn(codecTypes); - - OCMStub([mockOutput capturePhotoWithSettings:OCMOCK_ANY delegate:OCMOCK_ANY]) - .andDo(^(NSInvocation *invocation) { - FLTSavePhotoDelegate *delegate = cam.inProgressSavePhotoDelegates[@(settings.uniqueID)]; - // Completion runs on IO queue. - dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); - dispatch_async(ioQueue, ^{ - delegate.completionHandler(filePath, nil); - }); + // This test is only valid on iOS 11 or later. + if (@available(iOS 11.0, *)) { + XCTestExpectation *expectation = + [self expectationWithDescription: + @"Test must set extension to heif if availablePhotoCodecTypes contains HEVC."]; + dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); + dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, + (void *)FLTCaptureSessionQueueSpecific, NULL); + FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); + [cam setOutputFormat:OutputFormatHEIF]; + + // Set photo settings to HEVC + AVCapturePhotoSettings *settings = + [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + + id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); + OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); + + NSString *filePath = @"test"; + id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); + OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { + [expectation fulfill]; + }); + + id mockOutput = OCMClassMock([AVCapturePhotoOutput class]); + // Set availablePhotoCodecTypes to HEVC + NSArray *codecTypes = @[AVVideoCodecTypeHEVC]; + OCMStub([mockOutput availablePhotoCodecTypes]).andReturn(codecTypes); + + OCMStub([mockOutput capturePhotoWithSettings:OCMOCK_ANY delegate:OCMOCK_ANY]) + .andDo(^(NSInvocation *invocation) { + FLTSavePhotoDelegate *delegate = cam.inProgressSavePhotoDelegates[@(settings.uniqueID)]; + // Completion runs on IO queue. + dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); + dispatch_async(ioQueue, ^{ + delegate.completionHandler(filePath, nil); }); - cam.capturePhotoOutput = mockOutput; - - // `FLTCam::captureToFile` runs on capture session queue. - dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult]; }); - - [self waitForExpectationsWithTimeout:1 handler:nil]; - } + cam.capturePhotoOutput = mockOutput; + // `FLTCam::captureToFile` runs on capture session queue. + dispatch_async(captureSessionQueue, ^{ + [cam captureToFile:mockResult]; + }); + [self waitForExpectationsWithTimeout:1 handler:nil]; + } } @end diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index b77beb41a92..b866a73e727 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -267,9 +267,9 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { if (_outputFormat == OutputFormatHEIF) { if (@available(iOS 11.0, *)) { if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { - settings = [AVCapturePhotoSettings - photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - extension = @"heif"; + settings = [AVCapturePhotoSettings + photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + extension = @"heif"; } } } From a95ccef606226e0a27a0c16858057a3f65949d30 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 16:34:09 -0300 Subject: [PATCH 37/71] format code --- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 19 ++++++++++--------- .../camera_avfoundation/ios/Classes/FLTCam.m | 6 +++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index f5dc3dab461..f6e5e080700 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -114,9 +114,9 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); NSString *filePath = @"test"; - id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); + id mockResult = OCMClassMock([ FLTThreadSafeFlutterResult class]); OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { - [expectation fulfill]; + [expectation fulfill]; }); id mockOutput = OCMClassMock([AVCapturePhotoOutput class]); @@ -124,19 +124,20 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai NSArray *codecTypes = @[AVVideoCodecTypeHEVC]; OCMStub([mockOutput availablePhotoCodecTypes]).andReturn(codecTypes); + OCMStub([mockOutput capturePhotoWithSettings:OCMOCK_ANY delegate:OCMOCK_ANY]) .andDo(^(NSInvocation *invocation) { - FLTSavePhotoDelegate *delegate = cam.inProgressSavePhotoDelegates[@(settings.uniqueID)]; - // Completion runs on IO queue. - dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); - dispatch_async(ioQueue, ^{ - delegate.completionHandler(filePath, nil); - }); + FLTSavePhotoDelegate *delegate = cam.inProgressSavePhotoDelegates[@(settings.uniqueID)]; + // Completion runs on IO queue. + dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); + dispatch_async(ioQueue, ^{ + delegate.completionHandler(filePath, nil); + }); }); cam.capturePhotoOutput = mockOutput; // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult]; + [cam captureToFile:mockResult]; }); [self waitForExpectationsWithTimeout:1 handler:nil]; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index b866a73e727..f7662f93971 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -267,9 +267,9 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { if (_outputFormat == OutputFormatHEIF) { if (@available(iOS 11.0, *)) { if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { - settings = [AVCapturePhotoSettings - photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - extension = @"heif"; + settings = [AVCapturePhotoSettings + photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + extension = @"heif"; } } } From 97408dfd13610623ecc9d80a74925af2c13bd75c Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 17:32:39 -0300 Subject: [PATCH 38/71] fix format --- .../example/ios/RunnerTests/FLTCamPhotoCaptureTests.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index f6e5e080700..11e8ebfba72 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -105,6 +105,7 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); [cam setOutputFormat:OutputFormatHEIF]; + // Set photo settings to HEVC AVCapturePhotoSettings *settings = @@ -114,16 +115,15 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); NSString *filePath = @"test"; - id mockResult = OCMClassMock([ FLTThreadSafeFlutterResult class]); + id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { [expectation fulfill]; }); id mockOutput = OCMClassMock([AVCapturePhotoOutput class]); // Set availablePhotoCodecTypes to HEVC - NSArray *codecTypes = @[AVVideoCodecTypeHEVC]; + NSArray *codecTypes = @[ AVVideoCodecTypeHEVC ]; OCMStub([mockOutput availablePhotoCodecTypes]).andReturn(codecTypes); - OCMStub([mockOutput capturePhotoWithSettings:OCMOCK_ANY delegate:OCMOCK_ANY]) .andDo(^(NSInvocation *invocation) { From a5b8f1b72663547c9b94b5da6858d6a89dfdba5f Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 21:33:15 -0300 Subject: [PATCH 39/71] code improve --- .../example/integration_test/camera_test.dart | 4 +- packages/camera/camera/lib/camera.dart | 2 +- .../camera/lib/src/camera_controller.dart | 12 +-- .../camera/test/camera_preview_test.dart | 4 +- packages/camera/camera/test/camera_test.dart | 16 ++-- .../example/integration_test/camera_test.dart | 8 +- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 83 +++++++++---------- .../example/lib/camera_controller.dart | 4 +- .../ios/Classes/CameraPlugin.m | 6 +- .../ios/Classes/CameraProperties.h | 12 +-- .../ios/Classes/CameraProperties.m | 13 ++- .../camera_avfoundation/ios/Classes/FLTCam.h | 4 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 18 ++-- .../lib/src/avfoundation_camera.dart | 6 +- .../method_channel/method_channel_camera.dart | 6 +- .../platform_interface/camera_platform.dart | 4 +- .../lib/src/types/output_format.dart | 14 ++-- .../test/types/output_format_test.dart | 6 +- 18 files changed, 108 insertions(+), 114 deletions(-) diff --git a/packages/camera/camera/example/integration_test/camera_test.dart b/packages/camera/camera/example/integration_test/camera_test.dart index 86654abf85d..320714553a9 100644 --- a/packages/camera/camera/example/integration_test/camera_test.dart +++ b/packages/camera/camera/example/integration_test/camera_test.dart @@ -331,7 +331,7 @@ void main() { ); testWidgets( - 'Capture image with outputFormat', + 'Capture image with fileFormat', (WidgetTester tester) async { final List cameras = await availableCameras(); if (cameras.isEmpty) { @@ -341,7 +341,7 @@ void main() { final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); - await controller.setOutputFormat(OutputFormat.heif); + await controller.setFileFormat(FileFormat.heif); await controller.initialize(); final XFile file = await controller.takePicture(); diff --git a/packages/camera/camera/lib/camera.dart b/packages/camera/camera/lib/camera.dart index c6d7dd0ac1a..4e19cf1d8d9 100644 --- a/packages/camera/camera/lib/camera.dart +++ b/packages/camera/camera/lib/camera.dart @@ -13,7 +13,7 @@ export 'package:camera_platform_interface/camera_platform_interface.dart' ResolutionPreset, XFile, ImageFormatGroup, - OutputFormat; + FileFormat; export 'src/camera_controller.dart'; export 'src/camera_image.dart'; diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index f7eb386a5b8..c3076e9f36f 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -237,7 +237,7 @@ class CameraController extends ValueNotifier { this.resolutionPreset, { this.enableAudio = true, this.imageFormatGroup, - this.outputFormat, + this.fileFormat, }) : super(CameraValue.uninitialized(description)); /// The properties of the camera device controlled by this controller. @@ -259,12 +259,12 @@ class CameraController extends ValueNotifier { /// When null the imageFormat will fallback to the platforms default. final ImageFormatGroup? imageFormatGroup; - /// The [OutputFormat] describes the compression of the image. + /// The [FileFormat] describes the compression of the image. /// - /// When null the outputFormat will fallback to the platforms default. + /// When null the fileFormat will fallback to the platforms default. /// /// Only supported on iOS for now. - final OutputFormat? outputFormat; + final FileFormat? fileFormat; /// The id of a camera that hasn't been initialized. @visibleForTesting @@ -855,9 +855,9 @@ class CameraController extends ValueNotifier { /// Sets the output format for the camera. /// /// If [format] is omitted, the default output format is used. - Future setOutputFormat(OutputFormat format) async { + Future setFileFormat(FileFormat format) async { try { - await CameraPlatform.instance.setOutputFormat(_cameraId, format); + await CameraPlatform.instance.setFileFormat(_cameraId, format); } on PlatformException catch (e) { throw CameraException(e.code, e.message); } diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index 5e822f4e794..3b4ecb9fb0a 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -124,10 +124,10 @@ class FakeController extends ValueNotifier CameraDescription get description => value.description; @override - OutputFormat? get outputFormat => null; + FileFormat? get fileFormat => null; @override - Future setOutputFormat(OutputFormat format) async {} + Future setFileFormat(FileFormat format) async {} } void main() { diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index e512f6a25bd..a8ba761717a 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -1402,7 +1402,7 @@ void main() { ))); }); - test('setOutputFormat() calls $CameraPlatform', () async { + test('setFileFormat() calls $CameraPlatform', () async { final CameraController cameraController = CameraController( const CameraDescription( name: 'cam', @@ -1411,14 +1411,14 @@ void main() { ResolutionPreset.max); await cameraController.initialize(); - await cameraController.setOutputFormat(OutputFormat.jpeg); + await cameraController.setFileFormat(FileFormat.jpeg); verify(CameraPlatform.instance - .setOutputFormat(cameraController.cameraId, OutputFormat.jpeg)) + .setFileFormat(cameraController.cameraId, FileFormat.jpeg)) .called(1); }); - test('setOutputFormat() throws $CameraException on $PlatformException', + test('setFileFormat() throws $CameraException on $PlatformException', () async { final CameraController cameraController = CameraController( const CameraDescription( @@ -1429,7 +1429,7 @@ void main() { await cameraController.initialize(); when(CameraPlatform.instance - .setOutputFormat(cameraController.cameraId, OutputFormat.jpeg)) + .setFileFormat(cameraController.cameraId, FileFormat.jpeg)) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -1438,7 +1438,7 @@ void main() { ); expect( - cameraController.setOutputFormat(OutputFormat.jpeg), + cameraController.setFileFormat(FileFormat.jpeg), throwsA(isA().having( (CameraException error) => error.description, 'TEST_ERROR', @@ -1600,9 +1600,9 @@ class MockCameraPlatform extends Mock ) as Future; @override - Future setOutputFormat(int cameraId, OutputFormat format) async => + Future setFileFormat(int cameraId, FileFormat format) async => super.noSuchMethod( - Invocation.method(#setOutputFormat, [cameraId, format])); + Invocation.method(#setFileFormat, [cameraId, format])); } class MockCameraDescription extends CameraDescription { diff --git a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart index dbb6a51929c..25eb00a882a 100644 --- a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart +++ b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart @@ -320,7 +320,7 @@ void main() { expect(await completer.future, isNotNull); }); - // Test outputFormat is respected when taking a picture. + // Test fileFormat is respected when taking a picture. testWidgets('Capture specific image output formats', (WidgetTester tester) async { final List cameras = @@ -329,14 +329,14 @@ void main() { return; } for (final CameraDescription cameraDescription in cameras) { - for (final OutputFormat outputFormat in OutputFormat.values) { + for (final FileFormat fileFormat in FileFormat.values) { final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); await controller.initialize(); - await controller.setOutputFormat(outputFormat); + await controller.setFileFormat(fileFormat); final XFile file = await controller.takePicture(); await controller.dispose(); - expect(file.path.endsWith(outputFormat.name()), true); + expect(file.path.endsWith(fileFormat.name()), true); } } }); diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 11e8ebfba72..4f92b39f737 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -95,51 +95,48 @@ - (void)testCaptureToFile_mustReportPathToResultIfSavePhotoDelegateCompletionsWi } - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContainsHEVC { - // This test is only valid on iOS 11 or later. - if (@available(iOS 11.0, *)) { - XCTestExpectation *expectation = - [self expectationWithDescription: - @"Test must set extension to heif if availablePhotoCodecTypes contains HEVC."]; - dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); - dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, - (void *)FLTCaptureSessionQueueSpecific, NULL); - FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); - [cam setOutputFormat:OutputFormatHEIF]; + XCTestExpectation *expectation = + [self expectationWithDescription: + @"Test must set extension to heif if availablePhotoCodecTypes contains HEVC."]; + dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); + dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, + (void *)FLTCaptureSessionQueueSpecific, NULL); + FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); + [cam setFileFormat:FLTFileFormatHEIF]; - // Set photo settings to HEVC - AVCapturePhotoSettings *settings = - [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - - id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); - OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); - - NSString *filePath = @"test"; - id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); - OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { - [expectation fulfill]; - }); - - id mockOutput = OCMClassMock([AVCapturePhotoOutput class]); - // Set availablePhotoCodecTypes to HEVC - NSArray *codecTypes = @[ AVVideoCodecTypeHEVC ]; - OCMStub([mockOutput availablePhotoCodecTypes]).andReturn(codecTypes); - - OCMStub([mockOutput capturePhotoWithSettings:OCMOCK_ANY delegate:OCMOCK_ANY]) - .andDo(^(NSInvocation *invocation) { - FLTSavePhotoDelegate *delegate = cam.inProgressSavePhotoDelegates[@(settings.uniqueID)]; - // Completion runs on IO queue. - dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); - dispatch_async(ioQueue, ^{ - delegate.completionHandler(filePath, nil); - }); + // Set photo settings to HEVC + AVCapturePhotoSettings *settings = + [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + + id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); + OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); + + NSString *filePath = @"test"; + id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); + OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { + [expectation fulfill]; + }); + + id mockOutput = OCMClassMock([AVCapturePhotoOutput class]); + // Set availablePhotoCodecTypes to HEVC + NSArray *codecTypes = @[ AVVideoCodecTypeHEVC ]; + OCMStub([mockOutput availablePhotoCodecTypes]).andReturn(codecTypes); + + OCMStub([mockOutput capturePhotoWithSettings:OCMOCK_ANY delegate:OCMOCK_ANY]) + .andDo(^(NSInvocation *invocation) { + FLTSavePhotoDelegate *delegate = cam.inProgressSavePhotoDelegates[@(settings.uniqueID)]; + // Completion runs on IO queue. + dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); + dispatch_async(ioQueue, ^{ + delegate.completionHandler(filePath, nil); }); - cam.capturePhotoOutput = mockOutput; - // `FLTCam::captureToFile` runs on capture session queue. - dispatch_async(captureSessionQueue, ^{ - [cam captureToFile:mockResult]; - }); - [self waitForExpectationsWithTimeout:1 handler:nil]; - } + }); + cam.capturePhotoOutput = mockOutput; + // `FLTCam::captureToFile` runs on capture session queue. + dispatch_async(captureSessionQueue, ^{ + [cam captureToFile:mockResult]; + }); + [self waitForExpectationsWithTimeout:1 handler:nil]; } @end diff --git a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart index 7e28907c27f..19ceb17c597 100644 --- a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart +++ b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart @@ -438,8 +438,8 @@ class CameraController extends ValueNotifier { } /// Sets the output format for taking pictures. - Future setOutputFormat(OutputFormat format) async { - await CameraPlatform.instance.setOutputFormat(_cameraId, format); + Future setFileFormat(FileFormat format) async { + await CameraPlatform.instance.setFileFormat(_cameraId, format); } /// Releases the resources of this camera. diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index 3777de26492..bc44c9bdbd8 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -256,9 +256,9 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call [_camera resumePreviewWithResult:result]; } else if ([@"setDescriptionWhileRecording" isEqualToString:call.method]) { [_camera setDescriptionWhileRecording:(call.arguments[@"cameraName"]) result:result]; - } else if ([@"setOutputFormat" isEqualToString:call.method]) { - NSString *outputFormat = ((NSString *)argsMap[@"outputFormat"]); - [_camera setOutputFormat:FLTGetOutputFormatFromString(outputFormat)]; + } else if ([@"setFileFormat" isEqualToString:call.method]) { + NSString *fileFormat = call.arguments[@"fileFormat"]; + [_camera setFileFormat:FLTGetFileFormatFromString(fileFormat)]; } else { [result sendNotImplemented]; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index b8ac2834709..60070e7eab5 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -128,18 +128,18 @@ extern FLTResolutionPreset FLTGetFLTResolutionPresetForString(NSString *preset); extern OSType FLTGetVideoFormatFromString(NSString *videoFormatString); /** - * Represents image format. Mirrors OutputFormat in camera.dart. + * Represents image format. Mirrors FileFormat in camera.dart. */ -typedef NS_ENUM(NSInteger, OutputFormat) { - OutputFormatJPEG, - OutputFormatHEIF, +typedef NS_ENUM(NSInteger, FileFormat) { + FLTFileFormatJPEG, + FLTFileFormatHEIF, }; #pragma mark - image extension /** - * Gets a string representation of OutputFormat. + * Gets a string representation of FileFormat. */ -extern OutputFormat FLTGetOutputFormatFromString(NSString *outputFormatString); +extern FLTFileFormat FLTGetFileFormatFromString(NSString *fileFormatString); NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m index fb1d617f9e2..1196af95b6a 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m @@ -3,7 +3,6 @@ // found in the LICENSE file. #import "CameraProperties.h" -#import #pragma mark - flash mode @@ -152,18 +151,18 @@ OSType FLTGetVideoFormatFromString(NSString *videoFormatString) { #pragma mark - video codec -OutputFormat FLTGetOutputFormatFromString(NSString *outputFormatString) { - if ([outputFormatString isEqualToString:@"jpg"]) { - return OutputFormatJPEG; - } else if ([outputFormatString isEqualToString:@"heif"]) { - return OutputFormatHEIF; +FLTFileFormat FLTGetFileFormatFromString(NSString *fileFormatString) { + if ([fileFormatString isEqualToString:@"jpg"]) { + return FLTFileFormatJPEG; + } else if ([fileFormatString isEqualToString:@"heif"]) { + return FLTFileFormatHEIF; } else { NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:NSURLErrorUnknown userInfo:@{ NSLocalizedDescriptionKey : - [NSString stringWithFormat:@"Unknown image extension %@", outputFormatString] + [NSString stringWithFormat:@"Unknown image extension %@", fileFormatString] }]; @throw error; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 24513b7ef75..cc8f82153fa 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN @property(assign, nonatomic) FLTFlashMode flashMode; // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; -@property(assign, nonatomic) OutputFormat outputFormat; +@property(assign, nonatomic) FLTFileFormat fileFormat; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. @@ -51,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)captureToFile:(FLTThreadSafeFlutterResult *)result; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; -- (void)setOutputFormat:(OutputFormat)outputFormat; +- (void)setFileFormat:(FLTFileFormat)fileFormat; /** * Starts recording a video with an optional streaming messenger. * If the messenger is non-null then it will be called for each diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index f7662f93971..bc2ebce7479 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -144,7 +144,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName _deviceOrientation = orientation; _videoFormat = kCVPixelFormatType_32BGRA; _inProgressSavePhotoDelegates = [NSMutableDictionary dictionary]; - _outputFormat = OutputFormatJPEG; + _fileFormat = FLTFileFormatJPEG; // To limit memory consumption, limit the number of frames pending processing. // After some testing, 4 was determined to be the best maximum value. @@ -219,8 +219,8 @@ - (void)setVideoFormat:(OSType)videoFormat { @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)}; } -- (void)setOutputFormat:(OutputFormat)outputFormat { - _outputFormat = outputFormat; +- (void)setFileFormat:(FLTFileFormat)fileFormat { + _fileFormat = fileFormat; } - (void)setDeviceOrientation:(UIDeviceOrientation)orientation { @@ -264,13 +264,11 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setHighResolutionPhotoEnabled:YES]; } - if (_outputFormat == OutputFormatHEIF) { - if (@available(iOS 11.0, *)) { - if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { - settings = [AVCapturePhotoSettings - photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - extension = @"heif"; - } + if (_fileFormat == FLTFileFormatHEIF) { + if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { + settings = [AVCapturePhotoSettings + photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + extension = @"heif"; } } diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 3b07be79ffe..b81c43f02f9 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -523,12 +523,12 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setOutputFormat(int cameraId, OutputFormat format) { + Future setFileFormat(int cameraId, FileFormat format) { return _channel.invokeMethod( - 'setOutputFormat', + 'setFileFormat', { 'cameraId': cameraId, - 'outputFormat': format.name(), + 'fileFormat': format.name(), }, ); } diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 7f083c759d1..fcce6e961fd 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -516,12 +516,12 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setOutputFormat(int cameraId, OutputFormat format) { + Future setFileFormat(int cameraId, FileFormat format) { return _channel.invokeMethod( - 'setOutputFormat', + 'setFileFormat', { 'cameraId': cameraId, - 'outputFormat': format.name(), + 'fileFormat': format.name(), }, ); } diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 630d4063ca9..a2d3c2fc95f 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -286,7 +286,7 @@ abstract class CameraPlatform extends PlatformInterface { } /// Sets the output format for the selected camera. - Future setOutputFormat(int cameraId, OutputFormat format) { - throw UnimplementedError('setOutputFormat() is not implemented.'); + Future setFileFormat(int cameraId, FileFormat format) { + throw UnimplementedError('setFileFormat() is not implemented.'); } } diff --git a/packages/camera/camera_platform_interface/lib/src/types/output_format.dart b/packages/camera/camera_platform_interface/lib/src/types/output_format.dart index df56ec5465a..21889ebe3e2 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/output_format.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/output_format.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. /// The format in which images should be returned from the camera. -enum OutputFormat { +enum FileFormat { /// This is the default value. It will return the image in JPEG format. /// Is the widely used format for images. jpeg, @@ -14,16 +14,16 @@ enum OutputFormat { heif, } -/// Extension on [OutputFormat] to stringify the enum -extension OutputFormatName on OutputFormat { - /// returns a String value for [OutputFormat] +/// Extension on [FileFormat] to stringify the enum +extension FileFormatName on FileFormat { + /// returns a String value for [FileFormat] /// returns 'jpeg' if platform is not supported - /// or if [OutputFormat] is not supported for the platform + /// or if [FileFormat] is not supported for the platform String name() { switch (this) { - case OutputFormat.jpeg: + case FileFormat.jpeg: return 'jpeg'; - case OutputFormat.heif: + case FileFormat.heif: return 'heif'; } } diff --git a/packages/camera/camera_platform_interface/test/types/output_format_test.dart b/packages/camera/camera_platform_interface/test/types/output_format_test.dart index 29829789e8c..d2b681b2d78 100644 --- a/packages/camera/camera_platform_interface/test/types/output_format_test.dart +++ b/packages/camera/camera_platform_interface/test/types/output_format_test.dart @@ -6,10 +6,10 @@ import 'package:camera_platform_interface/src/types/types.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - group('$OutputFormat tests', () { + group('$FileFormat tests', () { test('ImageFormat extension returns correct values', () { - expect(OutputFormat.jpeg.name(), 'jpeg'); - expect(OutputFormat.heif.name(), 'heif'); + expect(FileFormat.jpeg.name(), 'jpeg'); + expect(FileFormat.heif.name(), 'heif'); }); }); } From 1a39b9a8922021177e92fce2a135a0e76e6deb29 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 18 Oct 2023 21:45:57 -0300 Subject: [PATCH 40/71] fix --- .../camera/camera_avfoundation/ios/Classes/CameraProperties.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index 60070e7eab5..00153e854a2 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -130,7 +130,7 @@ extern OSType FLTGetVideoFormatFromString(NSString *videoFormatString); /** * Represents image format. Mirrors FileFormat in camera.dart. */ -typedef NS_ENUM(NSInteger, FileFormat) { +typedef NS_ENUM(NSInteger, FLTFileFormat) { FLTFileFormatJPEG, FLTFileFormatHEIF, }; From 2b94bdb7bc26f0020149298ac68b8119312e4f9b Mon Sep 17 00:00:00 2001 From: Mairramer Date: Thu, 19 Oct 2023 10:48:32 -0300 Subject: [PATCH 41/71] improve code --- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 42 ++++++++++++++++++- .../ios/Classes/CameraProperties.h | 8 ++-- .../ios/Classes/CameraProperties.m | 6 +-- .../camera_avfoundation/ios/Classes/FLTCam.h | 4 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 6 +-- 5 files changed, 52 insertions(+), 14 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 4f92b39f737..66624c4d69f 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -102,8 +102,7 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); - [cam setFileFormat:FLTFileFormatHEIF]; - + [cam setFileFormat:FCPFileFormatHEIF]; // Set photo settings to HEVC AVCapturePhotoSettings *settings = @@ -139,4 +138,43 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai }); [self waitForExpectationsWithTimeout:1 handler:nil]; } + +- (void)testCaptureToFile_mustSetExtensionToJpegIfAvailablePhotoCodecTypesDoesNotContainHEVC { + XCTestExpectation *expectation = + [self expectationWithDescription: + @"Test must set extension to jpeg if availablePhotoCodecTypes does not contain HEVC."]; + dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); + dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, + (void *)FLTCaptureSessionQueueSpecific, NULL); + FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); + [cam setFileFormat:FCPFileFormatHEIF]; + + AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; + id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); + OCMStub([mockSettings photoSettings]).andReturn(settings); + + NSString *filePath = @"test"; + id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); + OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { + [expectation fulfill]; + }); + + id mockOutput = OCMClassMock([AVCapturePhotoOutput class]); + + OCMStub([mockOutput capturePhotoWithSettings:OCMOCK_ANY delegate:OCMOCK_ANY]) + .andDo(^(NSInvocation *invocation) { + FLTSavePhotoDelegate *delegate = cam.inProgressSavePhotoDelegates[@(settings.uniqueID)]; + // Completion runs on IO queue. + dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); + dispatch_async(ioQueue, ^{ + delegate.completionHandler(filePath, nil); + }); + }); + cam.capturePhotoOutput = mockOutput; + // `FLTCam::captureToFile` runs on capture session queue. + dispatch_async(captureSessionQueue, ^{ + [cam captureToFile:mockResult]; + [self waitForExpectationsWithTimeout:1 handler:nil]; + }); +} @end diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index 00153e854a2..c5141846b39 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -130,9 +130,9 @@ extern OSType FLTGetVideoFormatFromString(NSString *videoFormatString); /** * Represents image format. Mirrors FileFormat in camera.dart. */ -typedef NS_ENUM(NSInteger, FLTFileFormat) { - FLTFileFormatJPEG, - FLTFileFormatHEIF, +typedef NS_ENUM(NSInteger, FCPFileFormat) { + FCPFileFormatJPEG, + FCPFileFormatHEIF, }; #pragma mark - image extension @@ -140,6 +140,6 @@ typedef NS_ENUM(NSInteger, FLTFileFormat) { /** * Gets a string representation of FileFormat. */ -extern FLTFileFormat FLTGetFileFormatFromString(NSString *fileFormatString); +extern FCPFileFormat FLTGetFileFormatFromString(NSString *fileFormatString); NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m index 1196af95b6a..00f5eceb617 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m @@ -151,11 +151,11 @@ OSType FLTGetVideoFormatFromString(NSString *videoFormatString) { #pragma mark - video codec -FLTFileFormat FLTGetFileFormatFromString(NSString *fileFormatString) { +FCPFileFormat FLTGetFileFormatFromString(NSString *fileFormatString) { if ([fileFormatString isEqualToString:@"jpg"]) { - return FLTFileFormatJPEG; + return FCPFileFormatJPEG; } else if ([fileFormatString isEqualToString:@"heif"]) { - return FLTFileFormatHEIF; + return FCPFileFormatHEIF; } else { NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index cc8f82153fa..15069e747e4 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN @property(assign, nonatomic) FLTFlashMode flashMode; // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; -@property(assign, nonatomic) FLTFileFormat fileFormat; +@property(assign, nonatomic) FCPFileFormat fileFormat; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. @@ -51,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)captureToFile:(FLTThreadSafeFlutterResult *)result; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; -- (void)setFileFormat:(FLTFileFormat)fileFormat; +- (void)setFileFormat:(FCPFileFormat)fileFormat; /** * Starts recording a video with an optional streaming messenger. * If the messenger is non-null then it will be called for each diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index bc2ebce7479..189911f7376 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -144,7 +144,7 @@ - (instancetype)initWithCameraName:(NSString *)cameraName _deviceOrientation = orientation; _videoFormat = kCVPixelFormatType_32BGRA; _inProgressSavePhotoDelegates = [NSMutableDictionary dictionary]; - _fileFormat = FLTFileFormatJPEG; + _fileFormat = FCPFileFormatJPEG; // To limit memory consumption, limit the number of frames pending processing. // After some testing, 4 was determined to be the best maximum value. @@ -219,7 +219,7 @@ - (void)setVideoFormat:(OSType)videoFormat { @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)}; } -- (void)setFileFormat:(FLTFileFormat)fileFormat { +- (void)setFileFormat:(FCPFileFormat)fileFormat { _fileFormat = fileFormat; } @@ -264,7 +264,7 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setHighResolutionPhotoEnabled:YES]; } - if (_fileFormat == FLTFileFormatHEIF) { + if (_fileFormat == FCPFileFormatHEIF) { if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; From fb88b9413f156f6cff8e9e980390cf7431b15463 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Thu, 19 Oct 2023 18:11:44 -0300 Subject: [PATCH 42/71] fix test --- .../example/ios/RunnerTests/FLTCamPhotoCaptureTests.m | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 66624c4d69f..939dbce3ab4 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -103,6 +103,7 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); [cam setFileFormat:FCPFileFormatHEIF]; + // Set photo settings to HEVC AVCapturePhotoSettings *settings = @@ -140,9 +141,9 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai } - (void)testCaptureToFile_mustSetExtensionToJpegIfAvailablePhotoCodecTypesDoesNotContainHEVC { - XCTestExpectation *expectation = - [self expectationWithDescription: - @"Test must set extension to jpeg if availablePhotoCodecTypes does not contain HEVC."]; + XCTestExpectation *expectation = [self + expectationWithDescription: + @"Test must set extension to jpeg if availablePhotoCodecTypes does not contain HEVC."]; dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); @@ -174,7 +175,7 @@ - (void)testCaptureToFile_mustSetExtensionToJpegIfAvailablePhotoCodecTypesDoesNo // `FLTCam::captureToFile` runs on capture session queue. dispatch_async(captureSessionQueue, ^{ [cam captureToFile:mockResult]; - [self waitForExpectationsWithTimeout:1 handler:nil]; }); + [self waitForExpectationsWithTimeout:1 handler:nil]; } @end From 59f1a1001e44efad5f6ffa5f9f0f43ac220cb5a0 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 20 Oct 2023 08:58:12 -0300 Subject: [PATCH 43/71] format code --- .../example/ios/RunnerTests/FLTCamPhotoCaptureTests.m | 4 +--- packages/camera/camera_avfoundation/ios/Classes/FLTCam.m | 2 ++ 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 939dbce3ab4..7aedf2c3498 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -104,8 +104,6 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); [cam setFileFormat:FCPFileFormatHEIF]; - - // Set photo settings to HEVC AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; @@ -143,7 +141,7 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai - (void)testCaptureToFile_mustSetExtensionToJpegIfAvailablePhotoCodecTypesDoesNotContainHEVC { XCTestExpectation *expectation = [self expectationWithDescription: - @"Test must set extension to jpeg if availablePhotoCodecTypes does not contain HEVC."]; + @"Test must set extension to jpeg if availablePhotoCodecTypes does not contain HEVC."]; dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 189911f7376..15e19d40f68 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -265,6 +265,8 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { } if (_fileFormat == FCPFileFormatHEIF) { + // This will check if HEVC is available and set the format to HEIF. + // If HEVC codec is not available, it will fall back to JPEG. if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; From 7d9f5f544e30a5fd80c3e2d63e15ba0ebf65c957 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 20 Oct 2023 09:02:35 -0300 Subject: [PATCH 44/71] fix mistake --- packages/camera/camera_android/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml index ffbc3fa67e5..6c35ee8baed 100644 --- a/packages/camera/camera_android/pubspec.yaml +++ b/packages/camera/camera_android/pubspec.yaml @@ -19,7 +19,7 @@ flutter: dartPluginClass: AndroidCamera dependencies: - camera_platform_interface: ^2.5.1 + camera_platform_interface: ^2.5.2 flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.2 From 4bc9eb84bd8f9f47a913382ad2ac8a442b23c786 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 20 Oct 2023 09:05:12 -0300 Subject: [PATCH 45/71] fix update android --- packages/camera/camera_android/pubspec.yaml | 2 +- packages/camera/camera_android/test/android_camera_test.dart | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/camera/camera_android/pubspec.yaml b/packages/camera/camera_android/pubspec.yaml index 6c35ee8baed..86f3665dc08 100644 --- a/packages/camera/camera_android/pubspec.yaml +++ b/packages/camera/camera_android/pubspec.yaml @@ -19,7 +19,7 @@ flutter: dartPluginClass: AndroidCamera dependencies: - camera_platform_interface: ^2.5.2 + camera_platform_interface: ^2.5.0 flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.2 diff --git a/packages/camera/camera_android/test/android_camera_test.dart b/packages/camera/camera_android/test/android_camera_test.dart index 175ccd485b5..fb6f6a71639 100644 --- a/packages/camera/camera_android/test/android_camera_test.dart +++ b/packages/camera/camera_android/test/android_camera_test.dart @@ -551,8 +551,9 @@ void main() { // Assert expect(channel.log, [ - isMethodCall('takePicture', - arguments: {'cameraId': cameraId}), + isMethodCall('takePicture', arguments: { + 'cameraId': cameraId, + }), ]); expect(file.path, '/test/path.jpg'); }); From 998d2b6cfc9d597c55487748631d5d73e3ff2951 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 20 Oct 2023 09:07:27 -0300 Subject: [PATCH 46/71] rename file --- .../lib/src/types/{output_format.dart => file_format.dart} | 0 .../test/types/{output_format_test.dart => file_format_test.dart} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename packages/camera/camera_platform_interface/lib/src/types/{output_format.dart => file_format.dart} (100%) rename packages/camera/camera_platform_interface/test/types/{output_format_test.dart => file_format_test.dart} (100%) diff --git a/packages/camera/camera_platform_interface/lib/src/types/output_format.dart b/packages/camera/camera_platform_interface/lib/src/types/file_format.dart similarity index 100% rename from packages/camera/camera_platform_interface/lib/src/types/output_format.dart rename to packages/camera/camera_platform_interface/lib/src/types/file_format.dart diff --git a/packages/camera/camera_platform_interface/test/types/output_format_test.dart b/packages/camera/camera_platform_interface/test/types/file_format_test.dart similarity index 100% rename from packages/camera/camera_platform_interface/test/types/output_format_test.dart rename to packages/camera/camera_platform_interface/test/types/file_format_test.dart From 441eb68f69f38160966ff19dfeedabfb8427e166 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 20 Oct 2023 09:21:34 -0300 Subject: [PATCH 47/71] fix export --- packages/camera/camera_avfoundation/pubspec.yaml | 2 +- .../camera/camera_platform_interface/lib/src/types/types.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index 69b74510172..d37c2693bd2 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_avfoundation description: iOS implementation of the camera plugin. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.14 +version: 0.9.13+6 environment: sdk: ">=2.19.0 <4.0.0" diff --git a/packages/camera/camera_platform_interface/lib/src/types/types.dart b/packages/camera/camera_platform_interface/lib/src/types/types.dart index 73001dafc5d..db833b697c6 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/types.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/types.dart @@ -6,9 +6,9 @@ export 'camera_description.dart'; export 'camera_exception.dart'; export 'camera_image_data.dart'; export 'exposure_mode.dart'; +export 'file_format.dart'; export 'flash_mode.dart'; export 'focus_mode.dart'; export 'image_format_group.dart'; -export 'output_format.dart'; export 'resolution_preset.dart'; export 'video_capture_options.dart'; From c5ac5b630c591c7ae75687e83c32269113388ce5 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 20 Oct 2023 09:28:30 -0300 Subject: [PATCH 48/71] update version --- packages/camera/camera_avfoundation/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index d37c2693bd2..69b74510172 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -2,7 +2,7 @@ name: camera_avfoundation description: iOS implementation of the camera plugin. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.9.13+6 +version: 0.9.14 environment: sdk: ">=2.19.0 <4.0.0" From 6ad2422a5ce989bc8f1f1081814022b814b7e4b5 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 20 Oct 2023 16:27:47 -0300 Subject: [PATCH 49/71] refactor logic --- .../camera_avfoundation/ios/Classes/FLTCam.m | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 15e19d40f68..8f5c3b02435 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -259,19 +259,20 @@ - (void)updateOrientation:(UIDeviceOrientation)orientation - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; - NSString *extension = @"jpg"; + NSString *extension; if (_resolutionPreset == FLTResolutionPresetMax) { [settings setHighResolutionPhotoEnabled:YES]; } - if (_fileFormat == FCPFileFormatHEIF) { - // This will check if HEVC is available and set the format to HEIF. - // If HEVC codec is not available, it will fall back to JPEG. - if ([self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]) { - settings = [AVCapturePhotoSettings - photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - extension = @"heif"; - } + bool isHEVCCodecAvailable = [self.capturePhotoOutput.availablePhotoCodecTypes + containsObject:AVVideoCodecTypeHEVC]; + + if (_fileFormat == FCPFileFormatHEIF && isHEVCCodecAvailable) { + settings = [AVCapturePhotoSettings + photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + extension = @"heif"; + } else { + extension = @"jpg"; } AVCaptureFlashMode avFlashMode = FLTGetAVCaptureFlashModeForFLTFlashMode(_flashMode); From 4846d4a3fe9c45a0fd7f1682b5690afe64e18346 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 22 Oct 2023 13:06:32 -0300 Subject: [PATCH 50/71] improve code --- .../camera/camera_avfoundation/ios/Classes/CameraPlugin.m | 2 +- .../camera_avfoundation/ios/Classes/CameraProperties.h | 2 +- .../camera_avfoundation/ios/Classes/CameraProperties.m | 2 +- packages/camera/camera_avfoundation/ios/Classes/FLTCam.m | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index bc44c9bdbd8..b10054f244f 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -258,7 +258,7 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call [_camera setDescriptionWhileRecording:(call.arguments[@"cameraName"]) result:result]; } else if ([@"setFileFormat" isEqualToString:call.method]) { NSString *fileFormat = call.arguments[@"fileFormat"]; - [_camera setFileFormat:FLTGetFileFormatFromString(fileFormat)]; + [_camera setFileFormat:FCPGetFileFormatFromString(fileFormat)]; } else { [result sendNotImplemented]; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index c5141846b39..10494ba20ac 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -140,6 +140,6 @@ typedef NS_ENUM(NSInteger, FCPFileFormat) { /** * Gets a string representation of FileFormat. */ -extern FCPFileFormat FLTGetFileFormatFromString(NSString *fileFormatString); +extern FCPFileFormat FCPGetFileFormatFromString(NSString *fileFormatString); NS_ASSUME_NONNULL_END diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m index 00f5eceb617..0016b21f56c 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m @@ -151,7 +151,7 @@ OSType FLTGetVideoFormatFromString(NSString *videoFormatString) { #pragma mark - video codec -FCPFileFormat FLTGetFileFormatFromString(NSString *fileFormatString) { +FCPFileFormat FCPGetFileFormatFromString(NSString *fileFormatString) { if ([fileFormatString isEqualToString:@"jpg"]) { return FCPFileFormatJPEG; } else if ([fileFormatString isEqualToString:@"heif"]) { diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 8f5c3b02435..862cb0dc7bf 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -264,12 +264,12 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setHighResolutionPhotoEnabled:YES]; } - bool isHEVCCodecAvailable = [self.capturePhotoOutput.availablePhotoCodecTypes - containsObject:AVVideoCodecTypeHEVC]; + bool isHEVCCodecAvailable = + [self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]; if (_fileFormat == FCPFileFormatHEIF && isHEVCCodecAvailable) { - settings = [AVCapturePhotoSettings - photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; + settings = + [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; extension = @"heif"; } else { extension = @"jpg"; From b0106091d93a11d3454f1dd6750f40af539dbdff Mon Sep 17 00:00:00 2001 From: Mairramer Date: Sun, 22 Oct 2023 16:33:51 -0300 Subject: [PATCH 51/71] format code --- packages/camera/camera_avfoundation/ios/Classes/FLTCam.m | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 862cb0dc7bf..e4b789a9d7b 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -266,6 +266,7 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { bool isHEVCCodecAvailable = [self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]; + if (_fileFormat == FCPFileFormatHEIF && isHEVCCodecAvailable) { settings = From 369aa1be8d1ade2fbf4569a7018bdf6cfb03632f Mon Sep 17 00:00:00 2001 From: Mairramer Date: Mon, 23 Oct 2023 08:34:40 -0300 Subject: [PATCH 52/71] clang format --- packages/camera/camera_avfoundation/ios/Classes/FLTCam.m | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index e4b789a9d7b..b9527814e73 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -267,7 +267,6 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { bool isHEVCCodecAvailable = [self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]; - if (_fileFormat == FCPFileFormatHEIF && isHEVCCodecAvailable) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; From f07bc24f1ce2db61e56dc91e8be702ff5d2069e9 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Mon, 23 Oct 2023 08:36:40 -0300 Subject: [PATCH 53/71] next to camera --- packages/camera/camera/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index a8ac70a6629..58d6c87d002 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.10.6 +## NEXT * Add support to HEIF format to iOS From eb49544adcce3e6b05590e061fb25937885e6377 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Tue, 31 Oct 2023 17:48:23 -0300 Subject: [PATCH 54/71] some changes --- packages/camera/camera/CHANGELOG.md | 2 +- packages/camera/camera/lib/src/camera_controller.dart | 2 +- packages/camera/camera_avfoundation/CHANGELOG.md | 4 ++-- .../example/ios/RunnerTests/CameraPropertiesTests.m | 8 ++++++++ .../example/ios/RunnerTests/FLTCamPhotoCaptureTests.m | 8 +++++--- .../ios/Classes/CameraProperties.h | 1 + .../ios/Classes/CameraProperties.m | 11 ++--------- .../camera/camera_avfoundation/ios/Classes/FLTCam.m | 6 ++++-- 8 files changed, 24 insertions(+), 18 deletions(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index 58d6c87d002..df92134499e 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Add support to HEIF format to iOS +* Adds support to HEIF format to iOS ## 0.10.5+5 diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index c3076e9f36f..9a06127b0b4 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -261,7 +261,7 @@ class CameraController extends ValueNotifier { /// The [FileFormat] describes the compression of the image. /// - /// When null the fileFormat will fallback to the platforms default. + /// When null the fileFormat will fallback [FileFormat.jpeg] /// /// Only supported on iOS for now. final FileFormat? fileFormat; diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index a8f8e444736..f5c32a99a52 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,6 +1,6 @@ -## NEXT +## 0.9.14 -* Add support to HEIF format +* Adds support to HEIF format ## 0.9.13+6 diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.m index 95203bfa9e9..e77a6082016 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraPropertiesTests.m @@ -104,4 +104,12 @@ - (void)testFLTGetStringForUIDeviceOrientation { XCTAssertEqualObjects(@"portraitUp", FLTGetStringForUIDeviceOrientation(-1)); } +#pragma mark - file format tests + +- (void)testFLTGetFileFormatForString { + XCTAssertEqual(FCPFileFormatJPEG, FCPGetFileFormatFromString(@"jpg")); + XCTAssertEqual(FCPFileFormatHEIF, FCPGetFileFormatFromString(@"heif")); + XCTAssertEqual(FCPFileFormatInvalid, FCPGetFileFormatFromString(@"unknown")); +} + @end diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 7aedf2c3498..19f48369296 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -110,9 +110,10 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); - NSString *filePath = @"test"; + NSString *filePath = @"test.heif"; id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { + XCTAssertEqualObjects([filePath pathExtension], @"heif"); [expectation fulfill]; }); @@ -141,7 +142,7 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai - (void)testCaptureToFile_mustSetExtensionToJpegIfAvailablePhotoCodecTypesDoesNotContainHEVC { XCTestExpectation *expectation = [self expectationWithDescription: - @"Test must set extension to jpeg if availablePhotoCodecTypes does not contain HEVC."]; + @"Test must set extension to jpg if availablePhotoCodecTypes does not contain HEVC."]; dispatch_queue_t captureSessionQueue = dispatch_queue_create("capture_session_queue", NULL); dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); @@ -152,9 +153,10 @@ - (void)testCaptureToFile_mustSetExtensionToJpegIfAvailablePhotoCodecTypesDoesNo id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); OCMStub([mockSettings photoSettings]).andReturn(settings); - NSString *filePath = @"test"; + NSString *filePath = @"test.jpg"; id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { + XCTAssertEqualObjects([filePath pathExtension], @"jpg"); [expectation fulfill]; }); diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index 10494ba20ac..3bea6186317 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -133,6 +133,7 @@ extern OSType FLTGetVideoFormatFromString(NSString *videoFormatString); typedef NS_ENUM(NSInteger, FCPFileFormat) { FCPFileFormatJPEG, FCPFileFormatHEIF, + FCPFileFormatInvalid, }; #pragma mark - image extension diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m index 0016b21f56c..fb82bbd5c03 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.m @@ -149,7 +149,7 @@ OSType FLTGetVideoFormatFromString(NSString *videoFormatString) { } } -#pragma mark - video codec +#pragma mark - file format FCPFileFormat FCPGetFileFormatFromString(NSString *fileFormatString) { if ([fileFormatString isEqualToString:@"jpg"]) { @@ -157,13 +157,6 @@ FCPFileFormat FCPGetFileFormatFromString(NSString *fileFormatString) { } else if ([fileFormatString isEqualToString:@"heif"]) { return FCPFileFormatHEIF; } else { - NSError *error = [NSError - errorWithDomain:NSCocoaErrorDomain - code:NSURLErrorUnknown - userInfo:@{ - NSLocalizedDescriptionKey : - [NSString stringWithFormat:@"Unknown image extension %@", fileFormatString] - }]; - @throw error; + return FCPFileFormatInvalid; } } \ No newline at end of file diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index b9527814e73..a099f2be6fb 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -259,12 +259,14 @@ - (void)updateOrientation:(UIDeviceOrientation)orientation - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; - NSString *extension; + if (_resolutionPreset == FLTResolutionPresetMax) { [settings setHighResolutionPhotoEnabled:YES]; } - bool isHEVCCodecAvailable = + NSString *extension; + + BOOL isHEVCCodecAvailable = [self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]; if (_fileFormat == FCPFileFormatHEIF && isHEVCCodecAvailable) { From 23375abea0a9686ac4d93111b5a3ac4d4797700e Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 1 Nov 2023 09:53:32 -0300 Subject: [PATCH 55/71] fix false positive tests --- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 12 ++++++------ .../camera/camera_avfoundation/ios/Classes/FLTCam.h | 2 ++ .../camera/camera_avfoundation/ios/Classes/FLTCam.m | 8 +++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 19f48369296..d1a9cd552f8 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -94,7 +94,7 @@ - (void)testCaptureToFile_mustReportPathToResultIfSavePhotoDelegateCompletionsWi [self waitForExpectationsWithTimeout:1 handler:nil]; } -- (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContainsHEVC { +- (void)testCaptureToFile_mustReportFileExtensionWithHeifWhenHEVCIsAvailableAndFileFormatIsHEIF { XCTestExpectation *expectation = [self expectationWithDescription: @"Test must set extension to heif if availablePhotoCodecTypes contains HEVC."]; @@ -110,10 +110,10 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); - NSString *filePath = @"test.heif"; + NSString *filePath = @"test"; id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { - XCTAssertEqualObjects([filePath pathExtension], @"heif"); + XCTAssertEqualObjects(cam.fileExtension, @"heif"); [expectation fulfill]; }); @@ -139,7 +139,7 @@ - (void)testCaptureToFile_mustSetExtensionToHeicIfAvailablePhotoCodecTypesContai [self waitForExpectationsWithTimeout:1 handler:nil]; } -- (void)testCaptureToFile_mustSetExtensionToJpegIfAvailablePhotoCodecTypesDoesNotContainHEVC { +- (void)testCaptureToFile_mustReportFileExtensionWithJpgWhenHEVCNotAvailableAndFileFormatIsHEIF { XCTestExpectation *expectation = [self expectationWithDescription: @"Test must set extension to jpg if availablePhotoCodecTypes does not contain HEVC."]; @@ -153,10 +153,10 @@ - (void)testCaptureToFile_mustSetExtensionToJpegIfAvailablePhotoCodecTypesDoesNo id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); OCMStub([mockSettings photoSettings]).andReturn(settings); - NSString *filePath = @"test.jpg"; + NSString *filePath = @"test"; id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { - XCTAssertEqualObjects([filePath pathExtension], @"jpg"); + XCTAssertEqualObjects(cam.fileExtension, @"jpg"); [expectation fulfill]; }); diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 15069e747e4..15a10930e70 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -31,6 +31,8 @@ NS_ASSUME_NONNULL_BEGIN // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; @property(assign, nonatomic) FCPFileFormat fileFormat; +// This returns the file extension of the photo captured by the camera. +@property(readonly, nonatomic) NSString *fileExtension; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index a099f2be6fb..75110a77273 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -264,17 +264,15 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setHighResolutionPhotoEnabled:YES]; } - NSString *extension; - BOOL isHEVCCodecAvailable = [self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]; if (_fileFormat == FCPFileFormatHEIF && isHEVCCodecAvailable) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - extension = @"heif"; + _fileExtension = @"heif"; } else { - extension = @"jpg"; + _fileExtension = @"jpg"; } AVCaptureFlashMode avFlashMode = FLTGetAVCaptureFlashModeForFLTFlashMode(_flashMode); @@ -282,7 +280,7 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setFlashMode:avFlashMode]; } NSError *error; - NSString *path = [self getTemporaryFilePathWithExtension:extension + NSString *path = [self getTemporaryFilePathWithExtension:_fileExtension subfolder:@"pictures" prefix:@"CAP_" error:error]; From 0bdd96a3b9730f0fc743ad8a3a388ee588f74ff2 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 1 Nov 2023 16:23:52 -0300 Subject: [PATCH 56/71] fix --- .../example/ios/RunnerTests/FLTCamPhotoCaptureTests.m | 8 ++++---- packages/camera/camera_avfoundation/ios/Classes/FLTCam.h | 2 -- packages/camera/camera_avfoundation/ios/Classes/FLTCam.m | 8 +++++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index d1a9cd552f8..07333f8a02f 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -110,10 +110,10 @@ - (void)testCaptureToFile_mustReportFileExtensionWithHeifWhenHEVCIsAvailableAndF id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); - NSString *filePath = @"test"; + NSString *filePath = @"test.heif"; id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { - XCTAssertEqualObjects(cam.fileExtension, @"heif"); + XCTAssertEqualObjects([filePath pathExtension], @"heif"); [expectation fulfill]; }); @@ -153,10 +153,10 @@ - (void)testCaptureToFile_mustReportFileExtensionWithJpgWhenHEVCNotAvailableAndF id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); OCMStub([mockSettings photoSettings]).andReturn(settings); - NSString *filePath = @"test"; + NSString *filePath = @"test.jpg"; id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { - XCTAssertEqualObjects(cam.fileExtension, @"jpg"); + XCTAssertEqualObjects([filePath pathExtension], @"jpg"); [expectation fulfill]; }); diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 15a10930e70..15069e747e4 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -31,8 +31,6 @@ NS_ASSUME_NONNULL_BEGIN // Format used for video and image streaming. @property(assign, nonatomic) FourCharCode videoFormat; @property(assign, nonatomic) FCPFileFormat fileFormat; -// This returns the file extension of the photo captured by the camera. -@property(readonly, nonatomic) NSString *fileExtension; /// Initializes an `FLTCam` instance. /// @param cameraName a name used to uniquely identify the camera. diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index 75110a77273..a099f2be6fb 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -264,15 +264,17 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setHighResolutionPhotoEnabled:YES]; } + NSString *extension; + BOOL isHEVCCodecAvailable = [self.capturePhotoOutput.availablePhotoCodecTypes containsObject:AVVideoCodecTypeHEVC]; if (_fileFormat == FCPFileFormatHEIF && isHEVCCodecAvailable) { settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; - _fileExtension = @"heif"; + extension = @"heif"; } else { - _fileExtension = @"jpg"; + extension = @"jpg"; } AVCaptureFlashMode avFlashMode = FLTGetAVCaptureFlashModeForFLTFlashMode(_flashMode); @@ -280,7 +282,7 @@ - (void)captureToFile:(FLTThreadSafeFlutterResult *)result { [settings setFlashMode:avFlashMode]; } NSError *error; - NSString *path = [self getTemporaryFilePathWithExtension:_fileExtension + NSString *path = [self getTemporaryFilePathWithExtension:extension subfolder:@"pictures" prefix:@"CAP_" error:error]; From a7ede4304b882b2114510332daa086bd69b1b2f9 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Thu, 2 Nov 2023 10:58:28 -0300 Subject: [PATCH 57/71] fix changelog --- packages/camera/camera/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index df92134499e..2e5a8311c2a 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,4 +1,4 @@ -## NEXT +## 0.10.6 * Adds support to HEIF format to iOS From 7ae854097f388a9bc71d6c029d8eb6a9e6887dce Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 3 Nov 2023 10:47:31 -0300 Subject: [PATCH 58/71] fix tests --- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 14 ++++++++------ .../ios/Classes/FLTSavePhotoDelegate.m | 3 +++ .../ios/Classes/FLTSavePhotoDelegate_Test.h | 4 ++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 07333f8a02f..5d696a2779b 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -110,9 +110,10 @@ - (void)testCaptureToFile_mustReportFileExtensionWithHeifWhenHEVCIsAvailableAndF id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); OCMStub([mockSettings photoSettingsWithFormat:OCMOCK_ANY]).andReturn(settings); - NSString *filePath = @"test.heif"; id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); - OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { + OCMStub([mockResult sendSuccessWithData:OCMOCK_ANY]).andDo(^(NSInvocation *invocation) { + NSString *filePath; + [invocation getArgument:&filePath atIndex:2]; XCTAssertEqualObjects([filePath pathExtension], @"heif"); [expectation fulfill]; }); @@ -128,7 +129,7 @@ - (void)testCaptureToFile_mustReportFileExtensionWithHeifWhenHEVCIsAvailableAndF // Completion runs on IO queue. dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); dispatch_async(ioQueue, ^{ - delegate.completionHandler(filePath, nil); + delegate.completionHandler(delegate.filePath, nil); }); }); cam.capturePhotoOutput = mockOutput; @@ -153,9 +154,10 @@ - (void)testCaptureToFile_mustReportFileExtensionWithJpgWhenHEVCNotAvailableAndF id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); OCMStub([mockSettings photoSettings]).andReturn(settings); - NSString *filePath = @"test.jpg"; id mockResult = OCMClassMock([FLTThreadSafeFlutterResult class]); - OCMStub([mockResult sendSuccessWithData:filePath]).andDo(^(NSInvocation *invocation) { + OCMStub([mockResult sendSuccessWithData:OCMOCK_ANY]).andDo(^(NSInvocation *invocation) { + NSString *filePath; + [invocation getArgument:&filePath atIndex:2]; XCTAssertEqualObjects([filePath pathExtension], @"jpg"); [expectation fulfill]; }); @@ -168,7 +170,7 @@ - (void)testCaptureToFile_mustReportFileExtensionWithJpgWhenHEVCNotAvailableAndF // Completion runs on IO queue. dispatch_queue_t ioQueue = dispatch_queue_create("io_queue", NULL); dispatch_async(ioQueue, ^{ - delegate.completionHandler(filePath, nil); + delegate.completionHandler(delegate.filePath, nil); }); }); cam.capturePhotoOutput = mockOutput; diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTSavePhotoDelegate.m b/packages/camera/camera_avfoundation/ios/Classes/FLTSavePhotoDelegate.m index 310ffdb04eb..436c9f8f3b5 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTSavePhotoDelegate.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTSavePhotoDelegate.m @@ -55,4 +55,7 @@ - (void)captureOutput:(AVCapturePhotoOutput *)output }]; } +- (NSString *)filePath { + return self.path; +} @end diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTSavePhotoDelegate_Test.h b/packages/camera/camera_avfoundation/ios/Classes/FLTSavePhotoDelegate_Test.h index 2d0d4f96be9..80e8f77a3b0 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTSavePhotoDelegate_Test.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTSavePhotoDelegate_Test.h @@ -14,6 +14,10 @@ /// Exposed for unit tests to manually trigger the completion. @property(readonly, nonatomic) FLTSavePhotoDelegateCompletionHandler completionHandler; +/// The path for captured photo file. +/// Exposed for unit tests to verify the captured photo file path. +@property(readwrite, nonatomic) NSString *filePath; + /// Handler to write captured photo data into a file. /// @param error the capture error. /// @param photoDataProvider a closure that provides photo data. From c95d0f0abd5a3a4849970721dfd56e0fcdb658ba Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 17 Nov 2023 10:58:11 -0300 Subject: [PATCH 59/71] rename --- .../example/integration_test/camera_test.dart | 2 +- packages/camera/camera/lib/camera.dart | 2 +- .../camera/lib/src/camera_controller.dart | 4 ++-- .../camera/camera/test/camera_preview_test.dart | 4 ++-- packages/camera/camera/test/camera_test.dart | 10 +++++----- .../example/integration_test/camera_test.dart | 4 ++-- .../example/lib/camera_controller.dart | 2 +- .../ios/Classes/CameraProperties.h | 4 ++-- .../lib/src/avfoundation_camera.dart | 4 ++-- .../method_channel/method_channel_camera.dart | 4 ++-- .../src/platform_interface/camera_platform.dart | 2 +- ...{file_format.dart => image_file_format.dart} | 17 +---------------- .../lib/src/types/types.dart | 2 +- ...at_test.dart => image_file_format_test.dart} | 8 ++++---- 14 files changed, 27 insertions(+), 42 deletions(-) rename packages/camera/camera_platform_interface/lib/src/types/{file_format.dart => image_file_format.dart} (55%) rename packages/camera/camera_platform_interface/test/types/{file_format_test.dart => image_file_format_test.dart} (60%) diff --git a/packages/camera/camera/example/integration_test/camera_test.dart b/packages/camera/camera/example/integration_test/camera_test.dart index 320714553a9..c39f1a1179a 100644 --- a/packages/camera/camera/example/integration_test/camera_test.dart +++ b/packages/camera/camera/example/integration_test/camera_test.dart @@ -341,7 +341,7 @@ void main() { final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); - await controller.setFileFormat(FileFormat.heif); + await controller.setFileFormat(ImageFileFormat.heif); await controller.initialize(); final XFile file = await controller.takePicture(); diff --git a/packages/camera/camera/lib/camera.dart b/packages/camera/camera/lib/camera.dart index 4e19cf1d8d9..7ac4e32ebe6 100644 --- a/packages/camera/camera/lib/camera.dart +++ b/packages/camera/camera/lib/camera.dart @@ -13,7 +13,7 @@ export 'package:camera_platform_interface/camera_platform_interface.dart' ResolutionPreset, XFile, ImageFormatGroup, - FileFormat; + ImageFileFormat; export 'src/camera_controller.dart'; export 'src/camera_image.dart'; diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index 9a06127b0b4..ef7e85beff4 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -264,7 +264,7 @@ class CameraController extends ValueNotifier { /// When null the fileFormat will fallback [FileFormat.jpeg] /// /// Only supported on iOS for now. - final FileFormat? fileFormat; + final ImageFileFormat? fileFormat; /// The id of a camera that hasn't been initialized. @visibleForTesting @@ -855,7 +855,7 @@ class CameraController extends ValueNotifier { /// Sets the output format for the camera. /// /// If [format] is omitted, the default output format is used. - Future setFileFormat(FileFormat format) async { + Future setFileFormat(ImageFileFormat format) async { try { await CameraPlatform.instance.setFileFormat(_cameraId, format); } on PlatformException catch (e) { diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index 3b4ecb9fb0a..20b19109c21 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -124,10 +124,10 @@ class FakeController extends ValueNotifier CameraDescription get description => value.description; @override - FileFormat? get fileFormat => null; + ImageFileFormat? get fileFormat => null; @override - Future setFileFormat(FileFormat format) async {} + Future setFileFormat(ImageFileFormat format) async {} } void main() { diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index a8ba761717a..3fe18aef059 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -1411,10 +1411,10 @@ void main() { ResolutionPreset.max); await cameraController.initialize(); - await cameraController.setFileFormat(FileFormat.jpeg); + await cameraController.setFileFormat(ImageFileFormat.jpeg); verify(CameraPlatform.instance - .setFileFormat(cameraController.cameraId, FileFormat.jpeg)) + .setFileFormat(cameraController.cameraId, ImageFileFormat.jpeg)) .called(1); }); @@ -1429,7 +1429,7 @@ void main() { await cameraController.initialize(); when(CameraPlatform.instance - .setFileFormat(cameraController.cameraId, FileFormat.jpeg)) + .setFileFormat(cameraController.cameraId, ImageFileFormat.jpeg)) .thenThrow( PlatformException( code: 'TEST_ERROR', @@ -1438,7 +1438,7 @@ void main() { ); expect( - cameraController.setFileFormat(FileFormat.jpeg), + cameraController.setFileFormat(ImageFileFormat.jpeg), throwsA(isA().having( (CameraException error) => error.description, 'TEST_ERROR', @@ -1600,7 +1600,7 @@ class MockCameraPlatform extends Mock ) as Future; @override - Future setFileFormat(int cameraId, FileFormat format) async => + Future setFileFormat(int cameraId, ImageFileFormat format) async => super.noSuchMethod( Invocation.method(#setFileFormat, [cameraId, format])); } diff --git a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart index 25eb00a882a..6e1d96d7837 100644 --- a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart +++ b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart @@ -329,14 +329,14 @@ void main() { return; } for (final CameraDescription cameraDescription in cameras) { - for (final FileFormat fileFormat in FileFormat.values) { + for (final ImageFileFormat fileFormat in ImageFileFormat.values) { final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); await controller.initialize(); await controller.setFileFormat(fileFormat); final XFile file = await controller.takePicture(); await controller.dispose(); - expect(file.path.endsWith(fileFormat.name()), true); + expect(file.path.endsWith(fileFormat.name), true); } } }); diff --git a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart index 19ceb17c597..3ada659a020 100644 --- a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart +++ b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart @@ -438,7 +438,7 @@ class CameraController extends ValueNotifier { } /// Sets the output format for taking pictures. - Future setFileFormat(FileFormat format) async { + Future setFileFormat(ImageFileFormat format) async { await CameraPlatform.instance.setFileFormat(_cameraId, format); } diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h index 3bea6186317..aef8fca535a 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraProperties.h @@ -128,7 +128,7 @@ extern FLTResolutionPreset FLTGetFLTResolutionPresetForString(NSString *preset); extern OSType FLTGetVideoFormatFromString(NSString *videoFormatString); /** - * Represents image format. Mirrors FileFormat in camera.dart. + * Represents image format. Mirrors ImageFileFormat in camera.dart. */ typedef NS_ENUM(NSInteger, FCPFileFormat) { FCPFileFormatJPEG, @@ -139,7 +139,7 @@ typedef NS_ENUM(NSInteger, FCPFileFormat) { #pragma mark - image extension /** - * Gets a string representation of FileFormat. + * Gets a string representation of ImageFileFormat. */ extern FCPFileFormat FCPGetFileFormatFromString(NSString *fileFormatString); diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index b81c43f02f9..2f47f417720 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -523,12 +523,12 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFileFormat(int cameraId, FileFormat format) { + Future setFileFormat(int cameraId, ImageFileFormat format) { return _channel.invokeMethod( 'setFileFormat', { 'cameraId': cameraId, - 'fileFormat': format.name(), + 'fileFormat': format.name, }, ); } diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index 14d75aa51e0..a2ca63ac594 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -530,12 +530,12 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFileFormat(int cameraId, FileFormat format) { + Future setFileFormat(int cameraId, ImageFileFormat format) { return _channel.invokeMethod( 'setFileFormat', { 'cameraId': cameraId, - 'fileFormat': format.name(), + 'fileFormat': format.name, }, ); } diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 8c24c288087..6d1a7e65824 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -300,7 +300,7 @@ abstract class CameraPlatform extends PlatformInterface { } /// Sets the output format for the selected camera. - Future setFileFormat(int cameraId, FileFormat format) { + Future setFileFormat(int cameraId, ImageFileFormat format) { throw UnimplementedError('setFileFormat() is not implemented.'); } } diff --git a/packages/camera/camera_platform_interface/lib/src/types/file_format.dart b/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart similarity index 55% rename from packages/camera/camera_platform_interface/lib/src/types/file_format.dart rename to packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart index 21889ebe3e2..ece3a8bb86f 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/file_format.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. /// The format in which images should be returned from the camera. -enum FileFormat { +enum ImageFileFormat { /// This is the default value. It will return the image in JPEG format. /// Is the widely used format for images. jpeg, @@ -13,18 +13,3 @@ enum FileFormat { /// Will works only iOS 11+. heif, } - -/// Extension on [FileFormat] to stringify the enum -extension FileFormatName on FileFormat { - /// returns a String value for [FileFormat] - /// returns 'jpeg' if platform is not supported - /// or if [FileFormat] is not supported for the platform - String name() { - switch (this) { - case FileFormat.jpeg: - return 'jpeg'; - case FileFormat.heif: - return 'heif'; - } - } -} diff --git a/packages/camera/camera_platform_interface/lib/src/types/types.dart b/packages/camera/camera_platform_interface/lib/src/types/types.dart index 38177774629..e56b9b4c49a 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/types.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/types.dart @@ -6,9 +6,9 @@ export 'camera_description.dart'; export 'camera_exception.dart'; export 'camera_image_data.dart'; export 'exposure_mode.dart'; -export 'file_format.dart'; export 'flash_mode.dart'; export 'focus_mode.dart'; +export 'image_file_format.dart'; export 'image_format_group.dart'; export 'media_settings.dart'; export 'resolution_preset.dart'; diff --git a/packages/camera/camera_platform_interface/test/types/file_format_test.dart b/packages/camera/camera_platform_interface/test/types/image_file_format_test.dart similarity index 60% rename from packages/camera/camera_platform_interface/test/types/file_format_test.dart rename to packages/camera/camera_platform_interface/test/types/image_file_format_test.dart index d2b681b2d78..dd3b676c878 100644 --- a/packages/camera/camera_platform_interface/test/types/file_format_test.dart +++ b/packages/camera/camera_platform_interface/test/types/image_file_format_test.dart @@ -6,10 +6,10 @@ import 'package:camera_platform_interface/src/types/types.dart'; import 'package:flutter_test/flutter_test.dart'; void main() { - group('$FileFormat tests', () { - test('ImageFormat extension returns correct values', () { - expect(FileFormat.jpeg.name(), 'jpeg'); - expect(FileFormat.heif.name(), 'heif'); + group('$ImageFileFormat tests', () { + test('ImageFileFormat extension returns correct values', () { + expect(ImageFileFormat.jpeg.name, 'jpeg'); + expect(ImageFileFormat.heif.name, 'heif'); }); }); } From 09e8f0a81da4c51c7ecfd3a0da74b004219b278e Mon Sep 17 00:00:00 2001 From: Mairramer Date: Tue, 28 Nov 2023 17:20:15 -0300 Subject: [PATCH 60/71] new changes --- .../example/integration_test/camera_test.dart | 2 +- .../ios/RunnerTests/FLTCamPhotoCaptureTests.m | 4 +- .../example/lib/camera_controller.dart | 4 +- .../ios/Classes/CameraPlugin.m | 4 +- .../camera_avfoundation/ios/Classes/FLTCam.m | 2 +- .../ios/Classes/QueueUtils.h | 2 +- .../lib/src/avfoundation_camera.dart | 4 +- .../test/avfoundation_camera_test.dart | 40 +++++++++++++++++++ .../method_channel/method_channel_camera.dart | 4 +- .../platform_interface/camera_platform.dart | 2 +- 10 files changed, 54 insertions(+), 14 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart index 6e1d96d7837..b91fcec6a18 100644 --- a/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart +++ b/packages/camera/camera_avfoundation/example/integration_test/camera_test.dart @@ -333,7 +333,7 @@ void main() { final CameraController controller = CameraController(cameraDescription, ResolutionPreset.low); await controller.initialize(); - await controller.setFileFormat(fileFormat); + await controller.setImageFileFormat(fileFormat); final XFile file = await controller.takePicture(); await controller.dispose(); expect(file.path.endsWith(fileFormat.name), true); diff --git a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m index 5d696a2779b..f7204f27711 100644 --- a/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m +++ b/packages/camera/camera_avfoundation/example/ios/RunnerTests/FLTCamPhotoCaptureTests.m @@ -102,7 +102,7 @@ - (void)testCaptureToFile_mustReportFileExtensionWithHeifWhenHEVCIsAvailableAndF dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); - [cam setFileFormat:FCPFileFormatHEIF]; + [cam setImageFileFormat:FCPFileFormatHEIF]; AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey : AVVideoCodecTypeHEVC}]; @@ -148,7 +148,7 @@ - (void)testCaptureToFile_mustReportFileExtensionWithJpgWhenHEVCNotAvailableAndF dispatch_queue_set_specific(captureSessionQueue, FLTCaptureSessionQueueSpecific, (void *)FLTCaptureSessionQueueSpecific, NULL); FLTCam *cam = FLTCreateCamWithCaptureSessionQueue(captureSessionQueue); - [cam setFileFormat:FCPFileFormatHEIF]; + [cam setImageFileFormat:FCPFileFormatHEIF]; AVCapturePhotoSettings *settings = [AVCapturePhotoSettings photoSettings]; id mockSettings = OCMClassMock([AVCapturePhotoSettings class]); diff --git a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart index 3ada659a020..021435ba152 100644 --- a/packages/camera/camera_avfoundation/example/lib/camera_controller.dart +++ b/packages/camera/camera_avfoundation/example/lib/camera_controller.dart @@ -438,8 +438,8 @@ class CameraController extends ValueNotifier { } /// Sets the output format for taking pictures. - Future setFileFormat(ImageFileFormat format) async { - await CameraPlatform.instance.setFileFormat(_cameraId, format); + Future setImageFileFormat(ImageFileFormat format) async { + await CameraPlatform.instance.setImageFileFormat(_cameraId, format); } /// Releases the resources of this camera. diff --git a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m index b10054f244f..b30557a3680 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m +++ b/packages/camera/camera_avfoundation/ios/Classes/CameraPlugin.m @@ -256,9 +256,9 @@ - (void)handleMethodCallAsync:(FlutterMethodCall *)call [_camera resumePreviewWithResult:result]; } else if ([@"setDescriptionWhileRecording" isEqualToString:call.method]) { [_camera setDescriptionWhileRecording:(call.arguments[@"cameraName"]) result:result]; - } else if ([@"setFileFormat" isEqualToString:call.method]) { + } else if ([@"setImageFileFormat" isEqualToString:call.method]) { NSString *fileFormat = call.arguments[@"fileFormat"]; - [_camera setFileFormat:FCPGetFileFormatFromString(fileFormat)]; + [_camera setImageFileFormat:FCPGetFileFormatFromString(fileFormat)]; } else { [result sendNotImplemented]; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m index a099f2be6fb..cc820c18e9f 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.m @@ -219,7 +219,7 @@ - (void)setVideoFormat:(OSType)videoFormat { @{(NSString *)kCVPixelBufferPixelFormatTypeKey : @(videoFormat)}; } -- (void)setFileFormat:(FCPFileFormat)fileFormat { +- (void)setImageFileFormat:(FCPFileFormat)fileFormat { _fileFormat = fileFormat; } diff --git a/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h b/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h index a7e22da716d..e230a53508f 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h +++ b/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN /// Queue-specific context data to be associated with the capture session queue. -extern const char* FLTCaptureSessionQueueSpecific; +extern const char *FLTCaptureSessionQueueSpecific; /// Ensures the given block to be run on the main queue. /// If caller site is already on the main queue, the block will be run diff --git a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart index 2f47f417720..2f3957edbe4 100644 --- a/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart +++ b/packages/camera/camera_avfoundation/lib/src/avfoundation_camera.dart @@ -523,9 +523,9 @@ class AVFoundationCamera extends CameraPlatform { } @override - Future setFileFormat(int cameraId, ImageFileFormat format) { + Future setImageFileFormat(int cameraId, ImageFileFormat format) { return _channel.invokeMethod( - 'setFileFormat', + 'setImageFileFormat', { 'cameraId': cameraId, 'fileFormat': format.name, diff --git a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart index 17b06cddc1a..b924c103f71 100644 --- a/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart +++ b/packages/camera/camera_avfoundation/test/avfoundation_camera_test.dart @@ -1145,6 +1145,46 @@ void main() { isMethodCall('stopImageStream', arguments: null), ]); }); + + test('Should set the ImageFileFormat to heif', () async { + // Arrange + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: {'setImageFileFormat': 'heif'}, + ); + + // Act + await camera.setImageFileFormat(cameraId, ImageFileFormat.heif); + + // Assert + expect(channel.log, [ + isMethodCall('setImageFileFormat', arguments: { + 'cameraId': cameraId, + 'fileFormat': 'heif', + }), + ]); + }); + + test('Should set the ImageFileFormat to jpeg', () async { + // Arrange + final MethodChannelMock channel = MethodChannelMock( + channelName: _channelName, + methods: { + 'setImageFileFormat': 'jpeg', + }, + ); + + // Act + await camera.setImageFileFormat(cameraId, ImageFileFormat.jpeg); + + // Assert + expect(channel.log, [ + isMethodCall('setImageFileFormat', arguments: { + 'cameraId': cameraId, + 'fileFormat': 'jpeg', + }), + ]); + }); }); } diff --git a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart index a2ca63ac594..7ee0ed4e7b9 100644 --- a/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart +++ b/packages/camera/camera_platform_interface/lib/src/method_channel/method_channel_camera.dart @@ -530,9 +530,9 @@ class MethodChannelCamera extends CameraPlatform { } @override - Future setFileFormat(int cameraId, ImageFileFormat format) { + Future setImageFileFormat(int cameraId, ImageFileFormat format) { return _channel.invokeMethod( - 'setFileFormat', + 'setImageFileFormat', { 'cameraId': cameraId, 'fileFormat': format.name, diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 6d1a7e65824..4bac6ec0ce3 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -300,7 +300,7 @@ abstract class CameraPlatform extends PlatformInterface { } /// Sets the output format for the selected camera. - Future setFileFormat(int cameraId, ImageFileFormat format) { + Future setImageFileFormat(int cameraId, ImageFileFormat format) { throw UnimplementedError('setFileFormat() is not implemented.'); } } From e2712746fbe836801638da7ab7b47cd5c52fa371 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Tue, 28 Nov 2023 17:29:40 -0300 Subject: [PATCH 61/71] remove changes camera --- .../example/integration_test/camera_test.dart | 25 ---------- packages/camera/camera/example/pubspec.yaml | 5 -- .../camera/lib/src/camera_controller.dart | 19 ------- packages/camera/camera/pubspec.yaml | 8 --- .../camera/test/camera_preview_test.dart | 6 --- packages/camera/camera/test/camera_test.dart | 49 ------------------- 6 files changed, 112 deletions(-) diff --git a/packages/camera/camera/example/integration_test/camera_test.dart b/packages/camera/camera/example/integration_test/camera_test.dart index c39f1a1179a..6bef30e62c2 100644 --- a/packages/camera/camera/example/integration_test/camera_test.dart +++ b/packages/camera/camera/example/integration_test/camera_test.dart @@ -329,29 +329,4 @@ void main() { }, skip: !Platform.isIOS, ); - - testWidgets( - 'Capture image with fileFormat', - (WidgetTester tester) async { - final List cameras = await availableCameras(); - if (cameras.isEmpty) { - return; - } - for (final CameraDescription cameraDescription in cameras) { - final CameraController controller = - CameraController(cameraDescription, ResolutionPreset.low); - - await controller.setFileFormat(ImageFileFormat.heif); - await controller.initialize(); - - final XFile file = await controller.takePicture(); - final File fileImage = File(file.path); - final Image image = - await decodeImageFromList(fileImage.readAsBytesSync()); - - expect(image, isNotNull); - } - }, - skip: !Platform.isIOS, - ); } diff --git a/packages/camera/camera/example/pubspec.yaml b/packages/camera/camera/example/pubspec.yaml index bccf230f978..cf3560f2409 100644 --- a/packages/camera/camera/example/pubspec.yaml +++ b/packages/camera/camera/example/pubspec.yaml @@ -30,8 +30,3 @@ dev_dependencies: flutter: uses-material-design: true - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changing-federated-plugins -dependency_overrides: - {camera_platform_interface: {path: ../../../camera/camera_platform_interface}} diff --git a/packages/camera/camera/lib/src/camera_controller.dart b/packages/camera/camera/lib/src/camera_controller.dart index ef7e85beff4..2e8d0df8d74 100644 --- a/packages/camera/camera/lib/src/camera_controller.dart +++ b/packages/camera/camera/lib/src/camera_controller.dart @@ -237,7 +237,6 @@ class CameraController extends ValueNotifier { this.resolutionPreset, { this.enableAudio = true, this.imageFormatGroup, - this.fileFormat, }) : super(CameraValue.uninitialized(description)); /// The properties of the camera device controlled by this controller. @@ -259,13 +258,6 @@ class CameraController extends ValueNotifier { /// When null the imageFormat will fallback to the platforms default. final ImageFormatGroup? imageFormatGroup; - /// The [FileFormat] describes the compression of the image. - /// - /// When null the fileFormat will fallback [FileFormat.jpeg] - /// - /// Only supported on iOS for now. - final ImageFileFormat? fileFormat; - /// The id of a camera that hasn't been initialized. @visibleForTesting static const int kUninitializedCameraId = -1; @@ -852,17 +844,6 @@ class CameraController extends ValueNotifier { } } - /// Sets the output format for the camera. - /// - /// If [format] is omitted, the default output format is used. - Future setFileFormat(ImageFileFormat format) async { - try { - await CameraPlatform.instance.setFileFormat(_cameraId, format); - } on PlatformException catch (e) { - throw CameraException(e.code, e.message); - } - } - /// Releases the resources of this camera. @override Future dispose() async { diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 648e76df473..0620b606cc5 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -39,11 +39,3 @@ dev_dependencies: topics: - camera - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changing-federated-plugins -dependency_overrides: - { - camera_avfoundation: {path: ../../camera/camera_avfoundation}, - camera_platform_interface: {path: ../../camera/camera_platform_interface}, - } diff --git a/packages/camera/camera/test/camera_preview_test.dart b/packages/camera/camera/test/camera_preview_test.dart index 20b19109c21..c73e1816445 100644 --- a/packages/camera/camera/test/camera_preview_test.dart +++ b/packages/camera/camera/test/camera_preview_test.dart @@ -122,12 +122,6 @@ class FakeController extends ValueNotifier @override CameraDescription get description => value.description; - - @override - ImageFileFormat? get fileFormat => null; - - @override - Future setFileFormat(ImageFileFormat format) async {} } void main() { diff --git a/packages/camera/camera/test/camera_test.dart b/packages/camera/camera/test/camera_test.dart index 3fe18aef059..ec111ed8594 100644 --- a/packages/camera/camera/test/camera_test.dart +++ b/packages/camera/camera/test/camera_test.dart @@ -1401,50 +1401,6 @@ void main() { 'This is a test error message', ))); }); - - test('setFileFormat() calls $CameraPlatform', () async { - final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.front, - sensorOrientation: 90), - ResolutionPreset.max); - await cameraController.initialize(); - - await cameraController.setFileFormat(ImageFileFormat.jpeg); - - verify(CameraPlatform.instance - .setFileFormat(cameraController.cameraId, ImageFileFormat.jpeg)) - .called(1); - }); - - test('setFileFormat() throws $CameraException on $PlatformException', - () async { - final CameraController cameraController = CameraController( - const CameraDescription( - name: 'cam', - lensDirection: CameraLensDirection.front, - sensorOrientation: 90), - ResolutionPreset.max); - await cameraController.initialize(); - - when(CameraPlatform.instance - .setFileFormat(cameraController.cameraId, ImageFileFormat.jpeg)) - .thenThrow( - PlatformException( - code: 'TEST_ERROR', - message: 'This is a test error message', - ), - ); - - expect( - cameraController.setFileFormat(ImageFileFormat.jpeg), - throwsA(isA().having( - (CameraException error) => error.description, - 'TEST_ERROR', - 'This is a test error message', - ))); - }); }); } @@ -1598,11 +1554,6 @@ class MockCameraPlatform extends Mock Invocation.method(#setExposureOffset, [cameraId, offset]), returnValue: Future.value(1.0), ) as Future; - - @override - Future setFileFormat(int cameraId, ImageFileFormat format) async => - super.noSuchMethod( - Invocation.method(#setFileFormat, [cameraId, format])); } class MockCameraDescription extends CameraDescription { From 2338ac7fcc5a0bbf410ea0dfad3ada4a6b4d02fb Mon Sep 17 00:00:00 2001 From: Mairramer Date: Tue, 28 Nov 2023 17:36:04 -0300 Subject: [PATCH 62/71] fix --- packages/camera/camera_avfoundation/ios/Classes/FLTCam.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h index 15069e747e4..f5979a829ca 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h +++ b/packages/camera/camera_avfoundation/ios/Classes/FLTCam.h @@ -51,7 +51,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)captureToFile:(FLTThreadSafeFlutterResult *)result; - (void)close; - (void)startVideoRecordingWithResult:(FLTThreadSafeFlutterResult *)result; -- (void)setFileFormat:(FCPFileFormat)fileFormat; +- (void)setImageFileFormat:(FCPFileFormat)fileFormat; /** * Starts recording a video with an optional streaming messenger. * If the messenger is non-null then it will be called for each From 33b2ddeec860eea046bd4e232b752c582a16f9b1 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Tue, 28 Nov 2023 17:42:33 -0300 Subject: [PATCH 63/71] fix import --- packages/camera/camera/lib/camera.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/camera/camera/lib/camera.dart b/packages/camera/camera/lib/camera.dart index 7ac4e32ebe6..900c2633a5d 100644 --- a/packages/camera/camera/lib/camera.dart +++ b/packages/camera/camera/lib/camera.dart @@ -12,8 +12,7 @@ export 'package:camera_platform_interface/camera_platform_interface.dart' FocusMode, ResolutionPreset, XFile, - ImageFormatGroup, - ImageFileFormat; + ImageFormatGroup; export 'src/camera_controller.dart'; export 'src/camera_image.dart'; From df51b0be850aba89ed65972a6a0f7ffeda6392cf Mon Sep 17 00:00:00 2001 From: Mairramer Date: Tue, 28 Nov 2023 17:50:20 -0300 Subject: [PATCH 64/71] new changes --- packages/camera/camera/pubspec.yaml | 2 +- packages/camera/camera_avfoundation/CHANGELOG.md | 5 +---- packages/camera/camera_platform_interface/CHANGELOG.md | 5 +---- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/camera/camera/pubspec.yaml b/packages/camera/camera/pubspec.yaml index 0620b606cc5..78a7ed7afc7 100644 --- a/packages/camera/camera/pubspec.yaml +++ b/packages/camera/camera/pubspec.yaml @@ -4,7 +4,7 @@ description: A Flutter plugin for controlling the camera. Supports previewing Dart. repository: https://github.com/flutter/packages/tree/main/packages/camera/camera issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22 -version: 0.10.6 +version: 0.10.5+5 environment: sdk: ">=3.0.0 <4.0.0" diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 6a20ad57574..06c173d5c6b 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,10 +1,7 @@ -## NEXT - -* Updates minimum supported SDK version to Flutter 3.10/Dart 3. - ## 0.9.14 * Adds support to HEIF format +* Updates minimum supported SDK version to Flutter 3.10/Dart 3. ## 0.9.13+7 diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index 818f304e978..bf6c11511b6 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,10 +1,7 @@ -## NEXT - -* Updates minimum supported SDK version to Flutter 3.10/Dart 3. - ## 2.7.0 * Adds support to HEIF format for iOS. +* Updates minimum supported SDK version to Flutter 3.10/Dart 3. ## 2.6.0 From be233cba518ce3c498dea0acbfb96f659743a431 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Tue, 28 Nov 2023 17:50:53 -0300 Subject: [PATCH 65/71] fix --- packages/camera/camera_avfoundation/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 06c173d5c6b..589e162219a 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.9.14 -* Adds support to HEIF format +* Adds support to HEIF format. * Updates minimum supported SDK version to Flutter 3.10/Dart 3. ## 0.9.13+7 From f4b77ec7c488e34f6ae3121a19ea37777de4e9bf Mon Sep 17 00:00:00 2001 From: Mairramer Date: Tue, 28 Nov 2023 17:58:33 -0300 Subject: [PATCH 66/71] fix --- packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h b/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h index e230a53508f..a7e22da716d 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h +++ b/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN /// Queue-specific context data to be associated with the capture session queue. -extern const char *FLTCaptureSessionQueueSpecific; +extern const char* FLTCaptureSessionQueueSpecific; /// Ensures the given block to be run on the main queue. /// If caller site is already on the main queue, the block will be run From 5cbb66b5b6363bbc46623e8b45ebb876df1e6575 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 29 Nov 2023 16:05:44 -0300 Subject: [PATCH 67/71] new fixes --- packages/camera/camera/CHANGELOG.md | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/xcschemes/Runner.xcscheme | 2 +- packages/camera/camera/pubspec.yaml | 6 +-- .../camera/camera_avfoundation/CHANGELOG.md | 2 +- .../ios/Classes/QueueUtils.h | 2 +- .../camera_platform_interface/CHANGELOG.md | 2 +- .../platform_interface/camera_platform.dart | 17 +++----- .../lib/src/types/image_file_format.dart | 4 +- .../method_channel_camera_test.dart | 40 +++++++++++++++++++ .../test/types/image_file_format_test.dart | 15 ------- 11 files changed, 58 insertions(+), 36 deletions(-) delete mode 100644 packages/camera/camera_platform_interface/test/types/image_file_format_test.dart diff --git a/packages/camera/camera/CHANGELOG.md b/packages/camera/camera/CHANGELOG.md index bd8e8896f73..b8a108b188b 100644 --- a/packages/camera/camera/CHANGELOG.md +++ b/packages/camera/camera/CHANGELOG.md @@ -1,6 +1,6 @@ ## NEXT -* Updates minimum supported SDK version to Flutter 3.10/Dart 3. +* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0. ## 0.10.5+5 diff --git a/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj index a9ff9e273fd..59fa9076ed8 100644 --- a/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera/example/ios/Runner.xcodeproj/project.pbxproj @@ -169,7 +169,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1430; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = "The Flutter Authors"; TargetAttributes = { 97C146ED1CF9000F007C117D = { diff --git a/packages/camera/camera/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/camera/camera/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 1ff4b573d76..f4b3c109900 100644 --- a/packages/camera/camera/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/camera/camera/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,6 +1,6 @@ =3.0.0 <4.0.0" @@ -22,8 +22,8 @@ flutter: dependencies: camera_android: ^0.10.7 - camera_avfoundation: ^0.9.13+2 - camera_platform_interface: ^2.5.1 + camera_avfoundation: ^0.9.13 + camera_platform_interface: ^2.5.0 camera_web: ^0.3.1 flutter: sdk: flutter diff --git a/packages/camera/camera_avfoundation/CHANGELOG.md b/packages/camera/camera_avfoundation/CHANGELOG.md index 589e162219a..9c8aad281be 100644 --- a/packages/camera/camera_avfoundation/CHANGELOG.md +++ b/packages/camera/camera_avfoundation/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.9.14 * Adds support to HEIF format. -* Updates minimum supported SDK version to Flutter 3.10/Dart 3. +* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0. ## 0.9.13+7 diff --git a/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h b/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h index a7e22da716d..e230a53508f 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h +++ b/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN /// Queue-specific context data to be associated with the capture session queue. -extern const char* FLTCaptureSessionQueueSpecific; +extern const char *FLTCaptureSessionQueueSpecific; /// Ensures the given block to be run on the main queue. /// If caller site is already on the main queue, the block will be run diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index bf6c11511b6..e4c5c45a82f 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,7 +1,7 @@ ## 2.7.0 * Adds support to HEIF format for iOS. -* Updates minimum supported SDK version to Flutter 3.10/Dart 3. +* Updates minimum supported SDK version to Flutter 3.10/Dart 3.0. ## 2.6.0 diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 4bac6ec0ce3..2a269e79a62 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -113,13 +113,11 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError( - 'onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation( - int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -156,8 +154,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, - maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -185,8 +182,7 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, - {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -285,8 +281,7 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError( - 'setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. @@ -301,6 +296,6 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the output format for the selected camera. Future setImageFileFormat(int cameraId, ImageFileFormat format) { - throw UnimplementedError('setFileFormat() is not implemented.'); + throw UnimplementedError('setImageFileFormat() is not implemented.'); } } diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart b/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart index ece3a8bb86f..584e2c68e8b 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart @@ -4,11 +4,13 @@ /// The format in which images should be returned from the camera. enum ImageFileFormat { - /// This is the default value. It will return the image in JPEG format. + /// It will return the image in JPEG format. + /// /// Is the widely used format for images. jpeg, /// It will return the image in HEIF format. + /// /// HEIF is a file format name that refers to High Efficiency Image Format (HEIF). /// Will works only iOS 11+. heif, diff --git a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart index 8159cdfe26f..7cf878b8c38 100644 --- a/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart +++ b/packages/camera/camera_platform_interface/test/method_channel/method_channel_camera_test.dart @@ -1154,6 +1154,46 @@ void main() { isMethodCall('stopImageStream', arguments: null), ]); }); + + test('Should set the ImageFileFormat to heif', () async { + // Arrange + final MethodChannelMock channel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: {'setImageFileFormat': 'heif'}, + ); + + // Act + await camera.setImageFileFormat(cameraId, ImageFileFormat.heif); + + // Assert + expect(channel.log, [ + isMethodCall('setImageFileFormat', arguments: { + 'cameraId': cameraId, + 'fileFormat': 'heif', + }), + ]); + }); + + test('Should set the ImageFileFormat to jpeg', () async { + // Arrange + final MethodChannelMock channel = MethodChannelMock( + channelName: 'plugins.flutter.io/camera', + methods: { + 'setImageFileFormat': 'jpeg', + }, + ); + + // Act + await camera.setImageFileFormat(cameraId, ImageFileFormat.jpeg); + + // Assert + expect(channel.log, [ + isMethodCall('setImageFileFormat', arguments: { + 'cameraId': cameraId, + 'fileFormat': 'jpeg', + }), + ]); + }); }); }); } diff --git a/packages/camera/camera_platform_interface/test/types/image_file_format_test.dart b/packages/camera/camera_platform_interface/test/types/image_file_format_test.dart deleted file mode 100644 index dd3b676c878..00000000000 --- a/packages/camera/camera_platform_interface/test/types/image_file_format_test.dart +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'package:camera_platform_interface/src/types/types.dart'; -import 'package:flutter_test/flutter_test.dart'; - -void main() { - group('$ImageFileFormat tests', () { - test('ImageFileFormat extension returns correct values', () { - expect(ImageFileFormat.jpeg.name, 'jpeg'); - expect(ImageFileFormat.heif.name, 'heif'); - }); - }); -} From 4079924c736735533a5ff041b7dae1e88981b263 Mon Sep 17 00:00:00 2001 From: Mairramer Date: Wed, 29 Nov 2023 16:12:49 -0300 Subject: [PATCH 68/71] format code --- .../camera_avfoundation/ios/Classes/QueueUtils.h | 2 +- .../src/platform_interface/camera_platform.dart | 15 ++++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h b/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h index e230a53508f..a7e22da716d 100644 --- a/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h +++ b/packages/camera/camera_avfoundation/ios/Classes/QueueUtils.h @@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN /// Queue-specific context data to be associated with the capture session queue. -extern const char *FLTCaptureSessionQueueSpecific; +extern const char* FLTCaptureSessionQueueSpecific; /// Ensures the given block to be run on the main queue. /// If caller site is already on the main queue, the block will be run diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 2a269e79a62..08c9cb953b7 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -113,11 +113,13 @@ abstract class CameraPlatform extends PlatformInterface { /// Implementations for this: /// - Should support all 4 orientations. Stream onDeviceOrientationChanged() { - throw UnimplementedError('onDeviceOrientationChanged() is not implemented.'); + throw UnimplementedError( + 'onDeviceOrientationChanged() is not implemented.'); } /// Locks the capture orientation. - Future lockCaptureOrientation(int cameraId, DeviceOrientation orientation) { + Future lockCaptureOrientation( + int cameraId, DeviceOrientation orientation) { throw UnimplementedError('lockCaptureOrientation() is not implemented.'); } @@ -154,7 +156,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Please see [VideoCaptureOptions] for documentation on the /// configuration options. Future startVideoCapturing(VideoCaptureOptions options) { - return startVideoRecording(options.cameraId, maxVideoDuration: options.maxDuration); + return startVideoRecording(options.cameraId, + maxVideoDuration: options.maxDuration); } /// Stops the video recording and returns the file where it was saved. @@ -182,7 +185,8 @@ abstract class CameraPlatform extends PlatformInterface { /// // TODO(bmparr): Add options to control streaming settings (e.g., // resolution and FPS). - Stream onStreamedFrameAvailable(int cameraId, {CameraImageStreamOptions? options}) { + Stream onStreamedFrameAvailable(int cameraId, + {CameraImageStreamOptions? options}) { throw UnimplementedError('onStreamedFrameAvailable() is not implemented.'); } @@ -281,7 +285,8 @@ abstract class CameraPlatform extends PlatformInterface { /// Sets the active camera while recording. Future setDescriptionWhileRecording(CameraDescription description) { - throw UnimplementedError('setDescriptionWhileRecording() is not implemented.'); + throw UnimplementedError( + 'setDescriptionWhileRecording() is not implemented.'); } /// Returns a widget showing a live camera preview. From 9410af7bc693e11a07a9495d0c7f99ec5ad4b865 Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Tue, 5 Dec 2023 16:25:01 -0500 Subject: [PATCH 69/71] update some wording --- .../camera_platform_interface/CHANGELOG.md | 2 +- .../platform_interface/camera_platform.dart | 5 +++- .../lib/src/types/image_file_format.dart | 10 ++++---- .../test/events/camera_event_test.dart | 24 +++++++------------ 4 files changed, 17 insertions(+), 24 deletions(-) diff --git a/packages/camera/camera_platform_interface/CHANGELOG.md b/packages/camera/camera_platform_interface/CHANGELOG.md index e4c5c45a82f..f31511df65a 100644 --- a/packages/camera/camera_platform_interface/CHANGELOG.md +++ b/packages/camera/camera_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.7.0 -* Adds support to HEIF format for iOS. +* Adds support for setting the image file format. See `CameraPlatform.setImageFileFormat`. * Updates minimum supported SDK version to Flutter 3.10/Dart 3.0. ## 2.6.0 diff --git a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart index 08c9cb953b7..6707962cbc1 100644 --- a/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart +++ b/packages/camera/camera_platform_interface/lib/src/platform_interface/camera_platform.dart @@ -299,7 +299,10 @@ abstract class CameraPlatform extends PlatformInterface { throw UnimplementedError('dispose() is not implemented.'); } - /// Sets the output format for the selected camera. + /// Sets the output image file format for the selected camera. + /// + // TODO(bmparr): This is only supported on iOS. See + // https://github.com/flutter/flutter/issues/139588 Future setImageFileFormat(int cameraId, ImageFileFormat format) { throw UnimplementedError('setImageFileFormat() is not implemented.'); } diff --git a/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart b/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart index 584e2c68e8b..e745dc5e1fd 100644 --- a/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart +++ b/packages/camera/camera_platform_interface/lib/src/types/image_file_format.dart @@ -4,14 +4,12 @@ /// The format in which images should be returned from the camera. enum ImageFileFormat { - /// It will return the image in JPEG format. - /// - /// Is the widely used format for images. + /// The JPEG format. jpeg, - /// It will return the image in HEIF format. + /// The HEIF format. /// - /// HEIF is a file format name that refers to High Efficiency Image Format (HEIF). - /// Will works only iOS 11+. + /// HEIF is a file format name that refers to High Efficiency Image Format + /// (HEIF). For iOS, this is only supported on versions 11+. heif, } diff --git a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart index 990ead12a01..cb1e34845b3 100644 --- a/packages/camera/camera_platform_interface/test/events/camera_event_test.dart +++ b/packages/camera/camera_platform_interface/test/events/camera_event_test.dart @@ -45,14 +45,7 @@ void main() { test('toJson should return a map with all fields', () { const CameraInitializedEvent event = CameraInitializedEvent( - 1, - 1024, - 640, - ExposureMode.auto, - true, - FocusMode.auto, - true, - ); + 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); final Map jsonMap = event.toJson(); @@ -143,14 +136,13 @@ void main() { const CameraInitializedEvent event = CameraInitializedEvent( 1, 1024, 640, ExposureMode.auto, true, FocusMode.auto, true); final int expectedHashCode = Object.hash( - event.cameraId.hashCode, - event.previewWidth, - event.previewHeight, - event.exposureMode, - event.exposurePointSupported, - event.focusMode, - event.focusPointSupported, - ); + event.cameraId.hashCode, + event.previewWidth, + event.previewHeight, + event.exposureMode, + event.exposurePointSupported, + event.focusMode, + event.focusPointSupported); expect(event.hashCode, expectedHashCode); }); From 344d22eefc7aebf8494901260af942325261dfda Mon Sep 17 00:00:00 2001 From: Mairramer Date: Fri, 22 Dec 2023 09:00:23 -0300 Subject: [PATCH 70/71] remove federated --- packages/camera/camera_avfoundation/example/pubspec.yaml | 7 +------ packages/camera/camera_avfoundation/pubspec.yaml | 6 +----- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/pubspec.yaml b/packages/camera/camera_avfoundation/example/pubspec.yaml index b6fb7030ad6..2bbe63029d0 100644 --- a/packages/camera/camera_avfoundation/example/pubspec.yaml +++ b/packages/camera/camera_avfoundation/example/pubspec.yaml @@ -14,7 +14,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - camera_platform_interface: ^2.5.2 + camera_platform_interface: ^2.7.0 flutter: sdk: flutter path_provider: ^2.0.0 @@ -29,8 +29,3 @@ dev_dependencies: flutter: uses-material-design: true - -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changing-federated-plugins -dependency_overrides: - {camera_platform_interface: {path: ../../../camera/camera_platform_interface}} diff --git a/packages/camera/camera_avfoundation/pubspec.yaml b/packages/camera/camera_avfoundation/pubspec.yaml index ced37688d9c..0c4de731d39 100644 --- a/packages/camera/camera_avfoundation/pubspec.yaml +++ b/packages/camera/camera_avfoundation/pubspec.yaml @@ -17,7 +17,7 @@ flutter: dartPluginClass: AVFoundationCamera dependencies: - camera_platform_interface: ^2.5.2 + camera_platform_interface: ^2.7.0 flutter: sdk: flutter stream_transform: ^2.0.0 @@ -30,7 +30,3 @@ dev_dependencies: topics: - camera -# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE. -# See https://github.com/flutter/flutter/wiki/Contributing-to-Plugins-and-Packages#changing-federated-plugins -dependency_overrides: - {camera_platform_interface: {path: ../../camera/camera_platform_interface}} From 9588e3e263485e09931864a51141b46ff05cc4ae Mon Sep 17 00:00:00 2001 From: Maurice Parrish <10687576+bparrishMines@users.noreply.github.com> Date: Wed, 24 Jan 2024 15:14:22 -0500 Subject: [PATCH 71/71] Update project.pbxproj --- .../example/ios/Runner.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj index 5b886f07c20..df0879fad89 100644 --- a/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/camera/camera_avfoundation/example/ios/Runner.xcodeproj/project.pbxproj @@ -376,7 +376,7 @@ 9740EEB61CF901F6004384FC /* Run Script */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; - buildActionMask = 12; + buildActionMask = 2147483647; files = ( ); inputPaths = ( @@ -386,7 +386,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; 9872F2A25E8A171A111468CD /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase;