diff --git a/CHANGELOG.md b/CHANGELOG.md index d2c7fd5..9c95196 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 1.9.0 +Adds `clearTemporaryFiles()` that allows you to explicitly remove cached files — on Android applies typically to those picked from remote providers, on iOS _all_ picked files are cached. + ## 1.8.0+2 Updates podspec to use only PhotoGallery from DKImagePickerController (thanks @jamesdixon!) diff --git a/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java b/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java index d63492e..8ad6d8e 100644 --- a/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java +++ b/android/src/main/java/com/mr/flutter/plugin/filepicker/FilePickerPlugin.java @@ -146,6 +146,11 @@ public class FilePickerPlugin implements MethodChannel.MethodCallHandler, Flutte final MethodChannel.Result result = new MethodResultWrapper(rawResult); final HashMap arguments = (HashMap) call.arguments; + if (call.method != null && call.method.equals("clear")) { + result.success(FileUtils.clearCache(activity.getApplicationContext())); + return; + } + fileType = FilePickerPlugin.resolveType(call.method); isMultipleSelection = (boolean) arguments.get("allowMultipleSelection"); diff --git a/android/src/main/java/com/mr/flutter/plugin/filepicker/FileUtils.java b/android/src/main/java/com/mr/flutter/plugin/filepicker/FileUtils.java index fd22cec..5449f19 100644 --- a/android/src/main/java/com/mr/flutter/plugin/filepicker/FileUtils.java +++ b/android/src/main/java/com/mr/flutter/plugin/filepicker/FileUtils.java @@ -14,6 +14,7 @@ import android.util.Log; import android.webkit.MimeTypeMap; import java.io.BufferedOutputStream; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -211,12 +212,31 @@ public class FileUtils { return result; } + public static boolean clearCache(final Context context) { + try { + final File cacheDir = new File(context.getCacheDir() + "/file_picker/"); + final File[] files = cacheDir.listFiles(); + + if (files != null) { + for (final File file : files) { + file.delete(); + } + } + } catch (final Exception ex) { + Log.e(TAG, "There was an error while clearing cached files: " + ex.toString()); + return false; + } + return true; + } + public static String getUriFromRemote(final Context context, final Uri uri) { Log.i(TAG, "Caching file from remote/external URI"); FileOutputStream fos = null; final String fileName = FileUtils.getFileName(uri, context); - final String externalFile = context.getCacheDir().getAbsolutePath() + "/" + (fileName != null ? fileName : new Random().nextInt(100000)); + final String externalFile = context.getCacheDir().getAbsolutePath() + "/file_picker/" + (fileName != null ? fileName : new Random().nextInt(100000)); + + new File(externalFile).getParentFile().mkdirs(); try { fos = new FileOutputStream(externalFile); diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index cfefee6..29a3527 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,27 +1,8 @@ PODS: - - CropViewController (2.5.2) - - DKCamera (1.6.7) - - DKImagePickerController (4.2.2): - - DKImagePickerController/Camera (= 4.2.2) - - DKImagePickerController/Core (= 4.2.2) - - DKImagePickerController/ImageDataManager (= 4.2.2) - - DKImagePickerController/InlineCamera (= 4.2.2) - - DKImagePickerController/PhotoEditor (= 4.2.2) - - DKImagePickerController/PhotoGallery (= 4.2.2) - - DKImagePickerController/Resource (= 4.2.2) - - DKImagePickerController/Camera (4.2.2): - - DKCamera - - DKImagePickerController/Core - DKImagePickerController/Core (4.2.2): - DKImagePickerController/ImageDataManager - DKImagePickerController/Resource - DKImagePickerController/ImageDataManager (4.2.2) - - DKImagePickerController/InlineCamera (4.2.2): - - DKCamera - - DKImagePickerController/Core - - DKImagePickerController/PhotoEditor (4.2.2): - - CropViewController (~> 2.5) - - DKImagePickerController/Core - DKImagePickerController/PhotoGallery (4.2.2): - DKImagePickerController/Core - DKPhotoGallery @@ -50,7 +31,7 @@ PODS: - SDWebImage - SDWebImageFLPlugin - file_picker (0.0.1): - - DKImagePickerController + - DKImagePickerController/PhotoGallery - Flutter - FLAnimatedImage (1.0.12) - Flutter (1.0.0) @@ -70,8 +51,6 @@ DEPENDENCIES: SPEC REPOS: trunk: - - CropViewController - - DKCamera - DKImagePickerController - DKPhotoGallery - FLAnimatedImage @@ -87,11 +66,9 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_plugin_android_lifecycle/ios" SPEC CHECKSUMS: - CropViewController: 1aac40093c5739e60d992b04724a55d12a689a4c - DKCamera: a902b66921fca14b7a75266feb8c7568aa7caa71 DKImagePickerController: 4a3e7948a848c4348e600b3fe5ce41478835fa10 DKPhotoGallery: 0290d32343574f06eaa4c26f8f2f8a1035e916be - file_picker: f9134d4ef376b10e950694e6b96e81dafea9ceda + file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1 FLAnimatedImage: 4a0b56255d9b05f18b6dd7ee06871be5d3b89e31 Flutter: 0e3d915762c693b495b44d77113d4970485de6ec flutter_plugin_android_lifecycle: 47de533a02850f070f5696a623995e93eddcdb9b diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 7dd7764..e7ce601 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -246,30 +246,9 @@ files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh", - "${BUILT_PRODUCTS_DIR}/CropViewController/CropViewController.framework", - "${BUILT_PRODUCTS_DIR}/DKCamera/DKCamera.framework", - "${BUILT_PRODUCTS_DIR}/DKImagePickerController/DKImagePickerController.framework", - "${BUILT_PRODUCTS_DIR}/DKPhotoGallery/DKPhotoGallery.framework", - "${BUILT_PRODUCTS_DIR}/FLAnimatedImage/FLAnimatedImage.framework", - "${PODS_ROOT}/../.symlinks/flutter/ios/Flutter.framework", - "${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework", - "${BUILT_PRODUCTS_DIR}/SDWebImageFLPlugin/SDWebImageFLPlugin.framework", - "${BUILT_PRODUCTS_DIR}/file_picker/file_picker.framework", - "${BUILT_PRODUCTS_DIR}/flutter_plugin_android_lifecycle/flutter_plugin_android_lifecycle.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CropViewController.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKCamera.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKImagePickerController.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKPhotoGallery.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FLAnimatedImage.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Flutter.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageFLPlugin.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/file_picker.framework", - "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/flutter_plugin_android_lifecycle.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; diff --git a/example/lib/src/file_picker_demo.dart b/example/lib/src/file_picker_demo.dart index c680b89..94397a3 100644 --- a/example/lib/src/file_picker_demo.dart +++ b/example/lib/src/file_picker_demo.dart @@ -9,13 +9,14 @@ class FilePickerDemo extends StatefulWidget { } class _FilePickerDemoState extends State { + final GlobalKey _scaffoldKey = GlobalKey(); String _fileName; String _path; Map _paths; String _extension; bool _loadingPath = false; bool _multiPick = false; - FileType _pickingType; + FileType _pickingType = FileType.any; TextEditingController _controller = new TextEditingController(); @override @@ -54,10 +55,24 @@ class _FilePickerDemoState extends State { }); } + void _clearCachedFiles() { + FilePicker.clearTemporaryFiles().then((result) { + _scaffoldKey.currentState.showSnackBar( + SnackBar( + backgroundColor: result ? Colors.green : Colors.red, + content: Text((result + ? 'Temporary files removed with success.' + : 'Failed to clean temporary files')), + ), + ); + }); + } + @override Widget build(BuildContext context) { return new MaterialApp( home: new Scaffold( + key: _scaffoldKey, appBar: new AppBar( title: const Text('File Picker example app'), ), @@ -132,9 +147,17 @@ class _FilePickerDemoState extends State { ), new Padding( padding: const EdgeInsets.only(top: 50.0, bottom: 20.0), - child: new RaisedButton( - onPressed: () => _openFileExplorer(), - child: new Text("Open file picker"), + child: Column( + children: [ + new RaisedButton( + onPressed: () => _openFileExplorer(), + child: new Text("Open file picker"), + ), + new RaisedButton( + onPressed: () => _clearCachedFiles(), + child: new Text("Clear temporary files"), + ), + ], ), ), new Builder( diff --git a/ios/Classes/FilePickerPlugin.m b/ios/Classes/FilePickerPlugin.m index 4ef050b..7cf927b 100644 --- a/ios/Classes/FilePickerPlugin.m +++ b/ios/Classes/FilePickerPlugin.m @@ -47,6 +47,13 @@ } _result = result; + + if([call.method isEqualToString:@"clear"]) { + _result([NSNumber numberWithBool: [FileUtils clearTemporaryFiles]]); + _result = nil; + return; + } + NSDictionary * arguments = call.arguments; BOOL isMultiplePick = ((NSNumber*)[arguments valueForKey:@"allowMultipleSelection"]).boolValue; if([call.method isEqualToString:@"any"] || [call.method containsString:@"custom"]) { diff --git a/ios/Classes/FileUtils.h b/ios/Classes/FileUtils.h index 4ad476a..5c9839d 100644 --- a/ios/Classes/FileUtils.h +++ b/ios/Classes/FileUtils.h @@ -19,7 +19,8 @@ typedef NS_ENUM(NSInteger, MediaType) { MEDIA }; -@interface FileUtils : NSObject +@interface FileUtils : NSObject ++ (BOOL) clearTemporaryFiles; + (NSArray*) resolveType:(NSString*)type withAllowedExtensions:(NSArray*)allowedExtensions; + (MediaType) resolveMediaType:(NSString*)type; + (NSArray*) resolvePath:(NSArray *)urls; diff --git a/ios/Classes/FileUtils.m b/ios/Classes/FileUtils.m index 42bd9c7..fb59c9a 100644 --- a/ios/Classes/FileUtils.m +++ b/ios/Classes/FileUtils.m @@ -9,6 +9,24 @@ @implementation FileUtils ++ (BOOL) clearTemporaryFiles { + NSString *tmpDirectory = NSTemporaryDirectory(); + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSError *error; + NSArray *cacheFiles = [fileManager contentsOfDirectoryAtPath:tmpDirectory error:&error]; + + for (NSString *file in cacheFiles) { + error = nil; + [fileManager removeItemAtPath:[tmpDirectory stringByAppendingPathComponent:file] error:&error]; + if(error != nil) { + Log(@"Failed to remove temporary file %@, aborting. Error: %@", file, error); + return false; + } + } + Log(@"All temporary files clear"); + return true; +} + + (NSArray *) resolveType:(NSString*)type withAllowedExtensions:(NSArray*) allowedExtensions { if ([type isEqualToString:@"any"]) { diff --git a/lib/file_picker.dart b/lib/file_picker.dart index bef4db4..7e509a0 100644 --- a/lib/file_picker.dart +++ b/lib/file_picker.dart @@ -51,6 +51,17 @@ class FilePicker { return filePath != null ? File(filePath) : null; } + /// Asks the underlying platform to remove any temporary files created by this plugin. + /// + /// This typically relates to cached files that are stored in the cache directory of + /// each platform and it isn't required to invoke this as the system should take care + /// of it whenever needed. However, this will force the cleanup if you want to manage those on your own. + /// + /// Returns `true` if the files were removed with success, `false` otherwise. + static Future clearTemporaryFiles() async { + return _channel.invokeMethod('clear'); + } + /// Returns a `List` object from the selected files paths. /// /// This is an utility method that does the same of `getMultiFilePath()` but saving some boilerplate if diff --git a/pubspec.yaml b/pubspec.yaml index 521ec13..ec3a9cd 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: 1.8.0+2 +version: 1.9.0 dependencies: flutter: