From 5d3a9aa7affcda6868a4504e873511e1da9c7369 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 3 Jan 2022 13:55:17 +0100 Subject: [PATCH 01/36] Added new image picking method with flag for controlling metadata --- .../method_channel_image_picker.dart | 24 ++++++++- .../image_picker_platform.dart | 52 +++++++++++++++++++ .../pubspec.yaml | 2 +- 3 files changed, 76 insertions(+), 2 deletions(-) diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart index b02284e957fa..57581ef3eef1 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart @@ -86,6 +86,7 @@ class MethodChannelImagePicker extends ImagePickerPlatform { double? maxHeight, int? imageQuality, CameraDevice preferredCameraDevice = CameraDevice.rear, + bool forceFullMetadata = true, }) { if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) { throw ArgumentError.value( @@ -107,7 +108,8 @@ class MethodChannelImagePicker extends ImagePickerPlatform { 'maxWidth': maxWidth, 'maxHeight': maxHeight, 'imageQuality': imageQuality, - 'cameraDevice': preferredCameraDevice.index + 'cameraDevice': preferredCameraDevice.index, + 'forceFullMetadata': forceFullMetadata, }, ); } @@ -271,4 +273,24 @@ class MethodChannelImagePicker extends ImagePickerPlatform { files: pickedFileList, ); } + + @override + Future getImageFromSource({ + required ImageSource source, + double? maxWidth, + double? maxHeight, + int? imageQuality, + CameraDevice preferredCameraDevice = CameraDevice.rear, + bool forceFullMetadata = true, + }) async { + String? path = await _getImagePath( + source: source, + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice, + forceFullMetadata: forceFullMetadata, + ); + return path != null ? XFile(path) : null; + } } diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart index 5c1c8b698442..212113968020 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart @@ -146,6 +146,8 @@ abstract class ImagePickerPlatform extends PlatformInterface { throw UnimplementedError('retrieveLostData() has not been implemented.'); } + /// This method is deprecated in favor of [getImageFromSource] and will be removed in a future update + /// /// Returns an [XFile] with the image that was picked. /// /// The `source` argument controls where the image comes from. This can @@ -251,4 +253,54 @@ abstract class ImagePickerPlatform extends PlatformInterface { Future getLostData() { throw UnimplementedError('getLostData() has not been implemented.'); } + + /// Returns an [XFile] with the image that was picked. + /// + /// The `source` argument controls where the image comes from. This can + /// be either [ImageSource.camera] or [ImageSource.gallery]. + /// + /// Where iOS supports HEIC images, Android 8 and below doesn't. Android 9 and above only support HEIC images if used + /// in addition to a size modification, of which the usage is explained below. + /// + /// If specified, the image will be at most `maxWidth` wide and + /// `maxHeight` tall. Otherwise the image will be returned at it's + /// original width and height. + /// + /// The `imageQuality` argument modifies the quality of the image, ranging from 0-100 + /// where 100 is the original/max quality. If `imageQuality` is null, the image with + /// the original quality will be returned. Compression is only supported for certain + /// image types such as JPEG. If compression is not supported for the image that is picked, + /// a warning message will be logged. + /// + /// Use `preferredCameraDevice` to specify the camera to use when the `source` is [ImageSource.camera]. + /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device. + /// Defaults to [CameraDevice.rear]. Note that Android has no documented parameter for an intent to specify if + /// the front or rear camera should be opened, this function is not guaranteed + /// to work on an Android device. + /// + /// `forceFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata which may require + /// extra permission requests on certain platforms. + /// If `forceFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests + /// from the platform (e.g. on iOS the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). + /// + /// In Android, the MainActivity can be destroyed for various reasons. If that happens, the result will be lost + /// in this call. You can then call [getLostData] when your app relaunches to retrieve the lost data. + /// + /// If no images were picked, the return value is null. + Future getImageFromSource({ + required ImageSource source, + double? maxWidth, + double? maxHeight, + int? imageQuality, + CameraDevice preferredCameraDevice = CameraDevice.rear, + bool forceFullMetadata = true, + }) { + return getImage( + source: source, + maxHeight: maxHeight, + maxWidth: maxWidth, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice, + ); + } } diff --git a/packages/image_picker/image_picker_platform_interface/pubspec.yaml b/packages/image_picker/image_picker_platform_interface/pubspec.yaml index e41137fcb06b..8b9b7e6a138b 100644 --- a/packages/image_picker/image_picker_platform_interface/pubspec.yaml +++ b/packages/image_picker/image_picker_platform_interface/pubspec.yaml @@ -4,7 +4,7 @@ repository: https://github.com/flutter/plugins/tree/master/packages/image_picker issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%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.4.1 +version: 2.5.0 environment: sdk: ">=2.12.0 <3.0.0" From 4195dca01900653ef59649c5f338214ebbcf7a80 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 3 Jan 2022 14:09:48 +0100 Subject: [PATCH 02/36] Updated tests with cases for the new method Updated changelog with description of latest changes --- .../CHANGELOG.md | 8 + .../new_method_channel_image_picker_test.dart | 289 ++++++++++++++++-- 2 files changed, 279 insertions(+), 18 deletions(-) diff --git a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md index d637ac1a277e..eccd517cd100 100644 --- a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md +++ b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md @@ -1,3 +1,11 @@ +## 2.5.0 + +* Re-adding `forceFullMetadata` option to `pickImage`, but as truly non-breaking change. + * `forceFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata + which may require extra permission requests on certain platforms. + * If `forceFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces + permission requests from the platform (e.g on iOS the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). + ## 2.4.1 * Reverts the changes from 2.4.0, which was a breaking change that diff --git a/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart b/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart index 17caa8456621..aa1d6e53aebe 100644 --- a/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart +++ b/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart @@ -40,14 +40,16 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -93,49 +95,56 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -196,6 +205,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -215,6 +225,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, + 'forceFullMetadata': true, }), ], ); @@ -509,14 +520,16 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -562,49 +575,56 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -664,6 +684,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -683,6 +704,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, + 'forceFullMetadata': true, }), ], ); @@ -979,5 +1001,236 @@ void main() { expect(picker.getLostData(), throwsAssertionError); }); }); + + group('#getImageFromSource', () { + test('passes the image source argument correctly', () async { + await picker.getImageFromSource(source: ImageSource.camera); + await picker.getImageFromSource(source: ImageSource.gallery); + + expect( + log, + [ + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + isMethodCall('pickImage', arguments: { + 'source': 1, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + ], + ); + }); + + test('passes the width and height arguments correctly', () async { + await picker.getImageFromSource(source: ImageSource.camera); + await picker.getImageFromSource( + source: ImageSource.camera, + maxWidth: 10.0, + ); + await picker.getImageFromSource( + source: ImageSource.camera, + maxHeight: 10.0, + ); + await picker.getImageFromSource( + source: ImageSource.camera, + maxWidth: 10.0, + maxHeight: 20.0, + ); + await picker.getImageFromSource( + source: ImageSource.camera, + maxWidth: 10.0, + imageQuality: 70, + ); + await picker.getImageFromSource( + source: ImageSource.camera, + maxHeight: 10.0, + imageQuality: 70, + ); + await picker.getImageFromSource( + source: ImageSource.camera, + maxWidth: 10.0, + maxHeight: 20.0, + imageQuality: 70, + ); + + expect( + log, + [ + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': 10.0, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': 10.0, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': 10.0, + 'maxHeight': 20.0, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': 10.0, + 'maxHeight': null, + 'imageQuality': 70, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': 10.0, + 'imageQuality': 70, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': 10.0, + 'maxHeight': 20.0, + 'imageQuality': 70, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + ], + ); + }); + + test('does not accept a invalid imageQuality argument', () { + expect( + () => picker.getImageFromSource( + imageQuality: -1, source: ImageSource.gallery), + throwsArgumentError, + ); + + expect( + () => picker.getImageFromSource( + imageQuality: 101, source: ImageSource.gallery), + throwsArgumentError, + ); + + expect( + () => picker.getImageFromSource( + imageQuality: -1, source: ImageSource.camera), + throwsArgumentError, + ); + + expect( + () => picker.getImageFromSource( + imageQuality: 101, source: ImageSource.camera), + throwsArgumentError, + ); + }); + + test('does not accept a negative width or height argument', () { + expect( + () => picker.getImageFromSource( + source: ImageSource.camera, maxWidth: -1.0), + throwsArgumentError, + ); + + expect( + () => picker.getImageFromSource( + source: ImageSource.camera, maxHeight: -1.0), + throwsArgumentError, + ); + }); + + test('handles a null image path response gracefully', () async { + picker.channel + .setMockMethodCallHandler((MethodCall methodCall) => null); + + expect(await picker.getImageFromSource(source: ImageSource.gallery), + isNull); + expect(await picker.getImageFromSource(source: ImageSource.camera), + isNull); + }); + + test('camera position defaults to back', () async { + await picker.getImageFromSource(source: ImageSource.camera); + + expect( + log, + [ + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': true, + }), + ], + ); + }); + + test('camera position can set to front', () async { + await picker.getImageFromSource( + source: ImageSource.camera, + preferredCameraDevice: CameraDevice.front); + + expect( + log, + [ + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': 1, + 'forceFullMetadata': true, + }), + ], + ); + }); + + test('passes the full metadata argument correctly', () async { + await picker.getImageFromSource( + source: ImageSource.camera, forceFullMetadata: false); + + expect( + log, + [ + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': false, + }), + ], + ); + }); + }); }); } From 7d255de44b3130ccb93a0e61ebda51185bc645bf Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 3 Jan 2022 14:20:36 +0100 Subject: [PATCH 03/36] Updated changelog in platform interface and app-facing package to match actual changes --- packages/image_picker/image_picker/CHANGELOG.md | 2 +- packages/image_picker/image_picker/pubspec.yaml | 6 ++++++ .../image_picker_platform_interface/CHANGELOG.md | 7 ++----- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md index ce29eb522e3d..39b1743df2cd 100644 --- a/packages/image_picker/image_picker/CHANGELOG.md +++ b/packages/image_picker/image_picker/CHANGELOG.md @@ -1,7 +1,7 @@ ## NEXT - * Updates Android compileSdkVersion to 31. * Fix iOS RunnerUITests search paths. +* Adds `forceFullMetadata` option to `pickImage`, so images on iOS can be picked without `Photo Library Usage` permission. ## 0.8.4+4 diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml index 44a7c9b80749..ff7f1203209b 100755 --- a/packages/image_picker/image_picker/pubspec.yaml +++ b/packages/image_picker/image_picker/pubspec.yaml @@ -33,3 +33,9 @@ dev_dependencies: mockito: ^5.0.0 pedantic: ^1.10.0 plugin_platform_interface: ^2.0.0 + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + image_picker_platform_interface: + path: + ../image_picker_platform_interface \ No newline at end of file diff --git a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md index eccd517cd100..cdcd3385ae23 100644 --- a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md +++ b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md @@ -1,10 +1,7 @@ ## 2.5.0 -* Re-adding `forceFullMetadata` option to `pickImage`, but as truly non-breaking change. - * `forceFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata - which may require extra permission requests on certain platforms. - * If `forceFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces - permission requests from the platform (e.g on iOS the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). +* Re-adding `forceFullMetadata` option, but as a parameter of a new `pickImageFromSource` + method (non-breaking change approach). ## 2.4.1 From 3fd73838955df0fa8e059db72a7f9541af8eeb62 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 3 Jan 2022 14:32:12 +0100 Subject: [PATCH 04/36] Updated app-facing package to call new method from platform interface --- .../image_picker/lib/image_picker.dart | 11 ++++- .../image_picker/image_picker/pubspec.yaml | 2 +- .../test/image_picker_deprecated_test.dart | 29 +++++++---- .../image_picker/test/image_picker_test.dart | 48 +++++++++++++++---- 4 files changed, 70 insertions(+), 20 deletions(-) diff --git a/packages/image_picker/image_picker/lib/image_picker.dart b/packages/image_picker/image_picker/lib/image_picker.dart index 5bc99d7f0bb2..9ac682c010c7 100755 --- a/packages/image_picker/image_picker/lib/image_picker.dart +++ b/packages/image_picker/image_picker/lib/image_picker.dart @@ -191,6 +191,13 @@ class ImagePicker { /// the front or rear camera should be opened, this function is not guaranteed /// to work on an Android device. /// + /// Use `forceFullMetadata` (defaults to `true`) to control, how much additional information the plugin tries to get on iOS. + /// If `forceFullMetadata` is set to `true`, the plugin tries to get the full image metadata which may require + /// extra permission requests. + /// If `forceFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests + /// from the iOS platform (it won’t ask for the `Photo Library Usage` permission). + /// + /// /// In Android, the MainActivity can be destroyed for various reasons. If that happens, the result will be lost /// in this call. You can then call [retrieveLostData] when your app relaunches to retrieve the lost data. /// @@ -206,13 +213,15 @@ class ImagePicker { double? maxHeight, int? imageQuality, CameraDevice preferredCameraDevice = CameraDevice.rear, + bool forceFullMetadata = true, }) { - return platform.getImage( + return platform.getImageFromSource( source: source, maxWidth: maxWidth, maxHeight: maxHeight, imageQuality: imageQuality, preferredCameraDevice: preferredCameraDevice, + forceFullMetadata: forceFullMetadata, ); } diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml index ff7f1203209b..730e0164dc15 100755 --- a/packages/image_picker/image_picker/pubspec.yaml +++ b/packages/image_picker/image_picker/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for selecting images from the Android and iOS image library, and taking new pictures with the camera. repository: https://github.com/flutter/plugins/tree/master/packages/image_picker/image_picker issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 -version: 0.8.4+4 +version: 0.8.5 environment: sdk: ">=2.14.0 <3.0.0" diff --git a/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart b/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart index f295e3d02f66..21294f99526c 100644 --- a/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart +++ b/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart @@ -57,14 +57,16 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -103,49 +105,56 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -182,6 +191,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -201,6 +211,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, + 'forceFullMetadata': true, }), ], ); diff --git a/packages/image_picker/image_picker/test/image_picker_test.dart b/packages/image_picker/image_picker/test/image_picker_test.dart index 10bc64082aca..8a5bd8f9f9db 100644 --- a/packages/image_picker/image_picker/test/image_picker_test.dart +++ b/packages/image_picker/image_picker/test/image_picker_test.dart @@ -52,14 +52,16 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -98,49 +100,56 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': null, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': 70, - 'cameraDevice': 0 + 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -177,6 +186,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, + 'forceFullMetadata': true, }), ], ); @@ -196,6 +206,26 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, + 'forceFullMetadata': true, + }), + ], + ); + }); + + test('passes the full metadata argument correctly', () async { + await picker.pickImage( + source: ImageSource.camera, forceFullMetadata: false); + + expect( + log, + [ + isMethodCall('pickImage', arguments: { + 'source': 0, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': 0, + 'forceFullMetadata': false, }), ], ); From 1f7319122cd0ed900c2d6c16cedcbe4fcd78e77b Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Wed, 12 Jan 2022 11:08:26 +0100 Subject: [PATCH 05/36] Fixed version in changelog file --- packages/image_picker/image_picker/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md index 39b1743df2cd..eb74e13f45da 100644 --- a/packages/image_picker/image_picker/CHANGELOG.md +++ b/packages/image_picker/image_picker/CHANGELOG.md @@ -1,4 +1,4 @@ -## NEXT +## 0.8.5 * Updates Android compileSdkVersion to 31. * Fix iOS RunnerUITests search paths. * Adds `forceFullMetadata` option to `pickImage`, so images on iOS can be picked without `Photo Library Usage` permission. From 10847632a7c62ca50d3c15def0b2bbb11aaeda47 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 24 Jan 2022 12:29:59 +0100 Subject: [PATCH 06/36] PR remarks Added missing native implementation of the new flag --- .../ios/Classes/FLTImagePickerPlugin.m | 28 +++++++++++-- .../image_picker/lib/image_picker.dart | 9 ++--- .../CHANGELOG.md | 4 +- .../method_channel_image_picker.dart | 40 +++++++++---------- .../image_picker_platform.dart | 2 +- 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m index cf3103195482..89984dc2aec9 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m @@ -97,7 +97,12 @@ - (void)pickImageWithPHPicker:(int)maxImagesAllowed API_AVAILABLE(ios(14)) { self.maxImagesAllowed = maxImagesAllowed; - [self checkPhotoAuthorizationForAccessLevel]; + BOOL usePhaAsset = [[_arguments objectForKey:@"forceFullMetadata"] boolValue]; + if (usePhaAsset) { + [self checkPhotoAuthorizationForAccessLevel]; + } else { + [self showPhotoLibrary:PHPickerClassType]; + } } - (void)pickImageWithUIImagePicker { @@ -107,6 +112,7 @@ - (void)pickImageWithUIImagePicker { _imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ]; int imageSource = [[_arguments objectForKey:@"source"] intValue]; + BOOL usePhaAsset = [[_arguments objectForKey:@"forceFullMetadata"] boolValue]; self.maxImagesAllowed = 1; @@ -115,7 +121,11 @@ - (void)pickImageWithUIImagePicker { [self checkCameraAuthorization]; break; case SOURCE_GALLERY: - [self checkPhotoAuthorization]; + if (usePhaAsset) { + [self checkPhotoAuthorization]; + } else { + [self showPhotoLibrary:UIImagePickerClassType]; + } break; default: self.result([FlutterError errorWithCode:@"invalid_source" @@ -132,13 +142,14 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result details:nil]); self.result = nil; } + BOOL usePhaAsset = [[_arguments objectForKey:@"forceFullMetadata"] boolValue]; if ([@"pickImage" isEqualToString:call.method]) { self.result = result; _arguments = call.arguments; int imageSource = [[_arguments objectForKey:@"source"] intValue]; - if (imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker + if (usePhaAsset && imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker if (@available(iOS 14, *)) { // PHPicker is used [self pickImageWithPHPicker:1]; @@ -181,6 +192,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [self checkCameraAuthorization]; break; case SOURCE_GALLERY: + if (usePhaAsset) { + [self checkPhotoAuthorization]; + } else { + [self showPhotoLibrary:UIImagePickerClassType]; + } [self checkPhotoAuthorization]; break; default: @@ -484,8 +500,12 @@ - (void)imagePickerController:(UIImagePickerController *)picker NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"]; NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"]; NSNumber *desiredImageQuality = [self getDesiredImageQuality:imageQuality]; + BOOL usePhaAsset = [[_arguments objectForKey:@"forceFullMetadata"] boolValue]; - PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; + PHAsset *originalAsset; + if(usePhaAsset) { + PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; + } if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) { image = [FLTImagePickerImageUtil scaledImage:image diff --git a/packages/image_picker/image_picker/lib/image_picker.dart b/packages/image_picker/image_picker/lib/image_picker.dart index 9ac682c010c7..c06068fad2ec 100755 --- a/packages/image_picker/image_picker/lib/image_picker.dart +++ b/packages/image_picker/image_picker/lib/image_picker.dart @@ -191,12 +191,9 @@ class ImagePicker { /// the front or rear camera should be opened, this function is not guaranteed /// to work on an Android device. /// - /// Use `forceFullMetadata` (defaults to `true`) to control, how much additional information the plugin tries to get on iOS. - /// If `forceFullMetadata` is set to `true`, the plugin tries to get the full image metadata which may require - /// extra permission requests. - /// If `forceFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests - /// from the iOS platform (it won’t ask for the `Photo Library Usage` permission). - /// + /// Use `requestFullMetadata` (defaults to `true`) to control how much additional information the plugin tries to get on iOS. + /// If `requestFullMetadata` is set to `true`, the plugin tries to get the full image metadata which may require + /// extra permission requests on some platforms, such as `Photo Library Usage` permission on iOS . /// /// In Android, the MainActivity can be destroyed for various reasons. If that happens, the result will be lost /// in this call. You can then call [retrieveLostData] when your app relaunches to retrieve the lost data. diff --git a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md index 635f509f34ad..8d0929a8ca81 100644 --- a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md +++ b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md @@ -1,7 +1,7 @@ ## 2.5.0 -* Re-adding `forceFullMetadata` option, but as a parameter of a new `pickImageFromSource` - method (non-breaking change approach). +* Re-adds `forceFullMetadata` option, but as a parameter of a new `pickImageFromSource` + method. ## 2.4.3 diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart index ba334afcf610..f8e2c063c262 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart @@ -196,6 +196,26 @@ class MethodChannelImagePicker extends ImagePickerPlatform { return path != null ? XFile(path) : null; } + @override + Future getImageFromSource({ + required ImageSource source, + double? maxWidth, + double? maxHeight, + int? imageQuality, + CameraDevice preferredCameraDevice = CameraDevice.rear, + bool forceFullMetadata = true, + }) async { + String? path = await _getImagePath( + source: source, + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice, + forceFullMetadata: forceFullMetadata, + ); + return path != null ? XFile(path) : null; + } + @override Future?> getMultiImage({ double? maxWidth, @@ -272,24 +292,4 @@ class MethodChannelImagePicker extends ImagePickerPlatform { files: pickedFileList, ); } - - @override - Future getImageFromSource({ - required ImageSource source, - double? maxWidth, - double? maxHeight, - int? imageQuality, - CameraDevice preferredCameraDevice = CameraDevice.rear, - bool forceFullMetadata = true, - }) async { - String? path = await _getImagePath( - source: source, - maxWidth: maxWidth, - maxHeight: maxHeight, - imageQuality: imageQuality, - preferredCameraDevice: preferredCameraDevice, - forceFullMetadata: forceFullMetadata, - ); - return path != null ? XFile(path) : null; - } } diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart index 9016034b2407..9efe6ad4b98d 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart @@ -146,7 +146,7 @@ abstract class ImagePickerPlatform extends PlatformInterface { throw UnimplementedError('retrieveLostData() has not been implemented.'); } - /// This method is deprecated in favor of [getImageFromSource] and will be removed in a future update + /// This method is deprecated in favor of [getImageFromSource] and will be removed in a future update. /// /// Returns an [XFile] with the image that was picked. /// From a89ad0a31f6434eb21b44f58fe04bc0ad0e9aeef Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 24 Jan 2022 12:33:33 +0100 Subject: [PATCH 07/36] Renamed flag to better specify its purpose --- .../image_picker/lib/image_picker.dart | 4 +- .../test/image_picker_deprecated_test.dart | 22 +++--- .../image_picker/test/image_picker_test.dart | 26 +++---- .../method_channel_image_picker.dart | 8 +-- .../image_picker_platform.dart | 6 +- .../new_method_channel_image_picker_test.dart | 70 +++++++++---------- 6 files changed, 68 insertions(+), 68 deletions(-) diff --git a/packages/image_picker/image_picker/lib/image_picker.dart b/packages/image_picker/image_picker/lib/image_picker.dart index c06068fad2ec..209d5ddb2bad 100755 --- a/packages/image_picker/image_picker/lib/image_picker.dart +++ b/packages/image_picker/image_picker/lib/image_picker.dart @@ -210,7 +210,7 @@ class ImagePicker { double? maxHeight, int? imageQuality, CameraDevice preferredCameraDevice = CameraDevice.rear, - bool forceFullMetadata = true, + bool requestFullMetadata = true, }) { return platform.getImageFromSource( source: source, @@ -218,7 +218,7 @@ class ImagePicker { maxHeight: maxHeight, imageQuality: imageQuality, preferredCameraDevice: preferredCameraDevice, - forceFullMetadata: forceFullMetadata, + requestFullMetadata: requestFullMetadata, ); } diff --git a/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart b/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart index 21294f99526c..6358967b35c0 100644 --- a/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart +++ b/packages/image_picker/image_picker/test/image_picker_deprecated_test.dart @@ -58,7 +58,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, @@ -66,7 +66,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -106,7 +106,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -114,7 +114,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -122,7 +122,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -130,7 +130,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -138,7 +138,7 @@ void main() { 'maxHeight': null, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -146,7 +146,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -154,7 +154,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -191,7 +191,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -211,7 +211,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); diff --git a/packages/image_picker/image_picker/test/image_picker_test.dart b/packages/image_picker/image_picker/test/image_picker_test.dart index 8a5bd8f9f9db..2032a3856fff 100644 --- a/packages/image_picker/image_picker/test/image_picker_test.dart +++ b/packages/image_picker/image_picker/test/image_picker_test.dart @@ -53,7 +53,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, @@ -61,7 +61,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -101,7 +101,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -109,7 +109,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -117,7 +117,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -125,7 +125,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -133,7 +133,7 @@ void main() { 'maxHeight': null, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -141,7 +141,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -149,7 +149,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -186,7 +186,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -206,7 +206,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -214,7 +214,7 @@ void main() { test('passes the full metadata argument correctly', () async { await picker.pickImage( - source: ImageSource.camera, forceFullMetadata: false); + source: ImageSource.camera, requestFullMetadata: false); expect( log, @@ -225,7 +225,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': false, + 'requestFullMetadata': false, }), ], ); diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart index f8e2c063c262..efc4d98f16af 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart @@ -85,7 +85,7 @@ class MethodChannelImagePicker extends ImagePickerPlatform { double? maxHeight, int? imageQuality, CameraDevice preferredCameraDevice = CameraDevice.rear, - bool forceFullMetadata = true, + bool requestFullMetadata = true, }) { if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) { throw ArgumentError.value( @@ -108,7 +108,7 @@ class MethodChannelImagePicker extends ImagePickerPlatform { 'maxHeight': maxHeight, 'imageQuality': imageQuality, 'cameraDevice': preferredCameraDevice.index, - 'forceFullMetadata': forceFullMetadata, + 'requestFullMetadata': requestFullMetadata, }, ); } @@ -203,7 +203,7 @@ class MethodChannelImagePicker extends ImagePickerPlatform { double? maxHeight, int? imageQuality, CameraDevice preferredCameraDevice = CameraDevice.rear, - bool forceFullMetadata = true, + bool requestFullMetadata = true, }) async { String? path = await _getImagePath( source: source, @@ -211,7 +211,7 @@ class MethodChannelImagePicker extends ImagePickerPlatform { maxHeight: maxHeight, imageQuality: imageQuality, preferredCameraDevice: preferredCameraDevice, - forceFullMetadata: forceFullMetadata, + requestFullMetadata: requestFullMetadata, ); return path != null ? XFile(path) : null; } diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart index 9efe6ad4b98d..f75629d67d9c 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart @@ -278,9 +278,9 @@ abstract class ImagePickerPlatform extends PlatformInterface { /// the front or rear camera should be opened, this function is not guaranteed /// to work on an Android device. /// - /// `forceFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata which may require + /// `requestFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata which may require /// extra permission requests on certain platforms. - /// If `forceFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests + /// If `requestFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests /// from the platform (e.g. on iOS the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). /// /// In Android, the MainActivity can be destroyed for various reasons. If that happens, the result will be lost @@ -293,7 +293,7 @@ abstract class ImagePickerPlatform extends PlatformInterface { double? maxHeight, int? imageQuality, CameraDevice preferredCameraDevice = CameraDevice.rear, - bool forceFullMetadata = true, + bool requestFullMetadata = true, }) { return getImage( source: source, diff --git a/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart b/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart index aa1d6e53aebe..cfcfcc233d25 100644 --- a/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart +++ b/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart @@ -41,7 +41,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, @@ -49,7 +49,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -96,7 +96,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -104,7 +104,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -112,7 +112,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -120,7 +120,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -128,7 +128,7 @@ void main() { 'maxHeight': null, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -136,7 +136,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -144,7 +144,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -205,7 +205,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -225,7 +225,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -521,7 +521,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, @@ -529,7 +529,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -576,7 +576,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -584,7 +584,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -592,7 +592,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -600,7 +600,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -608,7 +608,7 @@ void main() { 'maxHeight': null, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -616,7 +616,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -624,7 +624,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -684,7 +684,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -704,7 +704,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -1016,7 +1016,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 1, @@ -1024,7 +1024,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -1071,7 +1071,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -1079,7 +1079,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -1087,7 +1087,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -1095,7 +1095,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -1103,7 +1103,7 @@ void main() { 'maxHeight': null, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -1111,7 +1111,7 @@ void main() { 'maxHeight': 10.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), isMethodCall('pickImage', arguments: { 'source': 0, @@ -1119,7 +1119,7 @@ void main() { 'maxHeight': 20.0, 'imageQuality': 70, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -1187,7 +1187,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -1207,7 +1207,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 1, - 'forceFullMetadata': true, + 'requestFullMetadata': true, }), ], ); @@ -1215,7 +1215,7 @@ void main() { test('passes the full metadata argument correctly', () async { await picker.getImageFromSource( - source: ImageSource.camera, forceFullMetadata: false); + source: ImageSource.camera, requestFullMetadata: false); expect( log, @@ -1226,7 +1226,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': 0, - 'forceFullMetadata': false, + 'requestFullMetadata': false, }), ], ); From 8ff7492d78e0ceecd1e6726b54464c0bba225bd5 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 24 Jan 2022 13:04:01 +0100 Subject: [PATCH 08/36] Renamed flag in remaining occurences --- packages/image_picker/image_picker/CHANGELOG.md | 2 +- .../image_picker/ios/Classes/FLTImagePickerPlugin.m | 8 ++++---- .../image_picker_platform_interface/CHANGELOG.md | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/image_picker/image_picker/CHANGELOG.md b/packages/image_picker/image_picker/CHANGELOG.md index eb74e13f45da..dce802879e92 100644 --- a/packages/image_picker/image_picker/CHANGELOG.md +++ b/packages/image_picker/image_picker/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.8.5 * Updates Android compileSdkVersion to 31. * Fix iOS RunnerUITests search paths. -* Adds `forceFullMetadata` option to `pickImage`, so images on iOS can be picked without `Photo Library Usage` permission. +* Adds `requestFullMetadata` option to `pickImage`, so images on iOS can be picked without `Photo Library Usage` permission. ## 0.8.4+4 diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m index 89984dc2aec9..6f5719e788eb 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m @@ -97,7 +97,7 @@ - (void)pickImageWithPHPicker:(int)maxImagesAllowed API_AVAILABLE(ios(14)) { self.maxImagesAllowed = maxImagesAllowed; - BOOL usePhaAsset = [[_arguments objectForKey:@"forceFullMetadata"] boolValue]; + BOOL usePhaAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; if (usePhaAsset) { [self checkPhotoAuthorizationForAccessLevel]; } else { @@ -112,7 +112,7 @@ - (void)pickImageWithUIImagePicker { _imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ]; int imageSource = [[_arguments objectForKey:@"source"] intValue]; - BOOL usePhaAsset = [[_arguments objectForKey:@"forceFullMetadata"] boolValue]; + BOOL usePhaAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; self.maxImagesAllowed = 1; @@ -142,7 +142,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result details:nil]); self.result = nil; } - BOOL usePhaAsset = [[_arguments objectForKey:@"forceFullMetadata"] boolValue]; + BOOL usePhaAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; if ([@"pickImage" isEqualToString:call.method]) { self.result = result; @@ -500,7 +500,7 @@ - (void)imagePickerController:(UIImagePickerController *)picker NSNumber *maxHeight = [_arguments objectForKey:@"maxHeight"]; NSNumber *imageQuality = [_arguments objectForKey:@"imageQuality"]; NSNumber *desiredImageQuality = [self getDesiredImageQuality:imageQuality]; - BOOL usePhaAsset = [[_arguments objectForKey:@"forceFullMetadata"] boolValue]; + BOOL usePhaAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; PHAsset *originalAsset; if(usePhaAsset) { diff --git a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md index 8d0929a8ca81..6f2b4642c3bd 100644 --- a/packages/image_picker/image_picker_platform_interface/CHANGELOG.md +++ b/packages/image_picker/image_picker_platform_interface/CHANGELOG.md @@ -1,6 +1,6 @@ ## 2.5.0 -* Re-adds `forceFullMetadata` option, but as a parameter of a new `pickImageFromSource` +* Re-adds `requestFullMetadata` option, but as a parameter of a new `pickImageFromSource` method. ## 2.4.3 @@ -18,10 +18,10 @@ ## 2.4.0 -* Add `forceFullMetadata` option to `pickImage`. - * To keep this non-breaking `forceFullMetadata` defaults to `true`, so the plugin tries +* Add `requestFullMetadata` option to `pickImage`. + * To keep this non-breaking `requestFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata which may require extra permission requests on certain platforms. - * If `forceFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces + * If `requestFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests from the platform (e.g on iOS the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). ## 2.3.0 From 95eef20a53fb5c52b6b65e9aa9a3900b70158bc1 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 24 Jan 2022 13:38:03 +0100 Subject: [PATCH 09/36] Fixed formatting and originalAsset assignment --- .../image_picker/ios/Classes/FLTImagePickerPlugin.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m index 6f5719e788eb..27cee924de66 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m @@ -503,8 +503,8 @@ - (void)imagePickerController:(UIImagePickerController *)picker BOOL usePhaAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; PHAsset *originalAsset; - if(usePhaAsset) { - PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; + if (usePhaAsset) { + originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; } if (maxWidth != (id)[NSNull null] || maxHeight != (id)[NSNull null]) { From f5f94b2e5236960af6f0c123d0be4c11ebf19a0e Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 14 Feb 2022 09:23:19 +0100 Subject: [PATCH 10/36] PR remarks --- .../image_picker/ios/Classes/FLTImagePickerPlugin.m | 7 ++++--- packages/image_picker/image_picker/lib/image_picker.dart | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m index f08081027213..7bffd435416c 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m @@ -142,13 +142,13 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result details:nil]); self.result = nil; } - BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; - + if ([@"pickImage" isEqualToString:call.method]) { self.result = result; _arguments = call.arguments; int imageSource = [[_arguments objectForKey:@"source"] intValue]; - + BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + if (usePHAsset && imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker if (@available(iOS 14, *)) { // PHPicker is used @@ -182,6 +182,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result _arguments = call.arguments; int imageSource = [[_arguments objectForKey:@"source"] intValue]; + BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; if ([[_arguments objectForKey:@"maxDuration"] isKindOfClass:[NSNumber class]]) { NSTimeInterval max = [[_arguments objectForKey:@"maxDuration"] doubleValue]; _imagePickerController.videoMaximumDuration = max; diff --git a/packages/image_picker/image_picker/lib/image_picker.dart b/packages/image_picker/image_picker/lib/image_picker.dart index 209d5ddb2bad..c874220ab3c1 100755 --- a/packages/image_picker/image_picker/lib/image_picker.dart +++ b/packages/image_picker/image_picker/lib/image_picker.dart @@ -191,7 +191,7 @@ class ImagePicker { /// the front or rear camera should be opened, this function is not guaranteed /// to work on an Android device. /// - /// Use `requestFullMetadata` (defaults to `true`) to control how much additional information the plugin tries to get on iOS. + /// Use `requestFullMetadata` (defaults to `true`) to control how much additional information the plugin tries to get. /// If `requestFullMetadata` is set to `true`, the plugin tries to get the full image metadata which may require /// extra permission requests on some platforms, such as `Photo Library Usage` permission on iOS . /// From bd3dfebed9d098716ce2e79a1f9fffecc31cf2eb Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 14 Feb 2022 09:38:10 +0100 Subject: [PATCH 11/36] Fixed issues after merge --- .../ios/Classes/FLTImagePickerPlugin.m | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m index c70e7f259b21..4f97337f221f 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m @@ -137,7 +137,7 @@ - (void)pickImageWithPHPicker:(int)maxImagesAllowed API_AVAILABLE(ios(14)) { if (usePHAsset) { [self checkPhotoAuthorizationForAccessLevel]; } else { - [self showPhotoLibrary:PHPickerClassType]; + [self showPhotoLibraryWithPHPicker:_pickerViewController]; } } @@ -158,7 +158,7 @@ - (void)launchUIImagePickerWithSource:(int)imageSource { if (usePHAsset) { [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; } else { - [self showPhotoLibrary:UIImagePickerClassType]; + [self showPhotoLibraryWithImagePicker:imagePickerController]; } break; default: @@ -179,12 +179,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result self.result = result; _arguments = call.arguments; - + BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + if ([@"pickImage" isEqualToString:call.method]) { int imageSource = [call.arguments[@"source"] intValue]; - BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; - - if (imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker + if (usePHAsset && imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker if (@available(iOS 14, *)) { // PHPicker is used [self pickImageWithPHPicker:1]; @@ -212,7 +211,6 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result imagePickerController.videoQuality = UIImagePickerControllerQualityTypeHigh; int imageSource = [call.arguments[@"source"] intValue]; - BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; if ([call.arguments[@"maxDuration"] isKindOfClass:[NSNumber class]]) { NSTimeInterval max = [call.arguments[@"maxDuration"] doubleValue]; imagePickerController.videoMaximumDuration = max; @@ -226,7 +224,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result if (usePHAsset) { [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; } else { - [self showPhotoLibrary:UIImagePickerClassType]; + [self showPhotoLibraryWithImagePicker:imagePickerController]; } break; default: From b99ba0744d80e9891e49a5e415b6181a4df2b52c Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 14 Feb 2022 11:19:32 +0100 Subject: [PATCH 12/36] Added a test for picking image without full metadata --- .../ios/RunnerTests/ImagePickerPluginTests.m | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m index 5f3287400c5e..eb552f1aae17 100644 --- a/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -180,6 +180,26 @@ - (void)testPickMultiImageShouldUseUIImagePickerControllerOnPreiOS14 { [mockUIImagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]); } +- (void)testPickImageWithoutFullMetadata { + id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); + + FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new]; + [plugin setImagePickerControllerOverrides:@[ mockUIImagePicker ]]; + FlutterMethodCall *call = [FlutterMethodCall methodCallWithMethodName:@"pickImage" + arguments:@{ + @"source" : @(1), + @"requestFullMetadata" : @(false), + }]; + + [plugin handleMethodCall:call + result:^(id _Nullable r){ + }]; + + OCMVerify(times(1), + [mockUIImagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]); +} + + #pragma mark - Test camera devices, no op on simulators - (void)testPluginPickImageDeviceCancelClickMultipleTimes { From 3d6c45c48bea769c7c851ef2fbcfaf3830b7370f Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 14 Feb 2022 11:23:19 +0100 Subject: [PATCH 13/36] Fixed code formatting --- .../example/ios/RunnerTests/ImagePickerPluginTests.m | 1 - .../image_picker/ios/Classes/FLTImagePickerPlugin.m | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m index eb552f1aae17..7b7d7342b05b 100644 --- a/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -199,7 +199,6 @@ - (void)testPickImageWithoutFullMetadata { [mockUIImagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]); } - #pragma mark - Test camera devices, no op on simulators - (void)testPluginPickImageDeviceCancelClickMultipleTimes { diff --git a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m index 4f97337f221f..4768ba4f2e23 100644 --- a/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker/ios/Classes/FLTImagePickerPlugin.m @@ -180,7 +180,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result self.result = result; _arguments = call.arguments; BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; - + if ([@"pickImage" isEqualToString:call.method]) { int imageSource = [call.arguments[@"source"] intValue]; if (usePHAsset && imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker From bf3f55ce1348eb2146583232b03c44e6e62e1f00 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 7 Apr 2022 13:59:27 +0200 Subject: [PATCH 14/36] PR remarks --- .../ios/Classes/FLTImagePickerPlugin.m | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m index 4768ba4f2e23..34011490d622 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m @@ -155,10 +155,15 @@ - (void)launchUIImagePickerWithSource:(int)imageSource { [self checkCameraAuthorizationWithImagePicker:imagePickerController]; break; case SOURCE_GALLERY: - if (usePHAsset) { - [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; + if (@available(iOS 11, *)) { + if (usePHAsset) { + [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; + } else { + [self showPhotoLibraryWithImagePicker:imagePickerController]; + } } else { - [self showPhotoLibraryWithImagePicker:imagePickerController]; + // Prior to iOS 11, accessing gallery requires authorization + [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; } break; default: @@ -179,11 +184,10 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result self.result = result; _arguments = call.arguments; - BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; if ([@"pickImage" isEqualToString:call.method]) { int imageSource = [call.arguments[@"source"] intValue]; - if (usePHAsset && imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker + if (imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker if (@available(iOS 14, *)) { // PHPicker is used [self pickImageWithPHPicker:1]; @@ -216,6 +220,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result imagePickerController.videoMaximumDuration = max; } + BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; switch (imageSource) { case SOURCE_CAMERA: [self checkCameraAuthorizationWithImagePicker:imagePickerController]; From 742b259eb90967f412856ff22455c865af9b5eee Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 7 Apr 2022 14:15:32 +0200 Subject: [PATCH 15/36] Fixed linter warnings --- .../lib/src/method_channel/method_channel_image_picker.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart index e1add079c47e..338bf2500885 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart @@ -208,7 +208,7 @@ class MethodChannelImagePicker extends ImagePickerPlatform { CameraDevice preferredCameraDevice = CameraDevice.rear, bool requestFullMetadata = true, }) async { - String? path = await _getImagePath( + final String? path = await _getImagePath( source: source, maxWidth: maxWidth, maxHeight: maxHeight, From d41b3900fbe1197eb0af7e2298d5a20e88af342d Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 7 Apr 2022 15:20:36 +0200 Subject: [PATCH 16/36] Added dependency overrides for missing modules Fixed failing test --- packages/image_picker/image_picker/example/pubspec.yaml | 6 ++++++ packages/image_picker/image_picker_android/pubspec.yaml | 6 ++++++ .../example/ios/RunnerTests/ImagePickerPluginTests.m | 6 ++++-- packages/image_picker/image_picker_ios/pubspec.yaml | 6 ++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/image_picker/image_picker/example/pubspec.yaml b/packages/image_picker/image_picker/example/pubspec.yaml index 4fe823587398..d4cec061a6cc 100755 --- a/packages/image_picker/image_picker/example/pubspec.yaml +++ b/packages/image_picker/image_picker/example/pubspec.yaml @@ -28,3 +28,9 @@ dev_dependencies: flutter: uses-material-design: true + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + image_picker_platform_interface: + path: + ../../image_picker_platform_interface \ No newline at end of file diff --git a/packages/image_picker/image_picker_android/pubspec.yaml b/packages/image_picker/image_picker_android/pubspec.yaml index dbeef9bed193..8aa83d78cbec 100755 --- a/packages/image_picker/image_picker_android/pubspec.yaml +++ b/packages/image_picker/image_picker_android/pubspec.yaml @@ -26,3 +26,9 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + image_picker_platform_interface: + path: + ../image_picker_platform_interface \ No newline at end of file diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m index ff2d3d61b91f..abfe902575b3 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -180,9 +180,11 @@ - (void)testPickMultiImageShouldUseUIImagePickerControllerOnPreiOS14 { [mockUIImagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]); } -- (void)testPickImageWithoutFullMetadata { +- (void)testPickImageWithoutFullMetadataPreiOS14 { + if (@available(iOS 14, *)) { + return; + } id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); - FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new]; [plugin setImagePickerControllerOverrides:@[ mockUIImagePicker ]]; FlutterMethodCall *call = [FlutterMethodCall methodCallWithMethodName:@"pickImage" diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml index 2587c9a0d15b..433af10e9836 100755 --- a/packages/image_picker/image_picker_ios/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/pubspec.yaml @@ -24,3 +24,9 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + image_picker_platform_interface: + path: + ../image_picker_platform_interface \ No newline at end of file From ead2f624a6abf9938c504b3efa1fb3f4eb0bdf8c Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 7 Apr 2022 15:22:44 +0200 Subject: [PATCH 17/36] Fixed formatting --- .../example/ios/RunnerTests/ImagePickerPluginTests.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m index abfe902575b3..9183d7b849f8 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -182,7 +182,7 @@ - (void)testPickMultiImageShouldUseUIImagePickerControllerOnPreiOS14 { - (void)testPickImageWithoutFullMetadataPreiOS14 { if (@available(iOS 14, *)) { - return; + return; } id mockUIImagePicker = OCMClassMock([UIImagePickerController class]); FLTImagePickerPlugin *plugin = [FLTImagePickerPlugin new]; From 7b6ace90fb337c5a78cb56095bf5ec0fed6000b3 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Fri, 8 Apr 2022 10:12:49 +0200 Subject: [PATCH 18/36] Added options class for handling image picking settings --- .../image_picker/lib/image_picker.dart | 12 ++-- .../method_channel_image_picker.dart | 17 ++--- .../image_picker_platform.dart | 41 +++--------- .../lib/src/types/image_picker_options.dart | 42 ++++++++++++ .../lib/src/types/types.dart | 1 + .../new_method_channel_image_picker_test.dart | 65 +++++++++++++------ 6 files changed, 112 insertions(+), 66 deletions(-) create mode 100644 packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart diff --git a/packages/image_picker/image_picker/lib/image_picker.dart b/packages/image_picker/image_picker/lib/image_picker.dart index c874220ab3c1..b086a2051dbe 100755 --- a/packages/image_picker/image_picker/lib/image_picker.dart +++ b/packages/image_picker/image_picker/lib/image_picker.dart @@ -214,11 +214,13 @@ class ImagePicker { }) { return platform.getImageFromSource( source: source, - maxWidth: maxWidth, - maxHeight: maxHeight, - imageQuality: imageQuality, - preferredCameraDevice: preferredCameraDevice, - requestFullMetadata: requestFullMetadata, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice, + requestFullMetadata: requestFullMetadata, + ), ); } diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart index 338bf2500885..6a5a6b69269d 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart @@ -202,19 +202,16 @@ class MethodChannelImagePicker extends ImagePickerPlatform { @override Future getImageFromSource({ required ImageSource source, - double? maxWidth, - double? maxHeight, - int? imageQuality, - CameraDevice preferredCameraDevice = CameraDevice.rear, - bool requestFullMetadata = true, + ImagePickerOptions? options, }) async { final String? path = await _getImagePath( source: source, - maxWidth: maxWidth, - maxHeight: maxHeight, - imageQuality: imageQuality, - preferredCameraDevice: preferredCameraDevice, - requestFullMetadata: requestFullMetadata, + maxHeight: options?.maxHeight, + maxWidth: options?.maxWidth, + imageQuality: options?.imageQuality, + preferredCameraDevice: + options?.preferredCameraDevice ?? CameraDevice.rear, + requestFullMetadata: options?.requestFullMetadata ?? true, ); return path != null ? XFile(path) : null; } diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart index aefaf8dff577..f96fadd62316 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart @@ -259,29 +259,11 @@ abstract class ImagePickerPlatform extends PlatformInterface { /// The `source` argument controls where the image comes from. This can /// be either [ImageSource.camera] or [ImageSource.gallery]. /// - /// Where iOS supports HEIC images, Android 8 and below doesn't. Android 9 and above only support HEIC images if used - /// in addition to a size modification, of which the usage is explained below. - /// - /// If specified, the image will be at most `maxWidth` wide and - /// `maxHeight` tall. Otherwise the image will be returned at it's - /// original width and height. - /// - /// The `imageQuality` argument modifies the quality of the image, ranging from 0-100 - /// where 100 is the original/max quality. If `imageQuality` is null, the image with - /// the original quality will be returned. Compression is only supported for certain - /// image types such as JPEG. If compression is not supported for the image that is picked, - /// a warning message will be logged. + /// The `options` argument controls additional settings that can be used when picking an image. See [ImagePickerOptions] + /// for more details. /// - /// Use `preferredCameraDevice` to specify the camera to use when the `source` is [ImageSource.camera]. - /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device. - /// Defaults to [CameraDevice.rear]. Note that Android has no documented parameter for an intent to specify if - /// the front or rear camera should be opened, this function is not guaranteed - /// to work on an Android device. - /// - /// `requestFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata which may require - /// extra permission requests on certain platforms. - /// If `requestFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests - /// from the platform (e.g. on iOS the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). + /// Where iOS supports HEIC images, Android 8 and below doesn't. Android 9 and above only support HEIC images if used + /// in addition to a size modification, of which the usage is explained in [ImagePickerOptions]. /// /// In Android, the MainActivity can be destroyed for various reasons. If that happens, the result will be lost /// in this call. You can then call [getLostData] when your app relaunches to retrieve the lost data. @@ -289,18 +271,15 @@ abstract class ImagePickerPlatform extends PlatformInterface { /// If no images were picked, the return value is null. Future getImageFromSource({ required ImageSource source, - double? maxWidth, - double? maxHeight, - int? imageQuality, - CameraDevice preferredCameraDevice = CameraDevice.rear, - bool requestFullMetadata = true, + ImagePickerOptions? options, }) { return getImage( source: source, - maxHeight: maxHeight, - maxWidth: maxWidth, - imageQuality: imageQuality, - preferredCameraDevice: preferredCameraDevice, + maxHeight: options?.maxHeight, + maxWidth: options?.maxWidth, + imageQuality: options?.imageQuality, + preferredCameraDevice: + options?.preferredCameraDevice ?? CameraDevice.rear, ); } } diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart b/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart new file mode 100644 index 000000000000..38612876bfbc --- /dev/null +++ b/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart @@ -0,0 +1,42 @@ +import 'package:image_picker_platform_interface/src/types/types.dart'; + +/// Specifies options for picking a single image from the device's camera or gallery. +class ImagePickerOptions { + /// Creates an instance with the given [maxHeight], [maxWidth], [imageQuality], + /// [referredCameraDevice] and [requestFullMetadata]. Any of the params may be null. + ImagePickerOptions({ + this.maxHeight, + this.maxWidth, + this.imageQuality, + this.preferredCameraDevice = CameraDevice.rear, + this.requestFullMetadata = true, + }); + + /// If specified, the image will be at most `maxWidth` wide. Otherwise, + /// the image will be returned at its original width. + final double? maxWidth; + + /// If specified, the image will be at most`maxHeight` tall. + /// Otherwise the image will be returned at its original height. + final double? maxHeight; + + /// Modifies the quality of the image, ranging from 0-100 + /// where 100 is the original/max quality. If `imageQuality` is null, the image with + /// the original quality will be returned. Compression is only supported for certain + /// image types such as JPEG. If compression is not supported for the image that is picked, + /// a warning message will be logged. + final int? imageQuality; + + /// Used to specify the camera to use when the `source` is [ImageSource.camera]. + /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device. + /// Defaults to [CameraDevice.rear]. Note that Android has no documented parameter for an intent to specify if + /// the front or rear camera should be opened, this function is not guaranteed + /// to work on an Android device. + final CameraDevice preferredCameraDevice; + + /// `requestFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata which may require + /// extra permission requests on certain platforms. + /// If `requestFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests + /// from the platform (e.g. on iOS the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). + final bool requestFullMetadata; +} diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/types/types.dart b/packages/image_picker/image_picker_platform_interface/lib/src/types/types.dart index 7f2844230287..dad86c5d1ba1 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/types/types.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/types/types.dart @@ -3,6 +3,7 @@ // found in the LICENSE file. export 'camera_device.dart'; +export 'image_picker_options.dart'; export 'image_source.dart'; export 'lost_data_response.dart'; export 'picked_file/picked_file.dart'; diff --git a/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart b/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart index 292ac7c389c9..3c22f0fb4faf 100644 --- a/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart +++ b/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart @@ -1034,32 +1034,40 @@ void main() { await picker.getImageFromSource(source: ImageSource.camera); await picker.getImageFromSource( source: ImageSource.camera, - maxWidth: 10.0, + options: ImagePickerOptions(maxWidth: 10.0), ); await picker.getImageFromSource( source: ImageSource.camera, - maxHeight: 10.0, + options: ImagePickerOptions(maxHeight: 10.0), ); await picker.getImageFromSource( source: ImageSource.camera, - maxWidth: 10.0, - maxHeight: 20.0, + options: ImagePickerOptions( + maxWidth: 10.0, + maxHeight: 20.0, + ), ); await picker.getImageFromSource( source: ImageSource.camera, - maxWidth: 10.0, - imageQuality: 70, + options: ImagePickerOptions( + maxWidth: 10.0, + imageQuality: 70, + ), ); await picker.getImageFromSource( source: ImageSource.camera, - maxHeight: 10.0, - imageQuality: 70, + options: ImagePickerOptions( + maxHeight: 10.0, + imageQuality: 70, + ), ); await picker.getImageFromSource( source: ImageSource.camera, - maxWidth: 10.0, - maxHeight: 20.0, - imageQuality: 70, + options: ImagePickerOptions( + maxWidth: 10.0, + maxHeight: 20.0, + imageQuality: 70, + ), ); expect( @@ -1128,25 +1136,33 @@ void main() { test('does not accept a invalid imageQuality argument', () { expect( () => picker.getImageFromSource( - imageQuality: -1, source: ImageSource.gallery), + source: ImageSource.gallery, + options: ImagePickerOptions(imageQuality: -1), + ), throwsArgumentError, ); expect( () => picker.getImageFromSource( - imageQuality: 101, source: ImageSource.gallery), + source: ImageSource.gallery, + options: ImagePickerOptions(imageQuality: 101), + ), throwsArgumentError, ); expect( () => picker.getImageFromSource( - imageQuality: -1, source: ImageSource.camera), + source: ImageSource.camera, + options: ImagePickerOptions(imageQuality: -1), + ), throwsArgumentError, ); expect( () => picker.getImageFromSource( - imageQuality: 101, source: ImageSource.camera), + source: ImageSource.camera, + options: ImagePickerOptions(imageQuality: 101), + ), throwsArgumentError, ); }); @@ -1154,13 +1170,17 @@ void main() { test('does not accept a negative width or height argument', () { expect( () => picker.getImageFromSource( - source: ImageSource.camera, maxWidth: -1.0), + source: ImageSource.camera, + options: ImagePickerOptions(maxWidth: -1.0), + ), throwsArgumentError, ); expect( () => picker.getImageFromSource( - source: ImageSource.camera, maxHeight: -1.0), + source: ImageSource.camera, + options: ImagePickerOptions(maxHeight: -1.0), + ), throwsArgumentError, ); }); @@ -1195,8 +1215,11 @@ void main() { test('camera position can set to front', () async { await picker.getImageFromSource( - source: ImageSource.camera, - preferredCameraDevice: CameraDevice.front); + source: ImageSource.camera, + options: ImagePickerOptions( + preferredCameraDevice: CameraDevice.front, + ), + ); expect( log, @@ -1215,7 +1238,9 @@ void main() { test('passes the full metadata argument correctly', () async { await picker.getImageFromSource( - source: ImageSource.camera, requestFullMetadata: false); + source: ImageSource.camera, + options: ImagePickerOptions(requestFullMetadata: false), + ); expect( log, From 0f436539322f030260d71fbdf2fafc3d456397a5 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Fri, 8 Apr 2022 10:49:31 +0200 Subject: [PATCH 19/36] Added missing license comment --- .../lib/src/types/image_picker_options.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart b/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart index 38612876bfbc..323357533ba9 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.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:image_picker_platform_interface/src/types/types.dart'; /// Specifies options for picking a single image from the device's camera or gallery. From c1fc9da480838a72de877202b365cdc05290aa4e Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Fri, 15 Apr 2022 08:34:30 +0200 Subject: [PATCH 20/36] PR remarks --- .../ios/Runner.xcodeproj/project.pbxproj | 2 +- .../image_picker_ios/example/pubspec.yaml | 6 ++++ .../lib/src/types/image_picker_options.dart | 28 ++++++++++--------- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj index 589858f39019..5d4ff45c68cf 100644 --- a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 50; objects = { /* Begin PBXBuildFile section */ diff --git a/packages/image_picker/image_picker_ios/example/pubspec.yaml b/packages/image_picker/image_picker_ios/example/pubspec.yaml index a47893d7687f..1aaf1da668ee 100755 --- a/packages/image_picker/image_picker_ios/example/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/example/pubspec.yaml @@ -27,3 +27,9 @@ dev_dependencies: flutter: uses-material-design: true + +# FOR TESTING ONLY. DO NOT MERGE. +dependency_overrides: + image_picker_platform_interface: + path: + ../../image_picker_platform_interface \ No newline at end of file diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart b/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart index 323357533ba9..9d6ae5701077 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart @@ -24,23 +24,25 @@ class ImagePickerOptions { /// Otherwise the image will be returned at its original height. final double? maxHeight; - /// Modifies the quality of the image, ranging from 0-100 - /// where 100 is the original/max quality. If `imageQuality` is null, the image with - /// the original quality will be returned. Compression is only supported for certain - /// image types such as JPEG. If compression is not supported for the image that is picked, - /// a warning message will be logged. + /// Modifies the quality of the image, ranging from 0-100 where 100 is the original/max + /// quality. If `imageQuality` is null, the image with the originalquality will + /// be returned. Compression is only supported for certain image types such as + /// JPEG. If compression is not supported for the image that is picked, a warning + /// message will be logged. final int? imageQuality; /// Used to specify the camera to use when the `source` is [ImageSource.camera]. - /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. It is also ignored if the chosen camera is not supported on the device. - /// Defaults to [CameraDevice.rear]. Note that Android has no documented parameter for an intent to specify if - /// the front or rear camera should be opened, this function is not guaranteed - /// to work on an Android device. + /// The `preferredCameraDevice` is ignored when `source` is [ImageSource.gallery]. + /// It is also ignored if the chosen camera is not supported on the device. + /// Defaults to [CameraDevice.rear]. Note that Android has no documented parameter + /// for an intent to specify if the front or rear camera should be opened, this + /// function is not guaranteed to work on an Android device. final CameraDevice preferredCameraDevice; - /// `requestFullMetadata` defaults to `true`, so the plugin tries to get the full image metadata which may require - /// extra permission requests on certain platforms. - /// If `requestFullMetadata` is set to `false`, the plugin fetches the image in a way that reduces permission requests - /// from the platform (e.g. on iOS the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). + /// `requestFullMetadata` defaults to `true`, so the plugin tries to get the + /// full image metadata which may require extra permission requests on certain platforms. + /// If `requestFullMetadata` is set to `false`, the plugin fetches the image + /// in a way that reduces permission requests from the platform (e.g. on iOS + /// the plugin won’t ask for the `NSPhotoLibraryUsageDescription` permission). final bool requestFullMetadata; } From 7f958a69efbf0295e805c2cfe3fc98dfb6af0549 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Fri, 15 Apr 2022 08:35:44 +0200 Subject: [PATCH 21/36] pbxproj version revert --- .../image_picker/example/ios/Runner.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj index 5d4ff45c68cf..589858f39019 100644 --- a/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/image_picker/image_picker/example/ios/Runner.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 46; objects = { /* Begin PBXBuildFile section */ From c825d09065082bd2210aa6eb25369772f4b72664 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Wed, 27 Apr 2022 15:08:48 +0200 Subject: [PATCH 22/36] PR remarks --- .../ios/RunnerTests/ImagePickerPluginTests.m | 2 +- .../ios/Classes/FLTImagePickerPlugin.m | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m index 9183d7b849f8..ebb8851054bc 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -190,7 +190,7 @@ - (void)testPickImageWithoutFullMetadataPreiOS14 { FlutterMethodCall *call = [FlutterMethodCall methodCallWithMethodName:@"pickImage" arguments:@{ @"source" : @(1), - @"requestFullMetadata" : @(false), + @"requestFullMetadata" : @(NO), }]; [plugin handleMethodCall:call diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m index 34011490d622..e416bc2072cc 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m @@ -133,8 +133,8 @@ - (void)pickImageWithPHPicker:(int)maxImagesAllowed API_AVAILABLE(ios(14)) { self.maxImagesAllowed = maxImagesAllowed; - BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; - if (usePHAsset) { + BOOL requestFullMetadata = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + if (requestFullMetadata) { [self checkPhotoAuthorizationForAccessLevel]; } else { [self showPhotoLibraryWithPHPicker:_pickerViewController]; @@ -147,7 +147,7 @@ - (void)launchUIImagePickerWithSource:(int)imageSource { imagePickerController.delegate = self; imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ]; - BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + BOOL requestFullMetadata = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; self.maxImagesAllowed = 1; switch (imageSource) { @@ -156,7 +156,7 @@ - (void)launchUIImagePickerWithSource:(int)imageSource { break; case SOURCE_GALLERY: if (@available(iOS 11, *)) { - if (usePHAsset) { + if (requestFullMetadata) { [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; } else { [self showPhotoLibraryWithImagePicker:imagePickerController]; @@ -220,13 +220,13 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result imagePickerController.videoMaximumDuration = max; } - BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + BOOL requestFullMetadata = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; switch (imageSource) { case SOURCE_CAMERA: [self checkCameraAuthorizationWithImagePicker:imagePickerController]; break; case SOURCE_GALLERY: - if (usePHAsset) { + if (requestFullMetadata) { [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; } else { [self showPhotoLibraryWithImagePicker:imagePickerController]; @@ -534,10 +534,11 @@ - (void)imagePickerController:(UIImagePickerController *)picker NSNumber *maxHeight = GetNullableValueForKey(_arguments, @"maxHeight"); NSNumber *imageQuality = GetNullableValueForKey(_arguments, @"imageQuality"); NSNumber *desiredImageQuality = [self getDesiredImageQuality:imageQuality]; - BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + BOOL requestFullMetadata = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; PHAsset *originalAsset; - if (usePHAsset) { + if (requestFullMetadata) { + // Full metadata are available only in PHAsset, which requires gallery permission originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; } From 0120c47dc7dee3b17c69e1df4eace1764a0c1280 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Wed, 27 Apr 2022 15:20:23 +0200 Subject: [PATCH 23/36] Resolved merge conflicts Unified changelogs and package versions in common and iOS package --- packages/image_picker/image_picker/pubspec.yaml | 2 +- packages/image_picker/image_picker_ios/CHANGELOG.md | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml index 8d65ef0506a3..61f6034ca2b5 100755 --- a/packages/image_picker/image_picker/pubspec.yaml +++ b/packages/image_picker/image_picker/pubspec.yaml @@ -3,7 +3,7 @@ description: Flutter plugin for selecting images from the Android and iOS image library, and taking new pictures with the camera. repository: https://github.com/flutter/plugins/tree/main/packages/image_picker/image_picker issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 -version: 0.8.5 +version: 0.8.6 environment: sdk: ">=2.14.0 <3.0.0" diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md index 3380d14418c2..b140dab877e8 100644 --- a/packages/image_picker/image_picker_ios/CHANGELOG.md +++ b/packages/image_picker/image_picker_ios/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.6 + +* Adds `requestFullMetadata` option to `pickImage`, so images on iOS can be picked without `Photo Library Usage` permission. + ## 0.8.5 * Switches to an in-package method channel based on Pigeon. From 0827c802c73d317463c37c5b252316d7489e4266 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Wed, 27 Apr 2022 18:25:15 +0200 Subject: [PATCH 24/36] Generated Pigeon files for new API and metadata flag --- .../ios/Classes/FLTImagePickerPlugin.m | 20 ++++++++++--------- .../ios/Classes/FLTImagePickerPlugin_Test.h | 3 +++ .../image_picker_ios/ios/Classes/messages.g.h | 3 ++- .../image_picker_ios/ios/Classes/messages.g.m | 9 ++++++--- .../lib/image_picker_ios.dart | 19 ++++++++++++++++++ .../image_picker_ios/lib/src/messages.g.dart | 13 +++++++----- .../image_picker_ios/pigeons/messages.dart | 6 +++--- .../image_picker_ios/test/test_api.dart | 16 ++++++++------- 8 files changed, 61 insertions(+), 28 deletions(-) diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m index c55b3d14ac92..533079eccf19 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m @@ -119,7 +119,7 @@ - (void)launchPHPickerWithContext:(nonnull FLTImagePickerMethodCallContext *)con _pickerViewController.presentationController.delegate = self; self.callContext = context; - BOOL requestFullMetadata = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + BOOL requestFullMetadata = context.requestFullMetadata; if (requestFullMetadata) { [self checkPhotoAuthorizationForAccessLevel]; } else { @@ -135,7 +135,7 @@ - (void)launchUIImagePickerWithSource:(nonnull FLTSourceSpecification *)source imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ]; self.callContext = context; - BOOL requestFullMetadata = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + BOOL requestFullMetadata = context.requestFullMetadata; switch (source.type) { case FLTSourceTypeCamera: @@ -167,6 +167,7 @@ - (void)launchUIImagePickerWithSource:(nonnull FLTSourceSpecification *)source - (void)pickImageWithSource:(nonnull FLTSourceSpecification *)source maxSize:(nonnull FLTMaxSize *)maxSize quality:(nullable NSNumber *)imageQuality + requestFullMetadata:(NSNumber *)requestFullMetadata completion: (nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { [self cancelInProgressCall]; @@ -182,6 +183,7 @@ - (void)pickImageWithSource:(nonnull FLTSourceSpecification *)source context.maxSize = maxSize; context.imageQuality = imageQuality; context.maxImageCount = 1; + context.requestFullMetadata = [requestFullMetadata boolValue]; if (source.type == FLTSourceTypeGallery) { // Capture is not possible with PHPicker if (@available(iOS 14, *)) { @@ -243,7 +245,7 @@ - (void)pickVideoWithSource:(nonnull FLTSourceSpecification *)source } self.callContext = context; - BOOL requestFullMetadata = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + BOOL requestFullMetadata = context.requestFullMetadata; switch (source.type) { case FLTSourceTypeCamera: @@ -251,11 +253,11 @@ - (void)pickVideoWithSource:(nonnull FLTSourceSpecification *)source camera:[self cameraDeviceForSource:source]]; break; case FLTSourceTypeGallery: - if (requestFullMetadata) { - [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; - } else { - [self showPhotoLibraryWithImagePicker:imagePickerController]; - } + if (requestFullMetadata) { + [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; + } else { + [self showPhotoLibraryWithImagePicker:imagePickerController]; + } break; default: [self sendCallResultWithError:[FlutterError errorWithCode:@"invalid_source" @@ -574,7 +576,7 @@ - (void)imagePickerController:(UIImagePickerController *)picker NSNumber *maxHeight = self.callContext.maxSize.height; NSNumber *imageQuality = self.callContext.imageQuality; NSNumber *desiredImageQuality = [self getDesiredImageQuality:imageQuality]; - BOOL requestFullMetadata = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; + BOOL requestFullMetadata = _callContext.requestFullMetadata; PHAsset *originalAsset; if (requestFullMetadata) { diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin_Test.h b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin_Test.h index 2c4167746c8e..174b1f7d7ff9 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin_Test.h +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin_Test.h @@ -46,6 +46,9 @@ typedef void (^FlutterResultAdapter)(NSArray *_Nullable, FlutterErro /** Maximum number of images to select. 0 indicates no maximum. */ @property(nonatomic, assign) int maxImageCount; +/** Whether the image should be picked with full metadata (requires gallery permissions) */ +@property(nonatomic, assign) BOOL requestFullMetadata; + @end #pragma mark - diff --git a/packages/image_picker/image_picker_ios/ios/Classes/messages.g.h b/packages/image_picker/image_picker_ios/ios/Classes/messages.g.h index 310165f72f4f..134c046ca0d0 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/messages.g.h +++ b/packages/image_picker/image_picker_ios/ios/Classes/messages.g.h @@ -1,7 +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. -// Autogenerated from Pigeon (v3.0.2), do not edit directly. +// Autogenerated from Pigeon (v3.0.3), do not edit directly. // See also: https://pub.dev/packages/pigeon #import @protocol FlutterBinaryMessenger; @@ -45,6 +45,7 @@ NSObject *FLTImagePickerApiGetCodec(void); - (void)pickImageWithSource:(FLTSourceSpecification *)source maxSize:(FLTMaxSize *)maxSize quality:(nullable NSNumber *)imageQuality + requestFullMetadata:(NSNumber *)requestFullMetadata completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)pickMultiImageWithMaxSize:(FLTMaxSize *)maxSize quality:(nullable NSNumber *)imageQuality diff --git a/packages/image_picker/image_picker_ios/ios/Classes/messages.g.m b/packages/image_picker/image_picker_ios/ios/Classes/messages.g.m index 6c91c0ab264f..ab001e7adc06 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/messages.g.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/messages.g.m @@ -1,7 +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. -// Autogenerated from Pigeon (v3.0.2), do not edit directly. +// Autogenerated from Pigeon (v3.0.3), do not edit directly. // See also: https://pub.dev/packages/pigeon #import "messages.g.h" #import @@ -144,18 +144,21 @@ void FLTImagePickerApiSetup(id binaryMessenger, binaryMessenger:binaryMessenger codec:FLTImagePickerApiGetCodec()]; if (api) { - NSCAssert([api respondsToSelector:@selector(pickImageWithSource:maxSize:quality:completion:)], + NSCAssert([api respondsToSelector:@selector + (pickImageWithSource:maxSize:quality:requestFullMetadata:completion:)], @"FLTImagePickerApi api (%@) doesn't respond to " - @"@selector(pickImageWithSource:maxSize:quality:completion:)", + @"@selector(pickImageWithSource:maxSize:quality:requestFullMetadata:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; FLTSourceSpecification *arg_source = GetNullableObjectAtIndex(args, 0); FLTMaxSize *arg_maxSize = GetNullableObjectAtIndex(args, 1); NSNumber *arg_imageQuality = GetNullableObjectAtIndex(args, 2); + NSNumber *arg_requestFullMetadata = GetNullableObjectAtIndex(args, 3); [api pickImageWithSource:arg_source maxSize:arg_maxSize quality:arg_imageQuality + requestFullMetadata:arg_requestFullMetadata completion:^(NSString *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; diff --git a/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart b/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart index 3d1413cf0cce..9c5b96c10a0c 100644 --- a/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart +++ b/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart @@ -59,6 +59,23 @@ class ImagePickerIOS extends ImagePickerPlatform { return path != null ? PickedFile(path) : null; } + @override + Future getImageFromSource({ + required ImageSource source, + ImagePickerOptions? options, + }) async { + final ImagePickerOptions pickerOptions = options ?? ImagePickerOptions(); + final String? path = await _pickImageAsPath( + source: source, + maxWidth: pickerOptions.maxWidth, + maxHeight: pickerOptions.maxHeight, + imageQuality: pickerOptions.imageQuality, + preferredCameraDevice: pickerOptions.preferredCameraDevice, + requestFullMetadata: pickerOptions.requestFullMetadata, + ); + return path != null ? XFile(path) : null; + } + @override Future?> pickMultiImage({ double? maxWidth, @@ -108,6 +125,7 @@ class ImagePickerIOS extends ImagePickerPlatform { double? maxHeight, int? imageQuality, CameraDevice preferredCameraDevice = CameraDevice.rear, + bool requestFullMetadata = true, }) { if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) { throw ArgumentError.value( @@ -128,6 +146,7 @@ class ImagePickerIOS extends ImagePickerPlatform { camera: _convertCamera(preferredCameraDevice)), MaxSize(width: maxWidth, height: maxHeight), imageQuality, + requestFullMetadata, ); } diff --git a/packages/image_picker/image_picker_ios/lib/src/messages.g.dart b/packages/image_picker/image_picker_ios/lib/src/messages.g.dart index 0c5859e80ac9..70509b062fd6 100644 --- a/packages/image_picker/image_picker_ios/lib/src/messages.g.dart +++ b/packages/image_picker/image_picker_ios/lib/src/messages.g.dart @@ -1,7 +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. -// Autogenerated from Pigeon (v3.0.2), do not edit directly. +// Autogenerated from Pigeon (v3.0.3), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name // @dart = 2.12 @@ -115,13 +115,16 @@ class ImagePickerApi { static const MessageCodec codec = _ImagePickerApiCodec(); Future pickImage(SourceSpecification arg_source, MaxSize arg_maxSize, - int? arg_imageQuality) async { + int? arg_imageQuality, bool arg_requestFullMetadata) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.ImagePickerApi.pickImage', codec, binaryMessenger: _binaryMessenger); - final Map? replyMap = - await channel.send([arg_source, arg_maxSize, arg_imageQuality]) - as Map?; + final Map? replyMap = await channel.send([ + arg_source, + arg_maxSize, + arg_imageQuality, + arg_requestFullMetadata + ]) as Map?; if (replyMap == null) { throw PlatformException( code: 'channel-error', diff --git a/packages/image_picker/image_picker_ios/pigeons/messages.dart b/packages/image_picker/image_picker_ios/pigeons/messages.dart index 94ac034606e9..49cb75fd0edd 100644 --- a/packages/image_picker/image_picker_ios/pigeons/messages.dart +++ b/packages/image_picker/image_picker_ios/pigeons/messages.dart @@ -35,9 +35,9 @@ class SourceSpecification { @HostApi(dartHostTestHandler: 'TestHostImagePickerApi') abstract class ImagePickerApi { @async - @ObjCSelector('pickImageWithSource:maxSize:quality:') - String? pickImage( - SourceSpecification source, MaxSize maxSize, int? imageQuality); + @ObjCSelector('pickImageWithSource:maxSize:quality:requestFullMetadata:') + String? pickImage(SourceSpecification source, MaxSize maxSize, + int? imageQuality, bool requestFullMetadata); @async @ObjCSelector('pickMultiImageWithMaxSize:quality:') List? pickMultiImage(MaxSize maxSize, int? imageQuality); diff --git a/packages/image_picker/image_picker_ios/test/test_api.dart b/packages/image_picker/image_picker_ios/test/test_api.dart index 1f76e871521d..ecece08b533d 100644 --- a/packages/image_picker/image_picker_ios/test/test_api.dart +++ b/packages/image_picker/image_picker_ios/test/test_api.dart @@ -1,7 +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. -// Autogenerated from Pigeon (v3.0.2), do not edit directly. +// Autogenerated from Pigeon (v3.0.3), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis // ignore_for_file: avoid_relative_lib_imports @@ -12,8 +12,7 @@ import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -// Manually changed due to https://github.com/flutter/flutter/issues/97744 -import 'package:image_picker_ios/src/messages.g.dart'; +import '../lib/src/messages.g.dart'; class _TestHostImagePickerApiCodec extends StandardMessageCodec { const _TestHostImagePickerApiCodec(); @@ -48,8 +47,8 @@ class _TestHostImagePickerApiCodec extends StandardMessageCodec { abstract class TestHostImagePickerApi { static const MessageCodec codec = _TestHostImagePickerApiCodec(); - Future pickImage( - SourceSpecification source, MaxSize maxSize, int? imageQuality); + Future pickImage(SourceSpecification source, MaxSize maxSize, + int? imageQuality, bool requestFullMetadata); Future?> pickMultiImage(MaxSize maxSize, int? imageQuality); Future pickVideo( SourceSpecification source, int? maxDurationSeconds); @@ -74,8 +73,11 @@ abstract class TestHostImagePickerApi { assert(arg_maxSize != null, 'Argument for dev.flutter.pigeon.ImagePickerApi.pickImage was null, expected non-null MaxSize.'); final int? arg_imageQuality = (args[2] as int?); - final String? output = - await api.pickImage(arg_source!, arg_maxSize!, arg_imageQuality); + final bool? arg_requestFullMetadata = (args[3] as bool?); + assert(arg_requestFullMetadata != null, + 'Argument for dev.flutter.pigeon.ImagePickerApi.pickImage was null, expected non-null bool.'); + final String? output = await api.pickImage(arg_source!, arg_maxSize!, + arg_imageQuality, arg_requestFullMetadata!); return {'result': output}; }); } From 994e45ff32a1476d61dd8a4383f9814dd37a72cd Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 28 Apr 2022 09:40:42 +0200 Subject: [PATCH 25/36] Switched to use options object in private picking method --- .../lib/image_picker_ios.dart | 42 +++++++++---------- .../test/image_picker_ios_test.dart | 7 +++- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart b/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart index 9c5b96c10a0c..7c7105b67ebd 100644 --- a/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart +++ b/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart @@ -51,10 +51,12 @@ class ImagePickerIOS extends ImagePickerPlatform { }) async { final String? path = await _pickImageAsPath( source: source, - maxWidth: maxWidth, - maxHeight: maxHeight, - imageQuality: imageQuality, - preferredCameraDevice: preferredCameraDevice, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice, + ), ); return path != null ? PickedFile(path) : null; } @@ -64,14 +66,9 @@ class ImagePickerIOS extends ImagePickerPlatform { required ImageSource source, ImagePickerOptions? options, }) async { - final ImagePickerOptions pickerOptions = options ?? ImagePickerOptions(); final String? path = await _pickImageAsPath( source: source, - maxWidth: pickerOptions.maxWidth, - maxHeight: pickerOptions.maxHeight, - imageQuality: pickerOptions.imageQuality, - preferredCameraDevice: pickerOptions.preferredCameraDevice, - requestFullMetadata: pickerOptions.requestFullMetadata, + options: options, ); return path != null ? XFile(path) : null; } @@ -121,21 +118,22 @@ class ImagePickerIOS extends ImagePickerPlatform { Future _pickImageAsPath({ required ImageSource source, - double? maxWidth, - double? maxHeight, - int? imageQuality, - CameraDevice preferredCameraDevice = CameraDevice.rear, - bool requestFullMetadata = true, + ImagePickerOptions? options, }) { + final ImagePickerOptions pickerOptions = options ?? ImagePickerOptions(); + + final int? imageQuality = pickerOptions.imageQuality; if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) { throw ArgumentError.value( imageQuality, 'imageQuality', 'must be between 0 and 100'); } + final double? maxWidth = pickerOptions.maxWidth; if (maxWidth != null && maxWidth < 0) { throw ArgumentError.value(maxWidth, 'maxWidth', 'cannot be negative'); } + final double? maxHeight = pickerOptions.maxHeight; if (maxHeight != null && maxHeight < 0) { throw ArgumentError.value(maxHeight, 'maxHeight', 'cannot be negative'); } @@ -143,10 +141,10 @@ class ImagePickerIOS extends ImagePickerPlatform { return _hostApi.pickImage( SourceSpecification( type: _convertSource(source), - camera: _convertCamera(preferredCameraDevice)), + camera: _convertCamera(pickerOptions.preferredCameraDevice)), MaxSize(width: maxWidth, height: maxHeight), imageQuality, - requestFullMetadata, + pickerOptions.requestFullMetadata, ); } @@ -186,10 +184,12 @@ class ImagePickerIOS extends ImagePickerPlatform { }) async { final String? path = await _pickImageAsPath( source: source, - maxWidth: maxWidth, - maxHeight: maxHeight, - imageQuality: imageQuality, - preferredCameraDevice: preferredCameraDevice, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: imageQuality, + preferredCameraDevice: preferredCameraDevice, + ), ); return path != null ? XFile(path) : null; } diff --git a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart index 09517f1ef96b..5639e93fbd12 100644 --- a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart +++ b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart @@ -39,7 +39,11 @@ class _ApiLogger implements TestHostImagePickerApi { @override Future pickImage( - SourceSpecification source, MaxSize maxSize, int? imageQuality) async { + SourceSpecification source, + MaxSize maxSize, + int? imageQuality, + bool requestFullMetadata, + ) async { // Flatten arguments for easy comparison. calls.add(_LoggedMethodCall('pickImage', arguments: { 'source': source.type, @@ -47,6 +51,7 @@ class _ApiLogger implements TestHostImagePickerApi { 'maxWidth': maxSize.width, 'maxHeight': maxSize.height, 'imageQuality': imageQuality, + 'requestFullMetadata': requestFullMetadata, })); return returnValue as String?; } From 933254e997575cbd88b7d02dbb6c4aadec62905f Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 28 Apr 2022 10:13:35 +0200 Subject: [PATCH 26/36] Fixed failing unit tests --- .../test/image_picker_ios_test.dart | 58 +++++++++++++------ .../image_picker_ios/test/test_api.dart | 3 +- 2 files changed, 42 insertions(+), 19 deletions(-) diff --git a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart index 5639e93fbd12..3a88afe9e04e 100644 --- a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart +++ b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart @@ -108,14 +108,16 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.gallery, 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), ], ); @@ -161,49 +163,56 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': 70, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': 70, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': 70, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), ], ); @@ -262,6 +271,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), ], ); @@ -281,6 +291,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': SourceCamera.front, + 'requestFullMetadata': true, }), ], ); @@ -529,14 +540,16 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.gallery, 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), ], ); @@ -582,49 +595,56 @@ void main() { 'maxWidth': null, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': null, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': 10.0, 'maxHeight': null, 'imageQuality': 70, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': null, 'maxHeight': 10.0, 'imageQuality': 70, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), const _LoggedMethodCall('pickImage', arguments: { 'source': SourceType.camera, 'maxWidth': 10.0, 'maxHeight': 20.0, 'imageQuality': 70, - 'cameraDevice': SourceCamera.rear + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), ], ); @@ -683,6 +703,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, }), ], ); @@ -702,6 +723,7 @@ void main() { 'maxHeight': null, 'imageQuality': null, 'cameraDevice': SourceCamera.front, + 'requestFullMetadata': true, }), ], ); diff --git a/packages/image_picker/image_picker_ios/test/test_api.dart b/packages/image_picker/image_picker_ios/test/test_api.dart index ecece08b533d..60976104ac03 100644 --- a/packages/image_picker/image_picker_ios/test/test_api.dart +++ b/packages/image_picker/image_picker_ios/test/test_api.dart @@ -11,8 +11,9 @@ import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:image_picker_ios/src/messages.g.dart'; -import '../lib/src/messages.g.dart'; +// import '../lib/src/messages.g.dart'; class _TestHostImagePickerApiCodec extends StandardMessageCodec { const _TestHostImagePickerApiCodec(); From 66f14b23ee3d891d853347f5326297de8568780a Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 28 Apr 2022 10:22:19 +0200 Subject: [PATCH 27/36] Added missing tests for a new method and request full metadata parameter --- .../test/image_picker_ios_test.dart | 271 ++++++++++++++++++ 1 file changed, 271 insertions(+) diff --git a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart index 3a88afe9e04e..8f6992549519 100644 --- a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart +++ b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart @@ -961,4 +961,275 @@ void main() { ); }); }); + + group('#getImageFromSource', () { + test('passes the image source argument correctly', () async { + await picker.getImageFromSource(source: ImageSource.camera); + await picker.getImageFromSource(source: ImageSource.gallery); + + expect( + log.calls, + <_LoggedMethodCall>[ + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.gallery, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + ], + ); + }); + + test('passes the width and height arguments correctly', () async { + await picker.getImageFromSource(source: ImageSource.camera); + await picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions(maxWidth: 10.0), + ); + await picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions(maxHeight: 10.0), + ); + await picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions( + maxWidth: 10.0, + maxHeight: 20.0, + ), + ); + await picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions( + maxWidth: 10.0, + imageQuality: 70, + ), + ); + await picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions( + maxHeight: 10.0, + imageQuality: 70, + ), + ); + await picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions( + maxWidth: 10.0, + maxHeight: 20.0, + imageQuality: 70, + ), + ); + + expect( + log.calls, + <_LoggedMethodCall>[ + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': 10.0, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': null, + 'maxHeight': 10.0, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': 10.0, + 'maxHeight': 20.0, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': 10.0, + 'maxHeight': null, + 'imageQuality': 70, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': null, + 'maxHeight': 10.0, + 'imageQuality': 70, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': 10.0, + 'maxHeight': 20.0, + 'imageQuality': 70, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + ], + ); + }); + + test('does not accept a invalid imageQuality argument', () { + expect( + () => picker.getImageFromSource( + source: ImageSource.gallery, + options: ImagePickerOptions(imageQuality: -1), + ), + throwsArgumentError, + ); + + expect( + () => picker.getImageFromSource( + source: ImageSource.gallery, + options: ImagePickerOptions(imageQuality: 101), + ), + throwsArgumentError, + ); + + expect( + () => picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions(imageQuality: -1), + ), + throwsArgumentError, + ); + + expect( + () => picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions(imageQuality: 101), + ), + throwsArgumentError, + ); + }); + + test('does not accept a negative width or height argument', () { + expect( + () => picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions(maxWidth: -1.0), + ), + throwsArgumentError, + ); + + expect( + () => picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions(maxHeight: -1.0), + ), + throwsArgumentError, + ); + }); + + test('handles a null image path response gracefully', () async { + log.returnValue = null; + + expect( + await picker.getImageFromSource(source: ImageSource.gallery), isNull); + expect( + await picker.getImageFromSource(source: ImageSource.camera), isNull); + }); + + test('camera position defaults to back', () async { + await picker.getImageFromSource(source: ImageSource.camera); + + expect( + log.calls, + <_LoggedMethodCall>[ + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + ], + ); + }); + + test('camera position can set to front', () async { + await picker.getImageFromSource( + source: ImageSource.camera, + options: ImagePickerOptions(preferredCameraDevice: CameraDevice.front), + ); + + expect( + log.calls, + <_LoggedMethodCall>[ + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.camera, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': SourceCamera.front, + 'requestFullMetadata': true, + }), + ], + ); + }); + + test('Request full metadata argument defaults to true', () async { + await picker.getImageFromSource(source: ImageSource.gallery); + + expect( + log.calls, + <_LoggedMethodCall>[ + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.gallery, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': true, + }), + ], + ); + }); + + test('passes the request full metadata argument correctly', () async { + await picker.getImageFromSource( + source: ImageSource.gallery, + options: ImagePickerOptions(requestFullMetadata: false), + ); + + expect( + log.calls, + <_LoggedMethodCall>[ + const _LoggedMethodCall('pickImage', arguments: { + 'source': SourceType.gallery, + 'maxWidth': null, + 'maxHeight': null, + 'imageQuality': null, + 'cameraDevice': SourceCamera.rear, + 'requestFullMetadata': false, + }), + ], + ); + }); + }); } From 47098ec32b887fcccc97790b773de87d9d5c9fdf Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 28 Apr 2022 10:50:27 +0200 Subject: [PATCH 28/36] Fixed failing native tests --- .../example/ios/RunnerTests/ImagePickerPluginTests.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m index 809de2861b66..540f04157faf 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -54,6 +54,7 @@ - (void)testPluginPickImageDeviceBack { camera:FLTSourceCameraRear] maxSize:[[FLTMaxSize alloc] init] quality:nil + requestFullMetadata:@(YES) completion:^(NSString *_Nullable result, FlutterError *_Nullable error){ }]; @@ -86,6 +87,7 @@ - (void)testPluginPickImageDeviceFront { camera:FLTSourceCameraFront] maxSize:[[FLTMaxSize alloc] init] quality:nil + requestFullMetadata:@(YES) completion:^(NSString *_Nullable result, FlutterError *_Nullable error){ }]; @@ -212,6 +214,7 @@ - (void)testPluginPickImageDeviceCancelClickMultipleTimes { camera:FLTSourceCameraRear] maxSize:[[FLTMaxSize alloc] init] quality:nil + requestFullMetadata:@(YES) completion:^(NSString *_Nullable result, FlutterError *_Nullable error){ }]; From 0a811d8caf5093b722c6536d29325f7359e4c335 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Fri, 29 Apr 2022 09:43:34 +0200 Subject: [PATCH 29/36] PR remarks --- .../lib/image_picker_ios.dart | 19 ++++++------ .../test/image_picker_ios_test.dart | 29 ++++++++++--------- .../method_channel_image_picker.dart | 13 ++++----- .../image_picker_platform.dart | 11 ++++--- .../lib/src/types/image_picker_options.dart | 2 +- 5 files changed, 36 insertions(+), 38 deletions(-) diff --git a/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart b/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart index 7c7105b67ebd..c488874890ed 100644 --- a/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart +++ b/packages/image_picker/image_picker_ios/lib/image_picker_ios.dart @@ -64,7 +64,7 @@ class ImagePickerIOS extends ImagePickerPlatform { @override Future getImageFromSource({ required ImageSource source, - ImagePickerOptions? options, + ImagePickerOptions options = const ImagePickerOptions(), }) async { final String? path = await _pickImageAsPath( source: source, @@ -118,33 +118,32 @@ class ImagePickerIOS extends ImagePickerPlatform { Future _pickImageAsPath({ required ImageSource source, - ImagePickerOptions? options, + ImagePickerOptions options = const ImagePickerOptions(), }) { - final ImagePickerOptions pickerOptions = options ?? ImagePickerOptions(); - - final int? imageQuality = pickerOptions.imageQuality; + final int? imageQuality = options.imageQuality; if (imageQuality != null && (imageQuality < 0 || imageQuality > 100)) { throw ArgumentError.value( imageQuality, 'imageQuality', 'must be between 0 and 100'); } - final double? maxWidth = pickerOptions.maxWidth; + final double? maxWidth = options.maxWidth; if (maxWidth != null && maxWidth < 0) { throw ArgumentError.value(maxWidth, 'maxWidth', 'cannot be negative'); } - final double? maxHeight = pickerOptions.maxHeight; + final double? maxHeight = options.maxHeight; if (maxHeight != null && maxHeight < 0) { throw ArgumentError.value(maxHeight, 'maxHeight', 'cannot be negative'); } return _hostApi.pickImage( SourceSpecification( - type: _convertSource(source), - camera: _convertCamera(pickerOptions.preferredCameraDevice)), + type: _convertSource(source), + camera: _convertCamera(options.preferredCameraDevice), + ), MaxSize(width: maxWidth, height: maxHeight), imageQuality, - pickerOptions.requestFullMetadata, + options.requestFullMetadata, ); } diff --git a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart index 8f6992549519..14d1d0be99e6 100644 --- a/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart +++ b/packages/image_picker/image_picker_ios/test/image_picker_ios_test.dart @@ -994,36 +994,36 @@ void main() { await picker.getImageFromSource(source: ImageSource.camera); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(maxWidth: 10.0), + options: const ImagePickerOptions(maxWidth: 10.0), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(maxHeight: 10.0), + options: const ImagePickerOptions(maxHeight: 10.0), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( maxWidth: 10.0, maxHeight: 20.0, ), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( maxWidth: 10.0, imageQuality: 70, ), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( maxHeight: 10.0, imageQuality: 70, ), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( maxWidth: 10.0, maxHeight: 20.0, imageQuality: 70, @@ -1097,7 +1097,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.gallery, - options: ImagePickerOptions(imageQuality: -1), + options: const ImagePickerOptions(imageQuality: -1), ), throwsArgumentError, ); @@ -1105,7 +1105,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.gallery, - options: ImagePickerOptions(imageQuality: 101), + options: const ImagePickerOptions(imageQuality: 101), ), throwsArgumentError, ); @@ -1113,7 +1113,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(imageQuality: -1), + options: const ImagePickerOptions(imageQuality: -1), ), throwsArgumentError, ); @@ -1121,7 +1121,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(imageQuality: 101), + options: const ImagePickerOptions(imageQuality: 101), ), throwsArgumentError, ); @@ -1131,7 +1131,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(maxWidth: -1.0), + options: const ImagePickerOptions(maxWidth: -1.0), ), throwsArgumentError, ); @@ -1139,7 +1139,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(maxHeight: -1.0), + options: const ImagePickerOptions(maxHeight: -1.0), ), throwsArgumentError, ); @@ -1175,7 +1175,8 @@ void main() { test('camera position can set to front', () async { await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(preferredCameraDevice: CameraDevice.front), + options: + const ImagePickerOptions(preferredCameraDevice: CameraDevice.front), ); expect( @@ -1214,7 +1215,7 @@ void main() { test('passes the request full metadata argument correctly', () async { await picker.getImageFromSource( source: ImageSource.gallery, - options: ImagePickerOptions(requestFullMetadata: false), + options: const ImagePickerOptions(requestFullMetadata: false), ); expect( diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart index 6a5a6b69269d..ba5d60d7a677 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/method_channel/method_channel_image_picker.dart @@ -202,16 +202,15 @@ class MethodChannelImagePicker extends ImagePickerPlatform { @override Future getImageFromSource({ required ImageSource source, - ImagePickerOptions? options, + ImagePickerOptions options = const ImagePickerOptions(), }) async { final String? path = await _getImagePath( source: source, - maxHeight: options?.maxHeight, - maxWidth: options?.maxWidth, - imageQuality: options?.imageQuality, - preferredCameraDevice: - options?.preferredCameraDevice ?? CameraDevice.rear, - requestFullMetadata: options?.requestFullMetadata ?? true, + maxHeight: options.maxHeight, + maxWidth: options.maxWidth, + imageQuality: options.imageQuality, + preferredCameraDevice: options.preferredCameraDevice, + requestFullMetadata: options.requestFullMetadata, ); return path != null ? XFile(path) : null; } diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart index f96fadd62316..4efbac7793aa 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/platform_interface/image_picker_platform.dart @@ -271,15 +271,14 @@ abstract class ImagePickerPlatform extends PlatformInterface { /// If no images were picked, the return value is null. Future getImageFromSource({ required ImageSource source, - ImagePickerOptions? options, + ImagePickerOptions options = const ImagePickerOptions(), }) { return getImage( source: source, - maxHeight: options?.maxHeight, - maxWidth: options?.maxWidth, - imageQuality: options?.imageQuality, - preferredCameraDevice: - options?.preferredCameraDevice ?? CameraDevice.rear, + maxHeight: options.maxHeight, + maxWidth: options.maxWidth, + imageQuality: options.imageQuality, + preferredCameraDevice: options.preferredCameraDevice, ); } } diff --git a/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart b/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart index 9d6ae5701077..74ebdd349f91 100644 --- a/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart +++ b/packages/image_picker/image_picker_platform_interface/lib/src/types/image_picker_options.dart @@ -8,7 +8,7 @@ import 'package:image_picker_platform_interface/src/types/types.dart'; class ImagePickerOptions { /// Creates an instance with the given [maxHeight], [maxWidth], [imageQuality], /// [referredCameraDevice] and [requestFullMetadata]. Any of the params may be null. - ImagePickerOptions({ + const ImagePickerOptions({ this.maxHeight, this.maxWidth, this.imageQuality, From 0789a7bbeab30dc7a889b0bdca5e9cd527800a49 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Fri, 29 Apr 2022 09:54:00 +0200 Subject: [PATCH 30/36] Fixed linting --- .../new_method_channel_image_picker_test.dart | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart b/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart index 3c22f0fb4faf..aea3ed9fc5a0 100644 --- a/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart +++ b/packages/image_picker/image_picker_platform_interface/test/new_method_channel_image_picker_test.dart @@ -1034,36 +1034,36 @@ void main() { await picker.getImageFromSource(source: ImageSource.camera); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(maxWidth: 10.0), + options: const ImagePickerOptions(maxWidth: 10.0), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(maxHeight: 10.0), + options: const ImagePickerOptions(maxHeight: 10.0), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( maxWidth: 10.0, maxHeight: 20.0, ), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( maxWidth: 10.0, imageQuality: 70, ), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( maxHeight: 10.0, imageQuality: 70, ), ); await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( maxWidth: 10.0, maxHeight: 20.0, imageQuality: 70, @@ -1137,7 +1137,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.gallery, - options: ImagePickerOptions(imageQuality: -1), + options: const ImagePickerOptions(imageQuality: -1), ), throwsArgumentError, ); @@ -1145,7 +1145,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.gallery, - options: ImagePickerOptions(imageQuality: 101), + options: const ImagePickerOptions(imageQuality: 101), ), throwsArgumentError, ); @@ -1153,7 +1153,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(imageQuality: -1), + options: const ImagePickerOptions(imageQuality: -1), ), throwsArgumentError, ); @@ -1161,7 +1161,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(imageQuality: 101), + options: const ImagePickerOptions(imageQuality: 101), ), throwsArgumentError, ); @@ -1171,7 +1171,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(maxWidth: -1.0), + options: const ImagePickerOptions(maxWidth: -1.0), ), throwsArgumentError, ); @@ -1179,7 +1179,7 @@ void main() { expect( () => picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(maxHeight: -1.0), + options: const ImagePickerOptions(maxHeight: -1.0), ), throwsArgumentError, ); @@ -1216,7 +1216,7 @@ void main() { test('camera position can set to front', () async { await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions( + options: const ImagePickerOptions( preferredCameraDevice: CameraDevice.front, ), ); @@ -1239,7 +1239,7 @@ void main() { test('passes the full metadata argument correctly', () async { await picker.getImageFromSource( source: ImageSource.camera, - options: ImagePickerOptions(requestFullMetadata: false), + options: const ImagePickerOptions(requestFullMetadata: false), ); expect( From c5966d4647f974ab974eb9a5dbf26a715c32633a Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 12 May 2022 18:25:48 +0200 Subject: [PATCH 31/36] Removed dependency overrides --- packages/image_picker/image_picker_android/pubspec.yaml | 6 ------ packages/image_picker/image_picker_ios/example/pubspec.yaml | 6 ------ packages/image_picker/image_picker_ios/pubspec.yaml | 6 ------ 3 files changed, 18 deletions(-) diff --git a/packages/image_picker/image_picker_android/pubspec.yaml b/packages/image_picker/image_picker_android/pubspec.yaml index 8aa83d78cbec..dbeef9bed193 100755 --- a/packages/image_picker/image_picker_android/pubspec.yaml +++ b/packages/image_picker/image_picker_android/pubspec.yaml @@ -26,9 +26,3 @@ dev_dependencies: flutter_test: sdk: flutter mockito: ^5.0.0 - -# FOR TESTING ONLY. DO NOT MERGE. -dependency_overrides: - image_picker_platform_interface: - path: - ../image_picker_platform_interface \ No newline at end of file diff --git a/packages/image_picker/image_picker_ios/example/pubspec.yaml b/packages/image_picker/image_picker_ios/example/pubspec.yaml index 1aaf1da668ee..a47893d7687f 100755 --- a/packages/image_picker/image_picker_ios/example/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/example/pubspec.yaml @@ -27,9 +27,3 @@ dev_dependencies: flutter: uses-material-design: true - -# FOR TESTING ONLY. DO NOT MERGE. -dependency_overrides: - image_picker_platform_interface: - path: - ../../image_picker_platform_interface \ No newline at end of file diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml index f1b6c39334f9..2a001934d7c8 100755 --- a/packages/image_picker/image_picker_ios/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/pubspec.yaml @@ -26,9 +26,3 @@ dev_dependencies: sdk: flutter mockito: ^5.0.0 pigeon: ^3.0.2 - -# FOR TESTING ONLY. DO NOT MERGE. -dependency_overrides: - image_picker_platform_interface: - path: - ../image_picker_platform_interface \ No newline at end of file From 217237b67453165b02b6993d8e1af62c31517cce Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 12 May 2022 18:40:44 +0200 Subject: [PATCH 32/36] PR remarks --- .../example/ios/RunnerTests/ImagePickerPluginTests.m | 6 +++--- .../image_picker_ios/ios/Classes/FLTImagePickerPlugin.m | 4 ++-- .../image_picker/image_picker_ios/ios/Classes/messages.g.h | 2 +- .../image_picker/image_picker_ios/ios/Classes/messages.g.m | 6 +++--- .../image_picker/image_picker_ios/pigeons/messages.dart | 2 +- packages/image_picker/image_picker_ios/test/test_api.dart | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m index 540f04157faf..e2311904f286 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/ImagePickerPluginTests.m @@ -54,7 +54,7 @@ - (void)testPluginPickImageDeviceBack { camera:FLTSourceCameraRear] maxSize:[[FLTMaxSize alloc] init] quality:nil - requestFullMetadata:@(YES) + fullMetadata:@(YES) completion:^(NSString *_Nullable result, FlutterError *_Nullable error){ }]; @@ -87,7 +87,7 @@ - (void)testPluginPickImageDeviceFront { camera:FLTSourceCameraFront] maxSize:[[FLTMaxSize alloc] init] quality:nil - requestFullMetadata:@(YES) + fullMetadata:@(YES) completion:^(NSString *_Nullable result, FlutterError *_Nullable error){ }]; @@ -214,7 +214,7 @@ - (void)testPluginPickImageDeviceCancelClickMultipleTimes { camera:FLTSourceCameraRear] maxSize:[[FLTMaxSize alloc] init] quality:nil - requestFullMetadata:@(YES) + fullMetadata:@(YES) completion:^(NSString *_Nullable result, FlutterError *_Nullable error){ }]; diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m index 533079eccf19..6495725b04b3 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m @@ -167,7 +167,7 @@ - (void)launchUIImagePickerWithSource:(nonnull FLTSourceSpecification *)source - (void)pickImageWithSource:(nonnull FLTSourceSpecification *)source maxSize:(nonnull FLTMaxSize *)maxSize quality:(nullable NSNumber *)imageQuality - requestFullMetadata:(NSNumber *)requestFullMetadata + fullMetadata:(NSNumber *)fullMetadata completion: (nonnull void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { [self cancelInProgressCall]; @@ -183,7 +183,7 @@ - (void)pickImageWithSource:(nonnull FLTSourceSpecification *)source context.maxSize = maxSize; context.imageQuality = imageQuality; context.maxImageCount = 1; - context.requestFullMetadata = [requestFullMetadata boolValue]; + context.requestFullMetadata = [fullMetadata boolValue]; if (source.type == FLTSourceTypeGallery) { // Capture is not possible with PHPicker if (@available(iOS 14, *)) { diff --git a/packages/image_picker/image_picker_ios/ios/Classes/messages.g.h b/packages/image_picker/image_picker_ios/ios/Classes/messages.g.h index 134c046ca0d0..0d3e96c842bb 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/messages.g.h +++ b/packages/image_picker/image_picker_ios/ios/Classes/messages.g.h @@ -45,7 +45,7 @@ NSObject *FLTImagePickerApiGetCodec(void); - (void)pickImageWithSource:(FLTSourceSpecification *)source maxSize:(FLTMaxSize *)maxSize quality:(nullable NSNumber *)imageQuality - requestFullMetadata:(NSNumber *)requestFullMetadata + fullMetadata:(NSNumber *)requestFullMetadata completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion; - (void)pickMultiImageWithMaxSize:(FLTMaxSize *)maxSize quality:(nullable NSNumber *)imageQuality diff --git a/packages/image_picker/image_picker_ios/ios/Classes/messages.g.m b/packages/image_picker/image_picker_ios/ios/Classes/messages.g.m index ab001e7adc06..b13601480aea 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/messages.g.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/messages.g.m @@ -145,9 +145,9 @@ void FLTImagePickerApiSetup(id binaryMessenger, codec:FLTImagePickerApiGetCodec()]; if (api) { NSCAssert([api respondsToSelector:@selector - (pickImageWithSource:maxSize:quality:requestFullMetadata:completion:)], + (pickImageWithSource:maxSize:quality:fullMetadata:completion:)], @"FLTImagePickerApi api (%@) doesn't respond to " - @"@selector(pickImageWithSource:maxSize:quality:requestFullMetadata:completion:)", + @"@selector(pickImageWithSource:maxSize:quality:fullMetadata:completion:)", api); [channel setMessageHandler:^(id _Nullable message, FlutterReply callback) { NSArray *args = message; @@ -158,7 +158,7 @@ void FLTImagePickerApiSetup(id binaryMessenger, [api pickImageWithSource:arg_source maxSize:arg_maxSize quality:arg_imageQuality - requestFullMetadata:arg_requestFullMetadata + fullMetadata:arg_requestFullMetadata completion:^(NSString *_Nullable output, FlutterError *_Nullable error) { callback(wrapResult(output, error)); }]; diff --git a/packages/image_picker/image_picker_ios/pigeons/messages.dart b/packages/image_picker/image_picker_ios/pigeons/messages.dart index 49cb75fd0edd..f6bff83959cf 100644 --- a/packages/image_picker/image_picker_ios/pigeons/messages.dart +++ b/packages/image_picker/image_picker_ios/pigeons/messages.dart @@ -35,7 +35,7 @@ class SourceSpecification { @HostApi(dartHostTestHandler: 'TestHostImagePickerApi') abstract class ImagePickerApi { @async - @ObjCSelector('pickImageWithSource:maxSize:quality:requestFullMetadata:') + @ObjCSelector('pickImageWithSource:maxSize:quality:fullMetadata:') String? pickImage(SourceSpecification source, MaxSize maxSize, int? imageQuality, bool requestFullMetadata); @async diff --git a/packages/image_picker/image_picker_ios/test/test_api.dart b/packages/image_picker/image_picker_ios/test/test_api.dart index f9a365fd3d07..ecece08b533d 100644 --- a/packages/image_picker/image_picker_ios/test/test_api.dart +++ b/packages/image_picker/image_picker_ios/test/test_api.dart @@ -6,13 +6,13 @@ // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis // ignore_for_file: avoid_relative_lib_imports // @dart = 2.12 +import 'dart:async'; import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:image_picker_ios/src/messages.g.dart'; -// import '../lib/src/messages.g.dart'; +import '../lib/src/messages.g.dart'; class _TestHostImagePickerApiCodec extends StandardMessageCodec { const _TestHostImagePickerApiCodec(); From 7a4d25075f5d8594f9260e116c2129e4d7cf66ad Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 12 May 2022 18:50:48 +0200 Subject: [PATCH 33/36] Fixed linter warnings and failing tests --- packages/image_picker/image_picker_ios/test/test_api.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/image_picker/image_picker_ios/test/test_api.dart b/packages/image_picker/image_picker_ios/test/test_api.dart index ecece08b533d..8bc1be2ca002 100644 --- a/packages/image_picker/image_picker_ios/test/test_api.dart +++ b/packages/image_picker/image_picker_ios/test/test_api.dart @@ -6,13 +6,11 @@ // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis // ignore_for_file: avoid_relative_lib_imports // @dart = 2.12 -import 'dart:async'; import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; import 'package:flutter/services.dart'; import 'package:flutter_test/flutter_test.dart'; - -import '../lib/src/messages.g.dart'; +import 'package:image_picker_ios/src/messages.g.dart'; class _TestHostImagePickerApiCodec extends StandardMessageCodec { const _TestHostImagePickerApiCodec(); From 4ee04cba7d61aa3d6d1b5faffcf84a7c0bb5b55c Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 12 May 2022 18:51:49 +0200 Subject: [PATCH 34/36] Removed remaining dependency override --- packages/image_picker/image_picker/example/pubspec.yaml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/image_picker/image_picker/example/pubspec.yaml b/packages/image_picker/image_picker/example/pubspec.yaml index d4cec061a6cc..4fe823587398 100755 --- a/packages/image_picker/image_picker/example/pubspec.yaml +++ b/packages/image_picker/image_picker/example/pubspec.yaml @@ -28,9 +28,3 @@ dev_dependencies: flutter: uses-material-design: true - -# FOR TESTING ONLY. DO NOT MERGE. -dependency_overrides: - image_picker_platform_interface: - path: - ../../image_picker_platform_interface \ No newline at end of file From b3fb220e4617813833d96149087ef53c55dc3e07 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Fri, 13 May 2022 10:37:21 +0200 Subject: [PATCH 35/36] Enforcing proper platform interface version having required API changes --- packages/image_picker/image_picker/pubspec.yaml | 2 +- packages/image_picker/image_picker_android/example/pubspec.yaml | 2 +- packages/image_picker/image_picker_android/pubspec.yaml | 2 +- packages/image_picker/image_picker_ios/example/pubspec.yaml | 2 +- packages/image_picker/image_picker_ios/pubspec.yaml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/image_picker/image_picker/pubspec.yaml b/packages/image_picker/image_picker/pubspec.yaml index 375e72807a75..5c95e98f7e51 100755 --- a/packages/image_picker/image_picker/pubspec.yaml +++ b/packages/image_picker/image_picker/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: image_picker_android: ^0.8.4+11 image_picker_for_web: ^2.1.0 image_picker_ios: ^0.8.4+11 - image_picker_platform_interface: ^2.3.0 + image_picker_platform_interface: ^2.5.0 dev_dependencies: flutter_test: diff --git a/packages/image_picker/image_picker_android/example/pubspec.yaml b/packages/image_picker/image_picker_android/example/pubspec.yaml index 0d88ae139c71..ad6cecaa8575 100755 --- a/packages/image_picker/image_picker_android/example/pubspec.yaml +++ b/packages/image_picker/image_picker_android/example/pubspec.yaml @@ -17,7 +17,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: ../ - image_picker_platform_interface: ^2.3.0 + image_picker_platform_interface: ^2.5.0 video_player: ^2.1.4 dev_dependencies: diff --git a/packages/image_picker/image_picker_android/pubspec.yaml b/packages/image_picker/image_picker_android/pubspec.yaml index 095534654ac5..694de3bbf29b 100755 --- a/packages/image_picker/image_picker_android/pubspec.yaml +++ b/packages/image_picker/image_picker_android/pubspec.yaml @@ -20,7 +20,7 @@ dependencies: flutter: sdk: flutter flutter_plugin_android_lifecycle: ^2.0.1 - image_picker_platform_interface: ^2.3.0 + image_picker_platform_interface: ^2.5.0 dev_dependencies: flutter_test: diff --git a/packages/image_picker/image_picker_ios/example/pubspec.yaml b/packages/image_picker/image_picker_ios/example/pubspec.yaml index a47893d7687f..d219831cce03 100755 --- a/packages/image_picker/image_picker_ios/example/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/example/pubspec.yaml @@ -16,7 +16,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: ../ - image_picker_platform_interface: ^2.3.0 + image_picker_platform_interface: ^2.5.0 video_player: ^2.1.4 dev_dependencies: diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml index 2a001934d7c8..58434b4d2996 100755 --- a/packages/image_picker/image_picker_ios/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/pubspec.yaml @@ -19,7 +19,7 @@ flutter: dependencies: flutter: sdk: flutter - image_picker_platform_interface: ^2.3.0 + image_picker_platform_interface: ^2.5.0 dev_dependencies: flutter_test: From c2240fadbb126e791041cbfb871ca219c6f28ef9 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Fri, 13 May 2022 11:10:50 +0200 Subject: [PATCH 36/36] Fixed failing test in app-facing plugin --- .../image_picker/test/image_picker_test.dart | 225 ++++++++++++++---- 1 file changed, 176 insertions(+), 49 deletions(-) diff --git a/packages/image_picker/image_picker/test/image_picker_test.dart b/packages/image_picker/image_picker/test/image_picker_test.dart index f981195fe1b3..43ac425d6f11 100644 --- a/packages/image_picker/image_picker/test/image_picker_test.dart +++ b/packages/image_picker/image_picker/test/image_picker_test.dart @@ -29,12 +29,8 @@ void main() { group('#Single image/video', () { group('#pickImage', () { setUp(() { - when(mockPlatform.getImage( - source: anyNamed('source'), - maxWidth: anyNamed('maxWidth'), - maxHeight: anyNamed('maxHeight'), - imageQuality: anyNamed('imageQuality'), - preferredCameraDevice: anyNamed('preferredCameraDevice'))) + when(mockPlatform.getImageFromSource( + source: anyNamed('source'), options: anyNamed('options'))) .thenAnswer((Invocation _) async => null); }); @@ -44,8 +40,20 @@ void main() { await picker.pickImage(source: ImageSource.gallery); verifyInOrder([ - mockPlatform.getImage(source: ImageSource.camera), - mockPlatform.getImage(source: ImageSource.gallery), + mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf(), + named: 'options', + ), + ), + mockPlatform.getImageFromSource( + source: ImageSource.gallery, + options: argThat( + isInstanceOf(), + named: 'options', + ), + ), ]); }); @@ -76,41 +84,111 @@ void main() { imageQuality: 70); verifyInOrder([ - mockPlatform.getImage( - source: ImageSource.camera, - maxWidth: null, - maxHeight: null, - imageQuality: null), - mockPlatform.getImage( - source: ImageSource.camera, - maxWidth: 10.0, - maxHeight: null, - imageQuality: null), - mockPlatform.getImage( - source: ImageSource.camera, - maxWidth: null, - maxHeight: 10.0, - imageQuality: null), - mockPlatform.getImage( - source: ImageSource.camera, - maxWidth: 10.0, - maxHeight: 20.0, - imageQuality: null), - mockPlatform.getImage( - source: ImageSource.camera, - maxWidth: 10.0, - maxHeight: null, - imageQuality: 70), - mockPlatform.getImage( - source: ImageSource.camera, - maxWidth: null, - maxHeight: 10.0, - imageQuality: 70), - mockPlatform.getImage( - source: ImageSource.camera, - maxWidth: 10.0, - maxHeight: 20.0, - imageQuality: 70), + mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf() + .having((ImagePickerOptions options) => options.maxWidth, + 'maxWidth', isNull) + .having((ImagePickerOptions options) => options.maxHeight, + 'maxHeight', isNull) + .having( + (ImagePickerOptions options) => options.imageQuality, + 'imageQuality', + isNull), + named: 'options', + ), + ), + mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf() + .having((ImagePickerOptions options) => options.maxWidth, + 'maxWidth', equals(10.0)) + .having((ImagePickerOptions options) => options.maxHeight, + 'maxHeight', isNull) + .having( + (ImagePickerOptions options) => options.imageQuality, + 'imageQuality', + isNull), + named: 'options', + ), + ), + mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf() + .having((ImagePickerOptions options) => options.maxWidth, + 'maxWidth', isNull) + .having((ImagePickerOptions options) => options.maxHeight, + 'maxHeight', equals(10.0)) + .having( + (ImagePickerOptions options) => options.imageQuality, + 'imageQuality', + isNull), + named: 'options', + ), + ), + mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf() + .having((ImagePickerOptions options) => options.maxWidth, + 'maxWidth', equals(10.0)) + .having((ImagePickerOptions options) => options.maxHeight, + 'maxHeight', equals(20.0)) + .having( + (ImagePickerOptions options) => options.imageQuality, + 'imageQuality', + isNull), + named: 'options', + ), + ), + mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf() + .having((ImagePickerOptions options) => options.maxWidth, + 'maxWidth', equals(10.0)) + .having((ImagePickerOptions options) => options.maxHeight, + 'maxHeight', isNull) + .having( + (ImagePickerOptions options) => options.imageQuality, + 'imageQuality', + equals(70)), + named: 'options', + ), + ), + mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf() + .having((ImagePickerOptions options) => options.maxWidth, + 'maxWidth', isNull) + .having((ImagePickerOptions options) => options.maxHeight, + 'maxHeight', equals(10.0)) + .having( + (ImagePickerOptions options) => options.imageQuality, + 'imageQuality', + equals(70)), + named: 'options', + ), + ), + mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf() + .having((ImagePickerOptions options) => options.maxWidth, + 'maxWidth', equals(10.0)) + .having((ImagePickerOptions options) => options.maxHeight, + 'maxHeight', equals(20.0)) + .having( + (ImagePickerOptions options) => options.imageQuality, + 'imageQuality', + equals(70)), + named: 'options', + ), + ), ]); }); @@ -138,9 +216,16 @@ void main() { final ImagePicker picker = ImagePicker(); await picker.pickImage(source: ImageSource.camera); - verify(mockPlatform.getImage( - source: ImageSource.camera, - preferredCameraDevice: CameraDevice.rear)); + verify(mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf().having( + (ImagePickerOptions options) => options.preferredCameraDevice, + 'preferredCameraDevice', + equals(CameraDevice.rear)), + named: 'options', + ), + )); }); test('camera position can set to front', () async { @@ -149,9 +234,51 @@ void main() { source: ImageSource.camera, preferredCameraDevice: CameraDevice.front); - verify(mockPlatform.getImage( - source: ImageSource.camera, - preferredCameraDevice: CameraDevice.front)); + verify(mockPlatform.getImageFromSource( + source: ImageSource.camera, + options: argThat( + isInstanceOf().having( + (ImagePickerOptions options) => options.preferredCameraDevice, + 'preferredCameraDevice', + equals(CameraDevice.front)), + named: 'options', + ), + )); + }); + + test('Full metadata argument defaults to true', () async { + final ImagePicker picker = ImagePicker(); + await picker.pickImage(source: ImageSource.gallery); + + verify(mockPlatform.getImageFromSource( + source: ImageSource.gallery, + options: argThat( + isInstanceOf().having( + (ImagePickerOptions options) => options.requestFullMetadata, + 'requestFullMetadata', + isTrue), + named: 'options', + ), + )); + }); + + test('passes the full metadata argument correctly', () async { + final ImagePicker picker = ImagePicker(); + await picker.pickImage( + source: ImageSource.gallery, + requestFullMetadata: false, + ); + + verify(mockPlatform.getImageFromSource( + source: ImageSource.gallery, + options: argThat( + isInstanceOf().having( + (ImagePickerOptions options) => options.requestFullMetadata, + 'requestFullMetadata', + isFalse), + named: 'options', + ), + )); }); });