Flutetr 实现文件下载 笔记及踩坑

mac2023-02-01  41

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 以后 对Android原生的api做了一些调整 已经自动注册,导致新版的flutter里 回调不生效,因此 需要改一些东西,https://github.com/flutter/flutter/wiki/Upgrading-pre-1.12-Android-projects 可了解更多1.12版本开始的迁移

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>

 

 

配置插件的提示语为中文  默认英文 替换即可

 

检查权限、请求权限

// 检查权限 方法1Future<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;}

 

 

最新回复(0)