Adds PHPickerController support for iOS 14 or later

Updates picker to use new PHPickerController for both single and multi media (image/video) picks (iOS 14 and above only).
This commit is contained in:
Miguel Ruivo 2020-09-23 10:23:38 +01:00
parent 4ff33b6acc
commit 24b4337d39
4 changed files with 64 additions and 13 deletions

View File

@ -1,3 +1,6 @@
## 2.0.1
iOS: Updates picker to use new PHPickerController for both single and multi media (image/video) picks (iOS 14 and above only).
## 2.0.0 ## 2.0.0
**Breaking Changes** **Breaking Changes**
- Unifies all platforms (IO, Web and Desktop) in a single plugin (file_picker) that can be used seamlessly across all. Both [file_picker_interface](https://pub.dev/packages/file_picker_platform_interface) and [file_picker_web](https://pub.dev/packages/file_picker_web) are no longer mantained from now on. - Unifies all platforms (IO, Web and Desktop) in a single plugin (file_picker) that can be used seamlessly across all. Both [file_picker_interface](https://pub.dev/packages/file_picker_platform_interface) and [file_picker_web](https://pub.dev/packages/file_picker_web) are no longer mantained from now on.

View File

@ -2,7 +2,8 @@
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h> #import <MediaPlayer/MediaPlayer.h>
#import <Photos/Photos.h> #import <Photos/Photos.h>
#import <PhotosUI/PHPicker.h>
#import <MobileCoreServices/MobileCoreServices.h> #import <MobileCoreServices/MobileCoreServices.h>
@interface FilePickerPlugin : NSObject<FlutterPlugin, FlutterStreamHandler, UIDocumentPickerDelegate, UITabBarDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate> @interface FilePickerPlugin : NSObject<FlutterPlugin, FlutterStreamHandler, UIDocumentPickerDelegate, UITabBarDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, PHPickerViewControllerDelegate>
@end @end

View File

@ -4,7 +4,7 @@
@import DKImagePickerController; @import DKImagePickerController;
@interface FilePickerPlugin() <UIImagePickerControllerDelegate, MPMediaPickerControllerDelegate, DKImageAssetExporterObserver> @interface FilePickerPlugin() <UIImagePickerControllerDelegate, MPMediaPickerControllerDelegate, DKImageAssetExporterObserver, PHPickerViewControllerDelegate>
@property (nonatomic) FlutterResult result; @property (nonatomic) FlutterResult result;
@property (nonatomic) FlutterEventSink eventSink; @property (nonatomic) FlutterEventSink eventSink;
@property (nonatomic) UIViewController *viewController; @property (nonatomic) UIViewController *viewController;
@ -56,8 +56,8 @@
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if (_result) { if (_result) {
result([FlutterError errorWithCode:@"multiple_request" result([FlutterError errorWithCode:@"multiple_request"
message:@"Cancelled by a second request" message:@"Cancelled by a second request"
details:nil]); details:nil]);
_result = nil; _result = nil;
return; return;
} }
@ -108,7 +108,7 @@
initWithDocumentTypes: isDirectory ? @[@"public.folder"] : self.allowedExtensions initWithDocumentTypes: isDirectory ? @[@"public.folder"] : self.allowedExtensions
inMode: isDirectory ? UIDocumentPickerModeOpen : UIDocumentPickerModeImport]; inMode: isDirectory ? UIDocumentPickerModeOpen : UIDocumentPickerModeImport];
} @catch (NSException * e) { } @catch (NSException * e) {
Log(@"Couldn't launch documents file picker. Probably due to iOS version being below 11.0 and not having the iCloud entitlement. If so, just make sure to enable it for your app in Xcode. Exception was: %@", e); Log(@"Couldn't launch documents file picker. Probably due to iOS version being below 11.0 and not having the iCloud entitlement. If so, just make sure to enable it for your app in Xcode. Exception was: %@", e);
_result = nil; _result = nil;
return; return;
} }
@ -116,7 +116,7 @@
if (@available(iOS 11.0, *)) { if (@available(iOS 11.0, *)) {
self.documentPickerController.allowsMultipleSelection = allowsMultipleSelection; self.documentPickerController.allowsMultipleSelection = allowsMultipleSelection;
} else if(allowsMultipleSelection) { } else if(allowsMultipleSelection) {
Log(@"Multiple file selection is only supported on iOS 11 and above. Single selection will be used."); Log(@"Multiple file selection is only supported on iOS 11 and above. Single selection will be used.");
} }
self.documentPickerController.delegate = self; self.documentPickerController.delegate = self;
@ -127,6 +127,20 @@
} }
- (void) resolvePickMedia:(MediaType)type withMultiPick:(BOOL)multiPick withCompressionAllowed:(BOOL)allowCompression { - (void) resolvePickMedia:(MediaType)type withMultiPick:(BOOL)multiPick withCompressionAllowed:(BOOL)allowCompression {
if (@available(iOS 14, *)) {
PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
config.filter = type == IMAGE ? [PHPickerFilter imagesFilter] : type == VIDEO ? [PHPickerFilter videosFilter] : [PHPickerFilter anyFilterMatchingSubfilters:@[[PHPickerFilter videosFilter], [PHPickerFilter imagesFilter]]];
if(multiPick) {
config.selectionLimit = 0;
}
PHPickerViewController *pickerViewController = [[PHPickerViewController alloc] initWithConfiguration:config];
pickerViewController.delegate = self;
[self.viewController presentViewController:pickerViewController animated:YES completion:nil];
return;
}
if(multiPick) { if(multiPick) {
[self resolveMultiPickFromGallery:type withCompressionAllowed:allowCompression]; [self resolveMultiPickFromGallery:type withCompressionAllowed:allowCompression];
@ -162,6 +176,8 @@
} }
[self.viewController presentViewController:self.galleryPickerController animated:YES completion:nil]; [self.viewController presentViewController:self.galleryPickerController animated:YES completion:nil];
} }
- (void) resolveMultiPickFromGallery:(MediaType)type withCompressionAllowed:(BOOL)allowCompression { - (void) resolveMultiPickFromGallery:(MediaType)type withCompressionAllowed:(BOOL)allowCompression {
@ -291,7 +307,7 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls{
NSURL *pickedVideoUrl = [info objectForKey:UIImagePickerControllerMediaURL]; NSURL *pickedVideoUrl = [info objectForKey:UIImagePickerControllerMediaURL];
NSURL *pickedImageUrl; NSURL *pickedImageUrl;
if(@available(iOS 13.0, *)){ if(@available(iOS 13.0, *)) {
if(pickedVideoUrl != nil) { if(pickedVideoUrl != nil) {
NSString * fileName = [pickedVideoUrl lastPathComponent]; NSString * fileName = [pickedVideoUrl lastPathComponent];
@ -307,10 +323,10 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls{
} }
} else if (@available(iOS 11.0, *)) { } else if (@available(iOS 11.0, *)) {
pickedImageUrl = [info objectForKey:UIImagePickerControllerImageURL]; pickedImageUrl = [info objectForKey:UIImagePickerControllerImageURL];
} else { } else {
UIImage *pickedImage = [info objectForKey:UIImagePickerControllerEditedImage]; UIImage *pickedImage = [info objectForKey:UIImagePickerControllerEditedImage];
if(pickedImage == nil) { if(pickedImage == nil) {
pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage]; pickedImage = [info objectForKey:UIImagePickerControllerOriginalImage];
} }
@ -318,7 +334,7 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls{
} }
[picker dismissViewControllerAnimated:YES completion:NULL]; [picker dismissViewControllerAnimated:YES completion:NULL];
if(pickedImageUrl == nil && pickedVideoUrl == nil) { if(pickedImageUrl == nil && pickedVideoUrl == nil) {
_result([FlutterError errorWithCode:@"file_picker_error" _result([FlutterError errorWithCode:@"file_picker_error"
message:@"Temporary file could not be created" message:@"Temporary file could not be created"
@ -330,6 +346,37 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls{
[self handleResult: pickedVideoUrl != nil ? pickedVideoUrl : pickedImageUrl]; [self handleResult: pickedVideoUrl != nil ? pickedVideoUrl : pickedImageUrl];
} }
-(void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14)){
Log(@"Picker:%@ didFinishPicking:%@", picker, results);
[picker dismissViewControllerAnimated:YES completion:nil];
if(results.count == 0) {
Log(@"FilePicker canceled");
_result(nil);
_result = nil;
return;
}
NSMutableArray<NSURL *> * urls = [[NSMutableArray alloc] initWithCapacity:results.count];
dispatch_group_t group = dispatch_group_create();
for (PHPickerResult *result in results) {
dispatch_group_enter(group);
[result.itemProvider loadFileRepresentationForTypeIdentifier: @"public.item"
completionHandler:^(NSURL * url, NSError * error) {
[urls addObject:url];
dispatch_group_leave(group);
}];
}
dispatch_group_notify(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),^{
[self handleResult:urls];
});
}
// AudioPicker delegate // AudioPicker delegate
- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection - (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
@ -340,7 +387,7 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls{
for(MPMediaItemCollection * item in [mediaItemCollection items]) { for(MPMediaItemCollection * item in [mediaItemCollection items]) {
[urls addObject: [item valueForKey:MPMediaItemPropertyAssetURL]]; [urls addObject: [item valueForKey:MPMediaItemPropertyAssetURL]];
} }
if(urls.count == 0) { if(urls.count == 0) {
Log(@"Couldn't retrieve the audio file path, either is not locally downloaded or the file is DRM protected."); Log(@"Couldn't retrieve the audio file path, either is not locally downloaded or the file is DRM protected.");
} }

View File

@ -1,7 +1,7 @@
name: file_picker name: file_picker
description: A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extension filtering support. description: A package that allows you to use a native file explorer to pick single or multiple absolute file paths, with extension filtering support.
homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker
version: 2.0.0 version: 2.0.1
dependencies: dependencies:
flutter: flutter: