Fixes FileType.audio on iOS by exporting non DRM ipod-library files (#441)
This commit is contained in:
parent
b690afe33e
commit
0fa01bb74a
|
@ -1,3 +1,6 @@
|
||||||
|
## 2.0.11
|
||||||
|
iOS: Fixes `FileType.audio` exports to support ipod-library content (non DRM protected). From now on, a cached asset (m4a) will be exported from the selected music file in the Music app, so it can later be used. Fixes ([#441](https://github.com/miguelpruivo/flutter_file_picker/issues/441)).
|
||||||
|
|
||||||
## 2.0.10
|
## 2.0.10
|
||||||
Adds missing extension to `name` property of `PlatformFile`. ([#444](https://github.com/miguelpruivo/flutter_file_picker/issues/444))
|
Adds missing extension to `name` property of `PlatformFile`. ([#444](https://github.com/miguelpruivo/flutter_file_picker/issues/444))
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ See the **[File Picker Wiki](https://github.com/miguelpruivo/flutter_file_picker
|
||||||
* [Filters](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/API#filters)
|
* [Filters](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/API#filters)
|
||||||
* [Parameters](https://github.com/miguelpruivo/flutter_file_picker/wiki/API#parameters)
|
* [Parameters](https://github.com/miguelpruivo/flutter_file_picker/wiki/API#parameters)
|
||||||
* [Methods](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/API#methods)
|
* [Methods](https://github.com/miguelpruivo/plugins_flutter_file_picker/wiki/API#methods)
|
||||||
|
4. [FAQ](https://github.com/miguelpruivo/flutter_file_picker/wiki/FAQ)
|
||||||
5. [Troubleshooting](https://github.com/miguelpruivo/flutter_file_picker/wiki/Troubleshooting)
|
5. [Troubleshooting](https://github.com/miguelpruivo/flutter_file_picker/wiki/Troubleshooting)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#import <PhotosUI/PHPicker.h>
|
#import <PhotosUI/PHPicker.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@interface FilePickerPlugin : NSObject<FlutterPlugin, FlutterStreamHandler, UIDocumentPickerDelegate, UITabBarDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, UIImagePickerControllerDelegate, MPMediaPickerControllerDelegate
|
@interface FilePickerPlugin : NSObject<FlutterPlugin, FlutterStreamHandler, UIDocumentPickerDelegate, UITabBarDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate, MPMediaPickerControllerDelegate
|
||||||
#ifdef PHPicker
|
#ifdef PHPicker
|
||||||
, PHPickerViewControllerDelegate
|
, PHPickerViewControllerDelegate
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -136,8 +136,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) resolvePickMedia:(MediaType)type withMultiPick:(BOOL)multiPick withCompressionAllowed:(BOOL)allowCompression {
|
- (void) resolvePickMedia:(MediaType)type withMultiPick:(BOOL)multiPick withCompressionAllowed:(BOOL)allowCompression {
|
||||||
|
|
||||||
#ifdef PHPicker
|
#ifdef PHPicker
|
||||||
if (@available(iOS 14, *)) {
|
if (@available(iOS 14, *)) {
|
||||||
PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
|
PHPickerConfiguration *config = [[PHPickerConfiguration alloc] init];
|
||||||
config.filter = type == IMAGE ? [PHPickerFilter imagesFilter] : type == VIDEO ? [PHPickerFilter videosFilter] : [PHPickerFilter anyFilterMatchingSubfilters:@[[PHPickerFilter videosFilter], [PHPickerFilter imagesFilter]]];
|
config.filter = type == IMAGE ? [PHPickerFilter imagesFilter] : type == VIDEO ? [PHPickerFilter videosFilter] : [PHPickerFilter anyFilterMatchingSubfilters:@[[PHPickerFilter videosFilter], [PHPickerFilter imagesFilter]]];
|
||||||
|
@ -152,7 +152,7 @@
|
||||||
[self.viewController presentViewController:pickerViewController animated:YES completion:nil];
|
[self.viewController presentViewController:pickerViewController animated:YES completion:nil];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(multiPick) {
|
if(multiPick) {
|
||||||
[self resolveMultiPickFromGallery:type withCompressionAllowed:allowCompression];
|
[self resolveMultiPickFromGallery:type withCompressionAllowed:allowCompression];
|
||||||
|
@ -401,7 +401,7 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls{
|
||||||
[NSFileManager.defaultManager copyItemAtURL: url
|
[NSFileManager.defaultManager copyItemAtURL: url
|
||||||
toURL: cachedUrl
|
toURL: cachedUrl
|
||||||
error: ©Error];
|
error: ©Error];
|
||||||
|
|
||||||
if (copyError) {
|
if (copyError) {
|
||||||
Log("%@ Error while caching picked file: %@", self, copyError);
|
Log("%@ Error while caching picked file: %@", self, copyError);
|
||||||
return;
|
return;
|
||||||
|
@ -424,10 +424,25 @@ didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls{
|
||||||
- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
|
- (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection
|
||||||
{
|
{
|
||||||
[mediaPicker dismissViewControllerAnimated:YES completion:NULL];
|
[mediaPicker dismissViewControllerAnimated:YES completion:NULL];
|
||||||
NSMutableArray<NSURL *> * urls = [[NSMutableArray alloc] initWithCapacity:[mediaItemCollection items].count];
|
int numberOfItems = (int)[mediaItemCollection items].count;
|
||||||
|
|
||||||
|
if(numberOfItems == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_eventSink != nil) {
|
||||||
|
_eventSink([NSNumber numberWithBool:YES]);
|
||||||
|
}
|
||||||
|
|
||||||
|
NSMutableArray<NSURL *> * urls = [[NSMutableArray alloc] initWithCapacity:numberOfItems];
|
||||||
|
|
||||||
for(MPMediaItemCollection * item in [mediaItemCollection items]) {
|
for(MPMediaItemCollection * item in [mediaItemCollection items]) {
|
||||||
[urls addObject: [item valueForKey:MPMediaItemPropertyAssetURL]];
|
NSURL * cachedAsset = [FileUtils exportMusicAsset: [item valueForKey:MPMediaItemPropertyAssetURL] withName: [item valueForKey:MPMediaItemPropertyTitle]];
|
||||||
|
[urls addObject: cachedAsset];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_eventSink != nil) {
|
||||||
|
_eventSink([NSNumber numberWithBool:NO]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(urls.count == 0) {
|
if(urls.count == 0) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ typedef NS_ENUM(NSInteger, MediaType) {
|
||||||
+ (NSArray<NSString*>*) resolveType:(NSString*)type withAllowedExtensions:(NSArray<NSString*>*)allowedExtensions;
|
+ (NSArray<NSString*>*) resolveType:(NSString*)type withAllowedExtensions:(NSArray<NSString*>*)allowedExtensions;
|
||||||
+ (MediaType) resolveMediaType:(NSString*)type;
|
+ (MediaType) resolveMediaType:(NSString*)type;
|
||||||
+ (NSArray<NSDictionary*>*) resolveFileInfo:(NSArray<NSURL *> *)urls withData:(BOOL)loadData;
|
+ (NSArray<NSDictionary*>*) resolveFileInfo:(NSArray<NSURL *> *)urls withData:(BOOL)loadData;
|
||||||
|
+ (NSURL*) exportMusicAsset:(NSString*)url withName: (NSString*)name;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,12 +89,75 @@
|
||||||
NSDictionary<NSFileAttributeKey, id> * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
|
NSDictionary<NSFileAttributeKey, id> * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil];
|
||||||
|
|
||||||
[files addObject: [[[FileInfo alloc] initWithPath: path
|
[files addObject: [[[FileInfo alloc] initWithPath: path
|
||||||
andName: [path lastPathComponent]
|
andName: [path lastPathComponent]
|
||||||
andSize: [NSNumber numberWithLongLong: [@(fileAttributes.fileSize) longLongValue] / 1024]
|
andSize: [NSNumber numberWithLongLong: [@(fileAttributes.fileSize) longLongValue] / 1024]
|
||||||
andData: loadData ? [NSData dataWithContentsOfFile:path options: 0 error:nil] : nil] toData]];
|
andData: loadData ? [NSData dataWithContentsOfFile:path options: 0 error:nil] : nil] toData]];
|
||||||
}
|
}
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (NSURL*) exportMusicAsset:(NSString*) url withName:(NSString *)name {
|
||||||
|
AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: (NSURL*)url options:nil];
|
||||||
|
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset
|
||||||
|
presetName:AVAssetExportPresetAppleM4A];
|
||||||
|
|
||||||
|
exporter.outputFileType = @"com.apple.m4a-audio";
|
||||||
|
|
||||||
|
NSString* savePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[name stringByAppendingString:@".m4a"]];
|
||||||
|
NSURL *exportURL = [NSURL fileURLWithPath:savePath];
|
||||||
|
|
||||||
|
if ([[NSFileManager defaultManager] fileExistsAtPath:savePath]) {
|
||||||
|
return exportURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
exporter.outputURL = exportURL;
|
||||||
|
|
||||||
|
dispatch_queue_t queue = dispatch_queue_create("exportQueue", 0);
|
||||||
|
|
||||||
|
dispatch_async(queue, ^{
|
||||||
|
|
||||||
|
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||||
|
|
||||||
|
[exporter exportAsynchronouslyWithCompletionHandler:
|
||||||
|
^{
|
||||||
|
|
||||||
|
switch (exporter.status)
|
||||||
|
{
|
||||||
|
case AVAssetExportSessionStatusFailed:
|
||||||
|
{
|
||||||
|
NSError *exportError = exporter.error;
|
||||||
|
Log(@"AVAssetExportSessionStatusFailed: %@", exportError);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AVAssetExportSessionStatusCompleted:
|
||||||
|
{
|
||||||
|
Log(@"AVAssetExportSessionStatusCompleted");
|
||||||
|
@autoreleasepool {
|
||||||
|
dispatch_semaphore_signal(semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AVAssetExportSessionStatusCancelled:
|
||||||
|
{
|
||||||
|
Log(@"AVAssetExportSessionStatusCancelled");
|
||||||
|
@autoreleasepool {
|
||||||
|
dispatch_semaphore_signal(semaphore);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
Log(@"didn't get export status");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||||
|
});
|
||||||
|
return exportURL;
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -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.10
|
version: 2.0.11
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
|
Loading…
Reference in New Issue