From 4467067e1c7887f870e9e756030355e73efd1032 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 15 Sep 2022 08:29:17 +0200 Subject: [PATCH 1/7] Fixed saving photos picked with PHPicker without permissions --- .../image_picker_ios/example/lib/main.dart | 23 ++++++++++++------- .../ios/Classes/FLTImagePickerPlugin.m | 1 + .../FLTPHPickerSaveImageToPathOperation.h | 1 + .../FLTPHPickerSaveImageToPathOperation.m | 8 ++++++- 4 files changed, 24 insertions(+), 9 deletions(-) diff --git a/packages/image_picker/image_picker_ios/example/lib/main.dart b/packages/image_picker/image_picker_ios/example/lib/main.dart index c5372b8e7ad8..440f2f1d7cca 100755 --- a/packages/image_picker/image_picker_ios/example/lib/main.dart +++ b/packages/image_picker/image_picker_ios/example/lib/main.dart @@ -93,10 +93,15 @@ class _MyHomePageState extends State { await _displayPickImageDialog(context!, (double? maxWidth, double? maxHeight, int? quality) async { try { - final List? pickedFileList = await _picker.getMultiImage( - maxWidth: maxWidth, - maxHeight: maxHeight, - imageQuality: quality, + final List pickedFileList = + await _picker.getMultiImageWithOptions( + options: MultiImagePickerOptions( + imageOptions: ImageOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + ), + ), ); setState(() { _imageFileList = pickedFileList; @@ -111,11 +116,13 @@ class _MyHomePageState extends State { await _displayPickImageDialog(context!, (double? maxWidth, double? maxHeight, int? quality) async { try { - final XFile? pickedFile = await _picker.getImage( + final XFile? pickedFile = await _picker.getImageFromSource( source: source, - maxWidth: maxWidth, - maxHeight: maxHeight, - imageQuality: quality, + options: ImagePickerOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + ), ); setState(() { _setImageFileListFromFile(pickedFile); 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 fa1bb6650501..ada69838c00f 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m @@ -495,6 +495,7 @@ - (void)picker:(PHPickerViewController *)picker maxHeight:maxHeight maxWidth:maxWidth desiredImageQuality:desiredImageQuality + fullMetadata:self.callContext.requestFullMetadata savedPathBlock:^(NSString *savedPath) { pathList[i] = savedPath; }]; diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h index 7ba3d28ef3dd..8c566bb52654 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h @@ -26,6 +26,7 @@ maxHeight:(NSNumber *)maxHeight maxWidth:(NSNumber *)maxWidth desiredImageQuality:(NSNumber *)desiredImageQuality + fullMetadata:(BOOL)fullMetadata savedPathBlock:(void (^)(NSString *))savedPathBlock API_AVAILABLE(ios(14)); @end diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m index a81c95f1b120..836d9175ad3a 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m @@ -13,6 +13,7 @@ @interface FLTPHPickerSaveImageToPathOperation () @property(assign, nonatomic) NSNumber *maxHeight; @property(assign, nonatomic) NSNumber *maxWidth; @property(assign, nonatomic) NSNumber *desiredImageQuality; +@property(assign, nonatomic) BOOL requestFullMetadata; @end @@ -28,6 +29,7 @@ - (instancetype)initWithResult:(PHPickerResult *)result maxHeight:(NSNumber *)maxHeight maxWidth:(NSNumber *)maxWidth desiredImageQuality:(NSNumber *)desiredImageQuality + fullMetadata:(BOOL)fullMetadata savedPathBlock:(GetSavedPath)savedPathBlock API_AVAILABLE(ios(14)) { if (self = [super init]) { if (result) { @@ -35,6 +37,7 @@ - (instancetype)initWithResult:(PHPickerResult *)result self.maxHeight = maxHeight; self.maxWidth = maxWidth; self.desiredImageQuality = desiredImageQuality; + self.requestFullMetadata = fullMetadata; getSavedPath = savedPathBlock; executing = NO; finished = NO; @@ -113,7 +116,10 @@ - (void)start { * Processes the image. */ - (void)processImage:(UIImage *)localImage API_AVAILABLE(ios(14)) { - PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result]; + PHAsset *originalAsset; + if (self.requestFullMetadata) { + originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result]; + } if (self.maxWidth != nil || self.maxHeight != nil) { localImage = [FLTImagePickerImageUtil scaledImage:localImage From 1bfbb9b096534fdb70a675c09cf6e57b8e63cdf9 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 15 Sep 2022 08:32:12 +0200 Subject: [PATCH 2/7] Fixed formatting --- .../ios/Classes/FLTImagePickerPlugin.m | 18 +++++++++--------- .../FLTPHPickerSaveImageToPathOperation.h | 2 +- .../FLTPHPickerSaveImageToPathOperation.m | 12 ++++++------ 3 files changed, 16 insertions(+), 16 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 ada69838c00f..27b06ba994ef 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m @@ -490,15 +490,15 @@ - (void)picker:(PHPickerViewController *)picker for (int i = 0; i < results.count; i++) { PHPickerResult *result = results[i]; - FLTPHPickerSaveImageToPathOperation *operation = - [[FLTPHPickerSaveImageToPathOperation alloc] initWithResult:result - maxHeight:maxHeight - maxWidth:maxWidth - desiredImageQuality:desiredImageQuality - fullMetadata:self.callContext.requestFullMetadata - savedPathBlock:^(NSString *savedPath) { - pathList[i] = savedPath; - }]; + FLTPHPickerSaveImageToPathOperation *operation = [[FLTPHPickerSaveImageToPathOperation alloc] + initWithResult:result + maxHeight:maxHeight + maxWidth:maxWidth + desiredImageQuality:desiredImageQuality + fullMetadata:self.callContext.requestFullMetadata + savedPathBlock:^(NSString *savedPath) { + pathList[i] = savedPath; + }]; [operationQueue addOperation:operation]; } [operationQueue waitUntilAllOperationsAreFinished]; diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h index 8c566bb52654..8e0970725e90 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.h @@ -26,7 +26,7 @@ maxHeight:(NSNumber *)maxHeight maxWidth:(NSNumber *)maxWidth desiredImageQuality:(NSNumber *)desiredImageQuality - fullMetadata:(BOOL)fullMetadata + fullMetadata:(BOOL)fullMetadata savedPathBlock:(void (^)(NSString *))savedPathBlock API_AVAILABLE(ios(14)); @end diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m index 836d9175ad3a..8e0cfec0bf5c 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m @@ -29,7 +29,7 @@ - (instancetype)initWithResult:(PHPickerResult *)result maxHeight:(NSNumber *)maxHeight maxWidth:(NSNumber *)maxWidth desiredImageQuality:(NSNumber *)desiredImageQuality - fullMetadata:(BOOL)fullMetadata + fullMetadata:(BOOL)fullMetadata savedPathBlock:(GetSavedPath)savedPathBlock API_AVAILABLE(ios(14)) { if (self = [super init]) { if (result) { @@ -37,7 +37,7 @@ - (instancetype)initWithResult:(PHPickerResult *)result self.maxHeight = maxHeight; self.maxWidth = maxWidth; self.desiredImageQuality = desiredImageQuality; - self.requestFullMetadata = fullMetadata; + self.requestFullMetadata = fullMetadata; getSavedPath = savedPathBlock; executing = NO; finished = NO; @@ -116,10 +116,10 @@ - (void)start { * Processes the image. */ - (void)processImage:(UIImage *)localImage API_AVAILABLE(ios(14)) { - PHAsset *originalAsset; - if (self.requestFullMetadata) { - originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result]; - } + PHAsset *originalAsset; + if (self.requestFullMetadata) { + originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result]; + } if (self.maxWidth != nil || self.maxHeight != nil) { localImage = [FLTImagePickerImageUtil scaledImage:localImage From 75858ca2477cfaf5fedc84e4f9686354c5995f7b Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 15 Sep 2022 08:38:49 +0200 Subject: [PATCH 3/7] Updated package version --- packages/image_picker/image_picker_ios/CHANGELOG.md | 3 +++ packages/image_picker/image_picker_ios/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md index 33e2b61b0e88..7d048c3cdb35 100644 --- a/packages/image_picker/image_picker_ios/CHANGELOG.md +++ b/packages/image_picker/image_picker_ios/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.8.6+1 +* Fixes issue with crashing the app when picking images with PHPicker without providing `Photo Library Usage` permission. + ## 0.8.6 * Adds `requestFullMetadata` option to `pickImage`, so images on iOS can be picked without `Photo Library Usage` permission. diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml index 5c30bf9d8c35..6c78b2340ed0 100755 --- a/packages/image_picker/image_picker_ios/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/pubspec.yaml @@ -2,7 +2,7 @@ name: image_picker_ios description: iOS implementation of the image_picker plugin. repository: https://github.com/flutter/plugins/tree/main/packages/image_picker/image_picker_ios issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+image_picker%22 -version: 0.8.6 +version: 0.8.6+1 environment: sdk: ">=2.14.0 <3.0.0" From 3d67fa023b19a57b616f106a8fabb0b781d826f7 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 15 Sep 2022 09:02:05 +0200 Subject: [PATCH 4/7] Fixed build issues in tests --- .../ios/RunnerTests/PickerSaveImageToPathOperationTests.m | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m index 688f5fbee032..3d3c93943bdd 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m @@ -87,6 +87,7 @@ - (void)verifySavingImageWithPickerResult:(PHPickerResult *)result API_AVAILABLE maxHeight:@100 maxWidth:@100 desiredImageQuality:@100 + fullMetadata:YES savedPathBlock:^(NSString *savedPath) { if ([[NSFileManager defaultManager] fileExistsAtPath:savedPath]) { [pathExpectation fulfill]; From 230297d15f827cdc668cd4a217b5e5df810eacb1 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Thu, 15 Sep 2022 18:58:33 +0200 Subject: [PATCH 5/7] Added a test covering the bugfix --- .../image_picker_ios/CHANGELOG.md | 1 + .../PickerSaveImageToPathOperationTests.m | 27 ++++++++++++++----- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md index 7d048c3cdb35..986f5c0ff6ca 100644 --- a/packages/image_picker/image_picker_ios/CHANGELOG.md +++ b/packages/image_picker/image_picker_ios/CHANGELOG.md @@ -1,4 +1,5 @@ ## 0.8.6+1 + * Fixes issue with crashing the app when picking images with PHPicker without providing `Photo Library Usage` permission. ## 0.8.6 diff --git a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m index 3d3c93943bdd..e04c4f2abb50 100644 --- a/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m +++ b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m @@ -22,7 +22,7 @@ - (void)testSaveWebPImage API_AVAILABLE(ios(14)) { PHPickerResult *result = [self createPickerResultWithProvider:itemProvider withIdentifier:UTTypeWebP.identifier]; - [self verifySavingImageWithPickerResult:result]; + [self verifySavingImageWithPickerResult:result fullMetadata:YES]; } - (void)testSavePNGImage API_AVAILABLE(ios(14)) { @@ -32,7 +32,7 @@ - (void)testSavePNGImage API_AVAILABLE(ios(14)) { PHPickerResult *result = [self createPickerResultWithProvider:itemProvider withIdentifier:UTTypeWebP.identifier]; - [self verifySavingImageWithPickerResult:result]; + [self verifySavingImageWithPickerResult:result fullMetadata:YES]; } - (void)testSaveJPGImage API_AVAILABLE(ios(14)) { @@ -42,7 +42,7 @@ - (void)testSaveJPGImage API_AVAILABLE(ios(14)) { PHPickerResult *result = [self createPickerResultWithProvider:itemProvider withIdentifier:UTTypeWebP.identifier]; - [self verifySavingImageWithPickerResult:result]; + [self verifySavingImageWithPickerResult:result fullMetadata:YES]; } - (void)testSaveGIFImage API_AVAILABLE(ios(14)) { @@ -52,7 +52,21 @@ - (void)testSaveGIFImage API_AVAILABLE(ios(14)) { PHPickerResult *result = [self createPickerResultWithProvider:itemProvider withIdentifier:UTTypeWebP.identifier]; - [self verifySavingImageWithPickerResult:result]; + [self verifySavingImageWithPickerResult:result fullMetadata:YES]; +} + +- (void)testSavePNGImageWithoutFullMetadata API_AVAILABLE(ios(14)) { + id photoAssetUtil = OCMClassMock([PHAsset class]); + + NSURL *imageURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"pngImage" + withExtension:@"png"]; + NSItemProvider *itemProvider = [[NSItemProvider alloc] initWithContentsOfURL:imageURL]; + PHPickerResult *result = [self createPickerResultWithProvider:itemProvider + withIdentifier:UTTypeWebP.identifier]; + + [self verifySavingImageWithPickerResult:result fullMetadata:NO]; + OCMVerify(times(0), [photoAssetUtil fetchAssetsWithLocalIdentifiers:[OCMArg any] + options:[OCMArg any]]); } /** @@ -79,7 +93,8 @@ - (PHPickerResult *)createPickerResultWithProvider:(NSItemProvider *)itemProvide * * @param result the picker result */ -- (void)verifySavingImageWithPickerResult:(PHPickerResult *)result API_AVAILABLE(ios(14)) { +- (void)verifySavingImageWithPickerResult:(PHPickerResult *)result + fullMetadata:(BOOL)fullMetadata API_AVAILABLE(ios(14)) { XCTestExpectation *pathExpectation = [self expectationWithDescription:@"Path was created"]; FLTPHPickerSaveImageToPathOperation *operation = [[FLTPHPickerSaveImageToPathOperation alloc] @@ -87,7 +102,7 @@ - (void)verifySavingImageWithPickerResult:(PHPickerResult *)result API_AVAILABLE maxHeight:@100 maxWidth:@100 desiredImageQuality:@100 - fullMetadata:YES + fullMetadata:fullMetadata savedPathBlock:^(NSString *savedPath) { if ([[NSFileManager defaultManager] fileExistsAtPath:savedPath]) { [pathExpectation fulfill]; From 4ed43b8f9b5485c4d5bb1789ea87aabb2c3a6133 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 19 Sep 2022 08:23:21 +0200 Subject: [PATCH 6/7] PR remarks Co-authored-by: Jenn Magder --- .../ios/Classes/FLTPHPickerSaveImageToPathOperation.m | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m index 8e0cfec0bf5c..6219efd1be0e 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m @@ -117,6 +117,7 @@ - (void)start { */ - (void)processImage:(UIImage *)localImage API_AVAILABLE(ios(14)) { PHAsset *originalAsset; + // Only if requested, fetch the full "PHAsset" metadata, which requires "Photo Library Usage" permissions. if (self.requestFullMetadata) { originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result]; } From 1c2f621afccf66d9e5ba45ebff6ceaac0d3befe0 Mon Sep 17 00:00:00 2001 From: Piotr Mitkowski Date: Mon, 19 Sep 2022 08:31:06 +0200 Subject: [PATCH 7/7] Fixed formatting --- .../ios/Classes/FLTPHPickerSaveImageToPathOperation.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m index 6219efd1be0e..7c8fbc9ca7cf 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTPHPickerSaveImageToPathOperation.m @@ -117,7 +117,8 @@ - (void)start { */ - (void)processImage:(UIImage *)localImage API_AVAILABLE(ios(14)) { PHAsset *originalAsset; - // Only if requested, fetch the full "PHAsset" metadata, which requires "Photo Library Usage" permissions. + // Only if requested, fetch the full "PHAsset" metadata, which requires "Photo Library Usage" + // permissions. if (self.requestFullMetadata) { originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result]; }