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

跳转浏览器下载

使用系统的下载服务

自定义下载任务

有了思路就好办了,下面介绍具体实现。

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

mWebView.setDownloadListener(new DownloadListener() {

@Override

public 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 {

@Override

public 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 {

// 传递两个参数:URL 和 目标路径

private String url;

private String destPath;

@Override

protected void onPreExecute() {

log.info("开始下载");

}

@Override

protected 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;

}

@Override

protected 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() {

@Override

public 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);

}

});

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

可以看出,这三种下载方式各有特点,大家可以根据需要选择,欢迎留言交流~~

android webview最新版下载,Android WebView 支持文件下载的几种方式相关推荐

  1. java 下载 docx文件_Java文件下载的几种方式.docx

    Java文件下载的几种方式文章分类:/blogs/category/javaJava编程 Java文件下载的几种方式Java代码 public?HttpServletResponse?download ...

  2. android studio最新版下载,Android Studio mac版-Android Studio for mac下载 V4.2.1-PC6苹果网

    Android Studio mac版为在各种类型的Android设备上构建应用程序提供了最快的工具.Android Studio mac版完全免费,跨平台支持Win/Mac/Linux,是替代 Ec ...

  3. Android源码 —— 构建下载Android源码的虚拟机环境(Win7+VMware12+Ubuntu16)

    Android源码 -- 构建下载Android源码的虚拟机环境(Win7+VMware12+Ubuntu16) 本文将介绍从Win7系统开始一步步构建下载Android源码的虚拟机环境: **1.使 ...

  4. android平台下OpenGL ES 3.0绘制立方体的几种方式

    OpenGL ES 3.0学习实践 android平台下OpenGL ES 3.0从零开始 android平台下OpenGL ES 3.0绘制纯色背景 android平台下OpenGL ES 3.0绘 ...

  5. python怎么下载图片怎么保存到本地_详解Python下载图片并保存本地的两种方式

    一:使用Python中的urllib类中的urlretrieve()函数,直接从网上下载资源到本地,具体代码: import os,stat import urllib.request img_url ...

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

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

  7. 烹饪冒险最新版下载android,烹饪冒险最新版下载安卓

    烹饪冒险最新版下载安卓是一款超级有趣的模拟经营类手机游戏.玩家可以在游戏里面经营自己的店铺,可以在游戏里面给客人送上很多的菜肴哦.游戏里面还有很多的游戏关卡等着大家来进行游戏的哦. 烹饪冒险最新版下载 ...

  8. android 显示天气插件下载,Android天气插件

    Android天气插件 天气插件Android SDK,包括实况天气.空气质量.灾害预警.生活指数等天气内容,支持在Android应用任意位置加入天气内容,并可生成天气频道页面. 下载 # 适配版本 ...

  9. Android 安装最新版的Android Studio软件(最新版3.6)

    Android Studio的安装使用(基于最新版本3.6) 安装Android studio 一.安装JDK8(以上) 二.官网下载Android studio并安装 三.通过终端配置Mac环境 1 ...

  10. 使用WebView实现文件下载的两种方式

    在应用中,通常会使用到文件下载功能,一般我们都是写一个下载操作工具类,在异步任务中执行下载功能. 今天我们来看下如何使用WebView的文件下载功能!方法1,自定义下载操作 1. 先来布局<Re ...

最新文章

  1. 重要的mysql语句用法
  2. ElasticSearch学习资料
  3. 更改Ubuntu终端复制和粘贴的快捷键
  4. php5.5开发环境配置,windows下配置php5.5开发环境及开发扩展
  5. Ubuntu中出现“Could not get lock /var/lib/dpkg/lock”的解决方法
  6. vue3中setup()函数的使用一
  7. Swift中的#pragma mark?
  8. 链表+启发式合并(bzoj 1483: [HNOI2009]梦幻布丁)
  9. 从C#开发人员到Windows Phone 7高级开发人员只需3周 – 序
  10. matplotlib实现数据的可视化
  11. 关于‘挖矿’minerd
  12. 丁磊推荐《你的灯亮着吗》为三大管理必读书
  13. 全球及中国熔融碳酸盐燃料电池行业市场消费量调研及未来前瞻报告2022-2028年
  14. qt5 开发及实例(第4版)_张厚粲现代心理与教育统计学第4版配套章节题库
  15. 重置计算机的本地策略,Win10怎样重置组策略/安全策略|Win10重置组策略/安全策略教程...
  16. 数据库的查询、视图和游标
  17. 【MySQL】听柠檬班公开课后,学习笔记及作业(一)
  18. bibtex引用参考文献排版格式
  19. ​​​LabVIEW视觉软件使用什么算法
  20. 什么是扇入?什么是扇出?

热门文章

  1. python3项目源代码下载_资源整理 | 36个惊人的Python开源项目,都在这了
  2. 写DM9000网卡芯片驱动的预备知识
  3. 经纬度WGS84地理坐标系转换成CGCS2000坐标系步骤
  4. 步数精灵v4.0霸占好友排行榜首位 安卓版
  5. 无人车传感器 IMU 深入剖析
  6. python去重脚本
  7. 内存颗粒和闪存颗粒的区别_什么是内存颗粒以及内存颗粒的种类和差别
  8. ISAPI报警模块流程
  9. 查看linux内存大小
  10. 阿里巴巴实习生 招聘内推