Flutetr 使用flutter_downloader插件  实现文件下载 笔记及踩坑 

所用到的依赖包:

可前往 PUB开源仓库拉取 https://pub.flutter-io.cn/

# 权限
permission_handler: ^3.3.0
# 获取路径
path_provider: ^1.4.0
# 文件下载
flutter_downloader: ^1.3.1

 

  1. 重要!!新建一个java类 或者 kotlin类,我这里时java类

继承FlutterApplication 并实现PluginRegistry.PluginRegistrantCallback ,否则下载时会报PluginRegistrantCallback 未实现。

 

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

  1. 重要!! 注册刚才创建的实现类

 

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

第三步

在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>

 

 

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

 

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

检查权限、请求权限

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

 

 

  1. 下载文件 在点击事件中使用  注意:点击事件要异步 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;
}

 

博主的完整示例:

import 'dart:io';
import 'dart:isolate';
import 'dart:ui';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:url_launcher/url_launcher.dart';
//import 'package:simple_permissions/simple_permissions.dart';
//import 'tools/ToolsClass.dart';
//import 'tools/ToolsWidget.dart';
void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ReceivePort _port = ReceivePort();
  String downloadId;
  String _link = "http://apk.gfan.net.cn/index.php?c=api&m=down&src=wap&apk=84260";
//  String _link = "https://i.loli.net/2019/10/18/gE3PTycd9SF5VqY.jpg";
  String _localPath;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    _init();
  }
  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]);
  }

//  //是否有权限
//  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<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;
  }


  //获取路径
  Future<String> _findLocalPath() async {
    // 因为Apple没有外置存储,所以第一步我们需要先对所在平台进行判断
    // 如果是android,使用getExternalStorageDirectory
    // 如果是iOS,使用getApplicationSupportDirectory
    final directory = Theme.of(context).platform == TargetPlatform.android
        ? await getExternalStorageDirectory()
        : await getApplicationSupportDirectory();
    return directory.path;
  }


  int count = 0;

  @override
  Widget build(BuildContext context) {
    List list = ["123","222","qeqw"];
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body:Column(
        children: <Widget>[
//          Text("集合转字符串"+ToolsClass.listToString(list,",")),
//          Text("原集合:"+list.toString()),
//          Text("字符串转集合:"+ToolsClass.stringToList("123,555,999,888", ",").toString()),
//          Text("字符串判空:"+ToolsClass.textIsNot(null).toString()),
          FlatButton(
            child:Text('点击我下载'),
            onPressed: () 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;
              }
            },
          ),
//          numRunturn(
//              count: count,
//              leftRightBtnWidth: 30,
//              inputWidth: 30,
//              changed:(v){
//                setState(() {
//                  count = v;
//                  print("num page:"+v.toString());
//                },);
//              },
//          ),
        ],
      ),
    );
  }
}

 

相关文章: