[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"