-
Notifications
You must be signed in to change notification settings - Fork 9.7k
[image_picker] add requestFullMetadata for iOS (optional permissions) #4638
Changes from 25 commits
5d3a9aa
4195dca
7d255de
3fd7383
686bc22
1f73191
24d0679
1ba0c73
1084763
a89ad0a
8ff7492
193bbe9
95eef20
e10b24e
f2c2e68
f5f94b2
97efdca
bd3dfeb
b99ba07
3d6c45c
b3e9166
bf3f55c
742b259
d41b390
ead2f62
7b6ace9
0f43653
c6dcc49
9ba71b9
c1fc9da
7f958a6
c825d09
a2ca361
0120c47
0827c80
994e45f
9b39e31
933254e
66f14b2
47098ec
0a811d8
0789a7b
c5966d4
6f32405
217237b
7a4d250
4ee04cb
b3fb220
4d884de
c2240fa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -191,6 +191,10 @@ 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. | ||
| /// 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. | ||
| /// | ||
|
|
@@ -206,13 +210,15 @@ class ImagePicker { | |
| double? maxHeight, | ||
| int? imageQuality, | ||
| CameraDevice preferredCameraDevice = CameraDevice.rear, | ||
| bool requestFullMetadata = true, | ||
| }) { | ||
| return platform.getImage( | ||
| return platform.getImageFromSource( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to require the version of the platform interface that has this method in pubspec.yaml. |
||
| source: source, | ||
| maxWidth: maxWidth, | ||
| maxHeight: maxHeight, | ||
| imageQuality: imageQuality, | ||
| preferredCameraDevice: preferredCameraDevice, | ||
| requestFullMetadata: requestFullMetadata, | ||
| ); | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -57,14 +57,16 @@ void main() { | |
| 'maxWidth': null, | ||
| 'maxHeight': null, | ||
| 'imageQuality': null, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
|
||
| }), | ||
| isMethodCall('pickImage', arguments: <String, dynamic>{ | ||
| 'source': 1, | ||
| 'maxWidth': null, | ||
| 'maxHeight': null, | ||
| 'imageQuality': null, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| ], | ||
| ); | ||
|
|
@@ -103,49 +105,56 @@ void main() { | |
| 'maxWidth': null, | ||
| 'maxHeight': null, | ||
| 'imageQuality': null, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| isMethodCall('pickImage', arguments: <String, dynamic>{ | ||
| 'source': 0, | ||
| 'maxWidth': 10.0, | ||
| 'maxHeight': null, | ||
| 'imageQuality': null, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| isMethodCall('pickImage', arguments: <String, dynamic>{ | ||
| 'source': 0, | ||
| 'maxWidth': null, | ||
| 'maxHeight': 10.0, | ||
| 'imageQuality': null, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| isMethodCall('pickImage', arguments: <String, dynamic>{ | ||
| 'source': 0, | ||
| 'maxWidth': 10.0, | ||
| 'maxHeight': 20.0, | ||
| 'imageQuality': null, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| isMethodCall('pickImage', arguments: <String, dynamic>{ | ||
| 'source': 0, | ||
| 'maxWidth': 10.0, | ||
| 'maxHeight': null, | ||
| 'imageQuality': 70, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| isMethodCall('pickImage', arguments: <String, dynamic>{ | ||
| 'source': 0, | ||
| 'maxWidth': null, | ||
| 'maxHeight': 10.0, | ||
| 'imageQuality': 70, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| isMethodCall('pickImage', arguments: <String, dynamic>{ | ||
| 'source': 0, | ||
| 'maxWidth': 10.0, | ||
| 'maxHeight': 20.0, | ||
| 'imageQuality': 70, | ||
| 'cameraDevice': 0 | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| ], | ||
| ); | ||
|
|
@@ -182,6 +191,7 @@ void main() { | |
| 'maxHeight': null, | ||
| 'imageQuality': null, | ||
| 'cameraDevice': 0, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| ], | ||
| ); | ||
|
|
@@ -201,6 +211,7 @@ void main() { | |
| 'maxHeight': null, | ||
| 'imageQuality': null, | ||
| 'cameraDevice': 1, | ||
| 'requestFullMetadata': true, | ||
| }), | ||
| ], | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -180,6 +180,27 @@ - (void)testPickMultiImageShouldUseUIImagePickerControllerOnPreiOS14 { | |
| [mockUIImagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary]); | ||
| } | ||
|
|
||
| - (void)testPickImageWithoutFullMetadataPreiOS14 { | ||
| if (@available(iOS 14, *)) { | ||
| return; | ||
| } | ||
| 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 { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -133,7 +133,12 @@ - (void)pickImageWithPHPicker:(int)maxImagesAllowed API_AVAILABLE(ios(14)) { | |
|
|
||
| self.maxImagesAllowed = maxImagesAllowed; | ||
|
|
||
| [self checkPhotoAuthorizationForAccessLevel]; | ||
| BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; | ||
|
||
| if (usePHAsset) { | ||
| [self checkPhotoAuthorizationForAccessLevel]; | ||
| } else { | ||
| [self showPhotoLibraryWithPHPicker:_pickerViewController]; | ||
| } | ||
| } | ||
|
|
||
| - (void)launchUIImagePickerWithSource:(int)imageSource { | ||
|
|
@@ -142,14 +147,24 @@ - (void)launchUIImagePickerWithSource:(int)imageSource { | |
| imagePickerController.delegate = self; | ||
| imagePickerController.mediaTypes = @[ (NSString *)kUTTypeImage ]; | ||
|
|
||
| BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; | ||
|
||
| self.maxImagesAllowed = 1; | ||
|
|
||
| switch (imageSource) { | ||
| case SOURCE_CAMERA: | ||
| [self checkCameraAuthorizationWithImagePicker:imagePickerController]; | ||
| break; | ||
| case SOURCE_GALLERY: | ||
| [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; | ||
| if (@available(iOS 11, *)) { | ||
| if (usePHAsset) { | ||
| [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; | ||
| } else { | ||
| [self showPhotoLibraryWithImagePicker:imagePickerController]; | ||
| } | ||
| } else { | ||
| // Prior to iOS 11, accessing gallery requires authorization | ||
| [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; | ||
| } | ||
| break; | ||
| default: | ||
| self.result([FlutterError errorWithCode:@"invalid_source" | ||
|
|
@@ -172,7 +187,6 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result | |
|
|
||
| if ([@"pickImage" isEqualToString:call.method]) { | ||
| int imageSource = [call.arguments[@"source"] intValue]; | ||
|
|
||
| if (imageSource == SOURCE_GALLERY) { // Capture is not possible with PHPicker | ||
| if (@available(iOS 14, *)) { | ||
| // PHPicker is used | ||
|
|
@@ -206,12 +220,17 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result | |
| imagePickerController.videoMaximumDuration = max; | ||
| } | ||
|
|
||
| BOOL usePHAsset = [[_arguments objectForKey:@"requestFullMetadata"] boolValue]; | ||
|
||
| switch (imageSource) { | ||
| case SOURCE_CAMERA: | ||
| [self checkCameraAuthorizationWithImagePicker:imagePickerController]; | ||
| break; | ||
| case SOURCE_GALLERY: | ||
| [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; | ||
| if (usePHAsset) { | ||
| [self checkPhotoAuthorizationWithImagePicker:imagePickerController]; | ||
| } else { | ||
| [self showPhotoLibraryWithImagePicker:imagePickerController]; | ||
| } | ||
| break; | ||
| default: | ||
| result([FlutterError errorWithCode:@"invalid_source" | ||
|
|
@@ -515,8 +534,12 @@ - (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]; | ||
|
|
||
| PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; | ||
| PHAsset *originalAsset; | ||
| if (usePHAsset) { | ||
| originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromImagePickerInfo:info]; | ||
| } | ||
|
|
||
| if (maxWidth != nil || maxHeight != nil) { | ||
| image = [FLTImagePickerImageUtil scaledImage:image | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.