最近在开发的过程中遇到一个需求,那就是让 WebView 支持文件下载,比如说下载 apk。WebView 默认是不支持下载的,需要开发者自己实现。既然 PM 提出了需求,那咱就撸起袖子干呗,于是乎在网上寻找了几种方法,主要思路有这么几种:

  • 跳转浏览器下载
  • 使用系统的下载服务
  • 自定义下载任务

有了思路就好办了,下面介绍具体实现。
要想让 WebView 支持下载,需要给 WebView 设置下载监听器 setDownloadListener,DownloadListener 里面只有一个方法 onDownloadStart,每当有文件需要下载时,该方法就会被回调,下载的 URL 通过方法参数传递,我们可以在这里处理下载事件。

mWebView.setDownloadListener(new DownloadListener() {@Overridepublic void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {// TODO: 2017-5-6 处理下载事件}
});

1. 跳转浏览器下载

这种方式最为简单粗暴,直接把下载任务抛给浏览器,剩下的就不用我们管了。缺点是无法感知下载完成,当然就没有后续的处理,比如下载 apk 完成后打开安装界面。

    private void downloadByBrowser(String url) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addCategory(Intent.CATEGORY_BROWSABLE);intent.setData(Uri.parse(url));startActivity(intent);}

2. 使用系统的下载服务

DownloadManager 是系统提供的用于处理下载的服务,使用者只需提供下载 URI 和存储路径,并进行简单的设置。DownloadManager 会在后台进行下载,并且在下载失败、网络切换以及系统重启后尝试重新下载。

     private void downloadBySystem(String url, String contentDisposition, String mimeType) {// 指定下载地址DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));// 允许媒体扫描,根据下载的文件类型被加入相册、音乐等媒体库request.allowScanningByMediaScanner();// 设置通知的显示类型,下载进行时和完成后显示通知request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);// 设置通知栏的标题,如果不设置,默认使用文件名
//        request.setTitle("This is title");// 设置通知栏的描述
//        request.setDescription("This is description");// 允许在计费流量下下载request.setAllowedOverMetered(false);// 允许该记录在下载管理界面可见request.setVisibleInDownloadsUi(false);// 允许漫游时下载request.setAllowedOverRoaming(true);// 允许下载的网路类型request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);// 设置下载文件保存的路径和文件名String fileName  = URLUtil.guessFileName(url, contentDisposition, mimeType);log.debug("fileName:{}", fileName);request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName);
//        另外可选一下方法,自定义下载路径
//        request.setDestinationUri()
//        request.setDestinationInExternalFilesDir()final DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);// 添加一个下载任务long downloadId = downloadManager.enqueue(request);log.debug("downloadId:{}", downloadId);}

这样我们就添加了一项下载任务,然后就静静等待系统下载完成吧。还要注意一点,别忘了添加读写外置存储权限和网络权限哦~
那怎么知道文件下载成功呢?系统在下载完成后会发送一条广播,里面有任务 ID,告诉调用者任务完成,通过 DownloadManager 获取到文件信息就可以进一步处理。

    private class DownloadCompleteReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {log.verbose("onReceive. intent:{}", intent != null ? intent.toUri(0) : null);if (intent != null) {if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(intent.getAction())) {long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);log.debug("downloadId:{}", downloadId);DownloadManager downloadManager = (DownloadManager) context.getSystemService(DOWNLOAD_SERVICE);String type = downloadManager.getMimeTypeForDownloadedFile(downloadId);log.debug("getMimeTypeForDownloadedFile:{}", type);if (TextUtils.isEmpty(type)) {type = "*/*";}Uri uri = downloadManager.getUriForDownloadedFile(downloadId);log.debug("UriForDownloadedFile:{}", uri);if (uri != null) {Intent handlerIntent = new Intent(Intent.ACTION_VIEW);handlerIntent.setDataAndType(uri, type);context.startActivity(handlerIntent);}}}}}// 使用DownloadCompleteReceiver receiver = new DownloadCompleteReceiver();IntentFilter intentFilter = new IntentFilter();intentFilter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);registerReceiver(receiver, intentFilter);

Ok,到这里,利用系统服务下载就算结束了,简单总结一下。我们只关心开始和完成,至于下载过程中的暂停、重试等机制,系统已经帮我们做好了,是不是非常友好?

3. 自定义下载任务

有了下载链接就可以自己实现网络部分,我在这儿自定义了一个下载任务,使用 HttpURLConnection 和 AsyncTask 实现,代码还是比较简单的。

    private class DownloadTask extends AsyncTask<String, Void, Void> {// 传递两个参数:URL 和 目标路径private String url;private String destPath;@Overrideprotected void onPreExecute() {log.info("开始下载");}@Overrideprotected Void doInBackground(String... params) {log.debug("doInBackground. url:{}, dest:{}", params[0], params[1]);url = params[0];destPath = params[1];OutputStream out = null;HttpURLConnection urlConnection = null;try {URL url = new URL(params[0]);urlConnection = (HttpURLConnection) url.openConnection();urlConnection.setConnectTimeout(15000);urlConnection.setReadTimeout(15000);InputStream in = urlConnection.getInputStream();out = new FileOutputStream(params[1]);byte[] buffer = new byte[10 * 1024];int len;while ((len = in.read(buffer)) != -1) {out.write(buffer, 0, len);}in.close();} catch (IOException e) {log.warn(e);} finally {if (urlConnection != null) {urlConnection.disconnect();}if (out != null) {try {out.close();} catch (IOException e) {log.warn(e);}}}return null;}@Overrideprotected void onPostExecute(Void aVoid) {log.info("完成下载");Intent handlerIntent = new Intent(Intent.ACTION_VIEW);String mimeType = getMIMEType(url);Uri uri = Uri.fromFile(new File(destPath));log.debug("mimiType:{}, uri:{}", mimeType, uri);handlerIntent.setDataAndType(uri, mimeType);startActivity(handlerIntent);}}private String getMIMEType(String url) {String type = null;String extension = MimeTypeMap.getFileExtensionFromUrl(url);log.debug("extension:{}", extension);if (extension != null) {type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);}return type;}//  使用mWebView.setDownloadListener(new DownloadListener() {@Overridepublic void onDownloadStart(String url, String userAgent, String contentDisposition, String mimeType, long contentLength) {String fileName = URLUtil.guessFileName(url, contentDisposition, mimeType);String destPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + File.separator + fileName;new DownloadTask().execute(url, destPath);}});

优势是我们可以感知下载进度,处理开始、取消、失败、完成等事件,不足之处是对下载的控制不如系统服务,必须自己处理网络带来的问题。

让webview支持下载相关推荐

  1. 让 Android WebView 支持文件下载的三种解决方案

    最近在开发的过程中遇到一个需求,那就是让 WebView 支持文件下载,比如说下载 apk.WebView 默认是不支持下载的,需要开发者自己实现.既然 PM 提出了需求,那咱就撸起袖子干呗,于是乎在 ...

  2. 三种方式让 Android WebView 支持文件下载

    三种方式让 Android WebView 支持文件下载 最近在开发的过程中遇到一个需求,那就是让 WebView 支持文件下载,比如说下载 apk.WebView 默认是不支持下载的,需要开发者自己 ...

  3. Android WebView支持文件下载之调起浏览器下载(Java与Kotlin版)

    使用函数 WebView默认没有开启文件下载的功能,如果想使得WebView能够支持文件下载,就需要给WebView设置下载监听器setDownloadListener,每当有文件需要下载时,就会回调 ...

  4. 简单提升微信打开浏览器速度(启用原生 WebView 支持)

    简单提升微信打开浏览器速度(启用原生 WebView 支持) 前言 启用原生 WebView 支持 小结 前言 国内的安卓系统环境真的是一言难尽,各种后台全家桶,在国内没有苹果的那种消息推送,性能较强 ...

  5. Android WebView 支持H5图片上传input type=file

    2019独角兽企业重金招聘Python工程师标准>>> Android WebView 缓存处理 Android WebView 支持H5图片上传<input type=&qu ...

  6. Advanced Download Manager(ADM) – 来自俄罗斯的 Android 下载神器,支持下载 BT 种子

    介绍: [Advanced Download Manager](Advanced Download Manager) 是一款 Android 下的下载管理器,支持最多 9 个线程进行后台下载,并且有& ...

  7. Cef开发学习 - Windows平台简易的Cef浏览器,支持下载管理和多标签管理

    Cef开发学习 - Windows平台简易的Cef浏览器,支持下载管理和多标签管理 PS:本系列文章主要学习介绍Cef开发相关的内容. 文章目录 Cef开发学习 - Windows平台简易的Cef浏览 ...

  8. apache 支持下载rar格式文件问题

    默认apache 不支持下载rar格式文件 这里涉及到mime 模块问题 需要添加 addtype application/octet-stream rar  这个语句 或者写入mime.types ...

  9. webview进行下载踩坑记录

    webview下载操作的踩坑记录 背景记录 由于公司需要, 需要在在webview中执行下载操作, 而且下载完成之后还需要跳转到自动安装页面~~~~ 接下来就是踩坑报告 1.webview执行下载操作 ...

最新文章

  1. linux03:系统常用的命令
  2. linux设置docker自动启动,CentOS7安装Docker配置服务端和容器自启动
  3. Django - 两周从入门到熟练工
  4. Linux终端的概念
  5. 黑客Alex Tapanaris与PDF文档
  6. java技术cad转图片_一键完成百张图纸转换,教你最简单CAD转JPG格式方法,只需三步...
  7. winvnc源码阅读笔记(四)---------vncDesktopThread线程
  8. excel 删除重复行数据,列数据
  9. 新人小白的第一次天池比赛感受
  10. OpenCV——将图片转换成视频
  11. 通过“单键锁配置法”实现访问控制
  12. 3.1.2随机梯度下降法
  13. OCR手写数字识别什么软件好用?介绍一种
  14. 【FFmpeg】ffplay 源代码结构图+播放模式分析
  15. python opencv resize函数_python cv2.resize函数high和width注意事项说明
  16. OS模块--批量修改文件名字(一)创建和修改文件路径
  17. SpringSecurity: 不能混用authorizeRequests和6.0里的authorizeHttpReuests
  18. imp 00017 由于 oracle 错误 6550,imp 导入dmp文件报错 IMP-00017: 由于 ORACLE 异常 20005 求大神!...
  19. excel单元格内容拆分_EXCEL单元格里提取、删除或替换部分内容
  20. Nvidia Agx Xavier平台MIPI CSI-DHPY驱动调试

热门文章

  1. Javascript---AJAX
  2. 数据库作业6:SQL练习3 - SELECT
  3. Ubuntu 网络连接不上-右上角WiFi标志都没有
  4. 【理论 | 代码】机器学习分类与回归性能评估指标大全
  5. Linux查看端口占用情况的几种方式
  6. 通过国家码切换默认输入法
  7. “真实姓名的图表地图集原镇名
  8. 大金牙破碎机锤头高度耐磨的中国髻
  9. thymeleaf 遍历map
  10. Jenkins+钉钉,实现Jenkins的构建结果直接发送到钉钉群