[image_picker] Allow saving photos picked with PHPicker without permissions (#6429)
diff --git a/packages/image_picker/image_picker_ios/CHANGELOG.md b/packages/image_picker/image_picker_ios/CHANGELOG.md index 33e2b61..986f5c0 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+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/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m b/packages/image_picker/image_picker_ios/example/ios/RunnerTests/PickerSaveImageToPathOperationTests.m index 688f5fb..e04c4f2 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ * * @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,6 +102,7 @@ maxHeight:@100 maxWidth:@100 desiredImageQuality:@100 + fullMetadata:fullMetadata savedPathBlock:^(NSString *savedPath) { if ([[NSFileManager defaultManager] fileExistsAtPath:savedPath]) { [pathExpectation fulfill];
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 c5372b8..440f2f1 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 @@ await _displayPickImageDialog(context!, (double? maxWidth, double? maxHeight, int? quality) async { try { - final List<XFile>? pickedFileList = await _picker.getMultiImage( - maxWidth: maxWidth, - maxHeight: maxHeight, - imageQuality: quality, + final List<XFile> pickedFileList = + await _picker.getMultiImageWithOptions( + options: MultiImagePickerOptions( + imageOptions: ImageOptions( + maxWidth: maxWidth, + maxHeight: maxHeight, + imageQuality: quality, + ), + ), ); setState(() { _imageFileList = pickedFileList; @@ -111,11 +116,13 @@ 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 fa1bb66..27b06ba 100644 --- a/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m +++ b/packages/image_picker/image_picker_ios/ios/Classes/FLTImagePickerPlugin.m
@@ -490,14 +490,15 @@ for (int i = 0; i < results.count; i++) { PHPickerResult *result = results[i]; - FLTPHPickerSaveImageToPathOperation *operation = - [[FLTPHPickerSaveImageToPathOperation alloc] initWithResult:result - maxHeight:maxHeight - maxWidth:maxWidth - desiredImageQuality:desiredImageQuality - 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 7ba3d28..8e097072 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 a81c95f..7c8fbc9 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 @@ @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 @@ 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 @@ self.maxHeight = maxHeight; self.maxWidth = maxWidth; self.desiredImageQuality = desiredImageQuality; + self.requestFullMetadata = fullMetadata; getSavedPath = savedPathBlock; executing = NO; finished = NO; @@ -113,7 +116,12 @@ * Processes the image. */ - (void)processImage:(UIImage *)localImage API_AVAILABLE(ios(14)) { - PHAsset *originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result]; + PHAsset *originalAsset; + // Only if requested, fetch the full "PHAsset" metadata, which requires "Photo Library Usage" + // permissions. + if (self.requestFullMetadata) { + originalAsset = [FLTImagePickerPhotoAssetUtil getAssetFromPHPickerResult:self.result]; + } if (self.maxWidth != nil || self.maxHeight != nil) { localImage = [FLTImagePickerImageUtil scaledImage:localImage
diff --git a/packages/image_picker/image_picker_ios/pubspec.yaml b/packages/image_picker/image_picker_ios/pubspec.yaml index 5c30bf9..6c78b23 100755 --- a/packages/image_picker/image_picker_ios/pubspec.yaml +++ b/packages/image_picker/image_picker_ios/pubspec.yaml
@@ -2,7 +2,7 @@ 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"