本文共 3522 字,大约阅读时间需要 11 分钟。
之前有做一个工具集的微信小程序「开挂Lite」,但是由于小程序自身限制,没有办法实现下载文件的功能,只能把下载链接解析出来。而且受限于微信平台,小程序的审核是一件很麻烦的事情,因此有了将其APP化的想法。
自从去年Flutter横空出世后,我便一直关注它的发展,时隔一年后重新拾起,发现它的生态已经初具规模,于是决定采用Flutter重做一个「开挂Lite」。后期我也会不定时更新一些和Flutter有关的文章,希望大家可以多多支持。本文记录的便是我利用Flutter实现文件下载功能的过程。
完整源码可在公众号:「01二进制」后台回复:「Flutter 文件下载」获取
我们先看一下实现的效果:
iOS
Android
本demo的实现效果非常简单,就是点击一个按钮,然后下载文件,完成后提示用户是否打开文件。
在本 demo 中使用的 IDE 为 Android Studio ,同时使用到了以下几个库:
我们先新建一个空项目,然后将上述依赖添加到项目的 pubspec.yaml
文件,添加位置如下:
接下来我们可以在 Terminal 中输入 flutter packagesget
或者点击 IDE 左上角的 Packagesget
字样安装依赖。
然后将初始项目中的多余代码删除,并在中间添加一个按钮。
其中 _doDownloadOperation()
便是我们执行下载操作的方法,至此,前期准备工作结束。
虽然整个下载演示的过程非常简单,但还是有必要来分析整个下载的流程,如下图所示:
所以我们接下来要做的事情便是:
获取权限:网络权限、存储权限
获取下载路径
设置下载回调(用于监听下载过程)
这里使用到一个权限获取插件: permission_handler
,这个插件提供了跨平台(Android和iOS)的权限检查以及获取API,地址在:https://pub.flutter-io.cn/packages/permission_handler。在获取权限前我们需要先申明权限(Android)。
打开项目根目录下的 android/app/src/main/AndroidManifest.xml
文件,位置如下图所示:
然后添加我们需要使用的权限的申明,如下图所示:
接下来我们就可以写代码来获取所需的权限了。创建一个 _checkPermission()
函数用于判断权限是否给予。当然由于平台差异,我们需要判断其为Android平台,申请代码如下:
这里是使用的插件是 path_provider
,它是一个配合Dart的IO库以便在Flutter中实现文件读写的插件,Flutter中文网对该插件有着详细的介绍(https://flutterchina.club/reading-writing-files/),这里我们需要明白一个问题,就是iOS没有外置存储这一概念,因此需要对平台进行判断,代码如下:
通过上述代码我们便可以获取存储路径,但是如果我们不想把文件下载到存储路径呢?比如我就喜欢单独设置一个 /Download
路径专门用于保存下载文件,其实也很简单:
下载文件这里我找了一些资料,发现貌似只有一个 flutter_downloader
插件,也不知道是什么情况。该插件的配置过程也是挺复杂的,好在文档(https://pub.flutter-io.cn/packages/flutter_downloader)写的还算明白。这个插件可以实现后台下载,分别基于 Android 中的 WorkManager
和 iOS 中的 NSURLSessionDownloadTask
实现的。
接下来分别说下在iOS端和Android端的设置。
插件配置
iOS端配置
启用 background mode
想要执行这一步,我们在Xcode中打开该项目的 iOS module ,如下图所示:
然后双击左侧 Runner 选项,选择 Capabilities 选项,按图中所示启用 background mode
添加 sqlite 依赖库
文档中还提供了一些 可选配置 :
设置 HTTP 请求支持
为了安全起见,苹果官方已经默认不让开发者使用不安全的http通信协议了,而是建议开发者使用安全的https协议。若我们还是需要使用 http 协议需要做一些配置,文档中给了两种方式配置,一种是允许单个HTTP请求的域名,另一种是允许所有HTTP请求的域名,这里出于演示目的,选择第二种。
只需要在 Info.plist
文件中添加如下代码即可:
设置最大同时下载数
默认支持同时下载最多3个文件,如果你需要更改同样需要更改 Info.plist
设置下载完成通知
同样的,修改 Info.plist
:
Android端配置
说完了iOS端的配置,我们再来说下Android端的配置。在 AndroidManifest.xml
文件中添加如下代码:
位置如下:
还有其他类似于iOS端的可选配置,功能大同小异,这里就不说了,详见官网。
编写下载代码
配置结束后,其实下载的代码很简单:
当然我们需要提前引入 flutter_downloader
库
文档中还提供了其他API,譬如暂停下载、取消下载,这里就不再阐述了,文档已经写的很清楚了。
到这其实就已经完成了下载的逻辑,然而下载的逻辑是实现了,想要让用户用的明白,我们还需要加一些提示信息,就像开头demo展示的有下载进度条和下载完成的提示框,接下来我们就来为下载设置这些提示信息吧。
这里以对话框和进度条的形式展现下载过程,我们使用到了 progress_dialog
这个插件,可以很方便的显示出一个下载对话框,地址是https://pub.flutter-io.cn/packages/progress_dialog。
使用 progress_dialog
插件非常简单,首先我们引入依赖文件:
然后创建一个对话框:
如果想要创建一个下载提示对话框的话我们只需要在合适的地方初始化这个Dialog:
然后执行 pr.show();
即可显示对话框。取消这个对话框也非常的简单,只需执行 pr.hide();
如果想要更新对话框中的提示信息,比如下载进度,只需执行下述代码:
同时我们还可以通过 isShowing()
函数判断对话框是否显示
是不是非常方便呢?
有了展示的对话框,下一步自然就是获取下载进度了,好在 flutter_downloader
已经给我们提供了一个下载回调,我们可以在下面的这个回调函数中更新我们的UI。
其中 id 是下载任务的id, status 是当前id下载任务的状态,有 undefined,enqueued,running,complete,failed,canceled,paused
这几种状态, progress 便是当前id下载任务的进度。
这里方便起见我选择在 initState()
函数中初始化下载回调函数和对话框:
然后我们需要根据下载的状态分情况讨论
其实到这里下载文件的操作就算结束了,但是通常在下载完成后APP都会提示你是否要打开,于是在这我们干脆 就拓展一下,实现打开我们已经下载好的文件。
那如何打开已经下载好的文件呢?插件已经提供好了打开下载文件的API,我们只需要像下面这样使用就可以了。
想要打开已经下载完成的文件,我们必须要要确保文件已经下载好了。所以我们需要紧接上面的代码中判断下载完成的函数。这里我们以弹出对话框的形式询问用户是否打开文件。
代码如下
对话框的使用上述代码已经注释的很详细了。
至此,我们便使用 Flutter 完成了一个完整的下载文件的过程了。
总的来说,利用Flutter实现文件下载的思路还是很清楚的, 获取权限->获取路径->开始下载->监听下载进程 ,一气呵成。同时,借助于 Flutter 社区的快速发展,已经有很多优秀的开发者开发了一些非常好用的插件,凭借着这些插件我们可以快速实现自己想要的功能。在这个demo中整个界面编写+逻辑实现总共也才 223 行代码,虽然界面有些丑陋,但考虑到Dart语言的迷之缩进这个行数也是很短的了。
最后想要源码可以扫描下面的二维码关注我的公众号「01二进制」,后台回复「Flutter 文件下载」即可,后期我也会不定时更新一些和Flutter有关的文章,希望大家可以多多支持。
原文
转载地址:http://byzii.baihongyu.com/