Flutetr 使用 flutter_downloader插件 实现文件下载 笔记及踩坑
完整代码-点击下载
所用到的依赖包:
# 检查权限
permission_handler: ^3.3.0
# 获取路径
path_provider: ^1.4.0
# 文件下载
flutter_downloader: ^1.3.1
# 进度提示框
progress_dialog: ^1.1.0+1
flutter1.12以下版本按照以前的版本进行配置即可。修改如下:
1.删除 android/app/src/main/java/[your/package/name]/MainActivity.java。如果没有添加过代码,可以直接删掉 [your/package/name]整个包结构,
因为里面只有MainActivity.java。
2.打开 android/app/src/main/AndroidManifest.xml.
3.从 application 标签中删除 FlutterApplication 的引用
修改之前的
<application
name="io.flutter.FlutterApplication"
>
<!-- code omitted -->
</application>
修改以后的
<application
>
<!-- code omitted -->
</application>
4. 修改AndroidManifest里的 activity,MainActivity 改为 FlutterActivity (前三行),
android:launchMode直接移除
改完后的
android:name="io.flutter.embedding.android.FlutterActivity"
android:theme="@android:style/Theme.Black.NoTitleBar"
5.更新 Splash 页(如果需要初始行为)
删除所有键为 android:name="io.flutter.app.android.SplashScreenUntilFirstFrame" 的<meta-data> 标签
-----------------------------------分割线-------------------------------------------------------------------
重要! !新建一个java类 或者 kotlin类,我这里时java类 1.12及以上版本 不需要操作这一步
继承FlutterApplication 并实现PluginRegistry.PluginRegistrantCallback ,否则下载时会报PluginRegistrantCallback 未实现。
重要! ! 注册刚才创建的实现类 1.12及以上版本 不需要操作这一步
第三步
在AndroidManifest.XML中加入 存储权限
< uses-permission android :name ="android.permission.REQUEST_INSTALL_PACKAGES" /> < uses-permission android :name ="android.permission.WRITE_EXTERNAL_STORAGE" /> < uses-permission android :name ="android.permission.READ_EXTERNAL_STORAGE" />
并加入 application 中加入如下配置:
< provider android :name ="vn.hunghd.flutterdownloader.DownloadedFileProvider" android :authorities ="${applicationId}.flutter_downloader.provider" android :exported ="false" android :grantUriPermissions ="true" > < meta-data android :name ="android.support.FILE_PROVIDER_PATHS" android :resource ="@xml/provider_paths" /> </ provider > < provider android :name ="androidx.work.impl.WorkManagerInitializer" android :authorities ="${applicationId}.workmanager-init" android :enabled ="false" android :exported ="false" /> < provider android :name ="vn.hunghd.flutterdownloader.FlutterDownloaderInitializer" android :authorities ="${applicationId}.flutter-downloader-init" android :exported ="false" > <!-- changes this number to configure the maximum number of concurrent tasks --> < meta-data android :name ="vn.hunghd.flutterdownloader.MAX_CONCURRENT_TASKS" android :value ="5" /> </ provider >
配置插件的提示语为中文 默认英文 替换即可
检查权限、请求权限
// 检查权限 方法1 Future<bool> _checkPermission() async { if (Theme. of ( context ). platform == TargetPlatform. android ) { PermissionStatus permission = await PermissionHandler () .checkPermissionStatus(PermissionGroup. storage ); if (permission != PermissionStatus. granted ) { Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler () .requestPermissions([PermissionGroup. storage ]); if (permissions[PermissionGroup. storage ] == PermissionStatus. granted ) { return true ; } } else { return true ; } } else { return true ; } return false ; }
//是否有权限 方法2 // Future<bool> checkPermission() async { // print(" 检查权限 "); // bool res = await SimplePermissions.checkPermission( // Permission.WriteExternalStorage); // return res; // } // // // 打开权限 // Future<PermissionStatus> requestPermission() async { // print(" 打开权限 "); // return SimplePermissions.requestPermission(Permission.WriteExternalStorage); // }
获取本地路径
// 获取路径 Future<String> _findLocalPath() async { final directory = Theme. of ( context ). platform == TargetPlatform. android ? await getExternalStorageDirectory() : await getApplicationSupportDirectory(); return directory. path ; }
插件初始化 重要! 在initState中调用
//初始化
Future< void > _init() async { await FlutterDownloader. initialize (); IsolateNameServer. registerPortWithName ( _port . sendPort , 'downloader_send_port' ); _port .listen(( dynamic data) { print( 'UI Isolate Callback: $data ' ); String id = data[ 0 ]; DownloadTaskStatus status = data[ 1 ]; int progress = data[ 2 ]; print( " 状态 : $status " ); print( " 进度 : $progress " ); print( "id == downloadId: ${id == downloadId } " ); }); // 下载回调 FlutterDownloader. registerCallback ( downloadCallback ); // 定义 保存目录路径 (这里设置为 当前 app 目录下的 Download ) _localPath = ( await _findLocalPath()) + '/Download' ; // 保存目录 final savedDir = Directory ( _localPath ); bool hasExisted = await savedDir.exists(); // 判断目录是否存在 不存在则创建 if (!hasExisted) { savedDir.create(); } }
static void downloadCallback ( String id, DownloadTaskStatus status, int progress) { print( ' 背景分离回调 : 任务 id ( $id ) \n 状态 ( $status ) \n 进度 ( $progress )' ); final SendPort send = IsolateNameServer. lookupPortByName ( 'downloader_send_port' ); send.send([id, status, progress]); }
下载文件 在点击事件中使用 注意:点击事件要异步 async
也可以写成一个异步方法
if ( await _checkPermission()) { await FlutterDownloader. initialize (); final taskId = await FlutterDownloader. enqueue ( url: _link , savedDir: _localPath , showNotification: true , // show download progress in status bar (for Android) openFileFromNotification: true , // click on notification to open downloaded file (for Android) ); downloadId = taskId; }