From 0fa01bb74ae43eb594e69b73ac2bce0713d9eae5 Mon Sep 17 00:00:00 2001 From: Miguel Ruivo Date: Sun, 25 Oct 2020 18:07:36 +0000 Subject: [PATCH] Fixes FileType.audio on iOS by exporting non DRM ipod-library files (#441) --- CHANGELOG.md | 3 ++ README.md | 1 + ios/Classes/FilePickerPlugin.h | 2 +- ios/Classes/FilePickerPlugin.m | 27 ++++++++++--- ios/Classes/FileUtils.h | 1 + ios/Classes/FileUtils.m | 69 ++++++++++++++++++++++++++++++++-- pubspec.yaml | 2 +- 7 files changed, 94 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0546d31..89b68c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 Adds missing extension to `name` property of `PlatformFile`. ([#444](https://github.com/miguelpruivo/flutter_file_picker/issues/444)) diff --git a/README.md b/README.md index e135dad..93d25e4 100644 --- a/README.md +++ b/README.md @@ -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) * [Parameters](https://github.com/miguelpruivo/flutter_file_picker/wiki/API#parameters) * [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) ## Usage diff --git a/ios/Classes/FilePickerPlugin.h b/ios/Classes/FilePickerPlugin.h index 2c5b45e..cf2b012 100644 --- a/ios/Classes/FilePickerPlugin.h +++ b/ios/Classes/FilePickerPlugin.h @@ -9,7 +9,7 @@ #import #endif -@interface FilePickerPlugin : NSObject *)urls{ [NSFileManager.defaultManager copyItemAtURL: url toURL: cachedUrl error: ©Error]; - + if (copyError) { Log("%@ Error while caching picked file: %@", self, copyError); return; @@ -424,10 +424,25 @@ didPickDocumentsAtURLs:(NSArray *)urls{ - (void)mediaPicker: (MPMediaPickerController *)mediaPicker didPickMediaItems:(MPMediaItemCollection *)mediaItemCollection { [mediaPicker dismissViewControllerAnimated:YES completion:NULL]; - NSMutableArray * 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 * urls = [[NSMutableArray alloc] initWithCapacity:numberOfItems]; 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) { diff --git a/ios/Classes/FileUtils.h b/ios/Classes/FileUtils.h index a4f7b77..47c57c3 100644 --- a/ios/Classes/FileUtils.h +++ b/ios/Classes/FileUtils.h @@ -24,6 +24,7 @@ typedef NS_ENUM(NSInteger, MediaType) { + (NSArray*) resolveType:(NSString*)type withAllowedExtensions:(NSArray*)allowedExtensions; + (MediaType) resolveMediaType:(NSString*)type; + (NSArray*) resolveFileInfo:(NSArray *)urls withData:(BOOL)loadData; ++ (NSURL*) exportMusicAsset:(NSString*)url withName: (NSString*)name; @end diff --git a/ios/Classes/FileUtils.m b/ios/Classes/FileUtils.m index 21bc214..2451aad 100644 --- a/ios/Classes/FileUtils.m +++ b/ios/Classes/FileUtils.m @@ -89,12 +89,75 @@ NSDictionary * fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil]; [files addObject: [[[FileInfo alloc] initWithPath: path - andName: [path lastPathComponent] - andSize: [NSNumber numberWithLongLong: [@(fileAttributes.fileSize) longLongValue] / 1024] - andData: loadData ? [NSData dataWithContentsOfFile:path options: 0 error:nil] : nil] toData]]; + andName: [path lastPathComponent] + andSize: [NSNumber numberWithLongLong: [@(fileAttributes.fileSize) longLongValue] / 1024] + andData: loadData ? [NSData dataWithContentsOfFile:path options: 0 error:nil] : nil] toData]]; } 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 diff --git a/pubspec.yaml b/pubspec.yaml index 6a3ae25..2129dba 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ 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. homepage: https://github.com/miguelpruivo/plugins_flutter_file_picker -version: 2.0.10 +version: 2.0.11 dependencies: flutter: