让webview支持下载
最近在开发的过程中遇到一个需求,那就是让 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支持下载相关推荐
- 让 Android WebView 支持文件下载的三种解决方案
最近在开发的过程中遇到一个需求,那就是让 WebView 支持文件下载,比如说下载 apk.WebView 默认是不支持下载的,需要开发者自己实现.既然 PM 提出了需求,那咱就撸起袖子干呗,于是乎在 ...
- 三种方式让 Android WebView 支持文件下载
三种方式让 Android WebView 支持文件下载 最近在开发的过程中遇到一个需求,那就是让 WebView 支持文件下载,比如说下载 apk.WebView 默认是不支持下载的,需要开发者自己 ...
- Android WebView支持文件下载之调起浏览器下载(Java与Kotlin版)
使用函数 WebView默认没有开启文件下载的功能,如果想使得WebView能够支持文件下载,就需要给WebView设置下载监听器setDownloadListener,每当有文件需要下载时,就会回调 ...
- 简单提升微信打开浏览器速度(启用原生 WebView 支持)
简单提升微信打开浏览器速度(启用原生 WebView 支持) 前言 启用原生 WebView 支持 小结 前言 国内的安卓系统环境真的是一言难尽,各种后台全家桶,在国内没有苹果的那种消息推送,性能较强 ...
- Android WebView 支持H5图片上传input type=file
2019独角兽企业重金招聘Python工程师标准>>> Android WebView 缓存处理 Android WebView 支持H5图片上传<input type=&qu ...
- Advanced Download Manager(ADM) – 来自俄罗斯的 Android 下载神器,支持下载 BT 种子
介绍: [Advanced Download Manager](Advanced Download Manager) 是一款 Android 下的下载管理器,支持最多 9 个线程进行后台下载,并且有& ...
- Cef开发学习 - Windows平台简易的Cef浏览器,支持下载管理和多标签管理
Cef开发学习 - Windows平台简易的Cef浏览器,支持下载管理和多标签管理 PS:本系列文章主要学习介绍Cef开发相关的内容. 文章目录 Cef开发学习 - Windows平台简易的Cef浏览 ...
- apache 支持下载rar格式文件问题
默认apache 不支持下载rar格式文件 这里涉及到mime 模块问题 需要添加 addtype application/octet-stream rar 这个语句 或者写入mime.types ...
- webview进行下载踩坑记录
webview下载操作的踩坑记录 背景记录 由于公司需要, 需要在在webview中执行下载操作, 而且下载完成之后还需要跳转到自动安装页面~~~~ 接下来就是踩坑报告 1.webview执行下载操作 ...
最新文章
- linux03:系统常用的命令
- linux设置docker自动启动,CentOS7安装Docker配置服务端和容器自启动
- Django - 两周从入门到熟练工
- Linux终端的概念
- 黑客Alex Tapanaris与PDF文档
- java技术cad转图片_一键完成百张图纸转换,教你最简单CAD转JPG格式方法,只需三步...
- winvnc源码阅读笔记(四)---------vncDesktopThread线程
- excel 删除重复行数据,列数据
- 新人小白的第一次天池比赛感受
- OpenCV——将图片转换成视频
- 通过“单键锁配置法”实现访问控制
- 3.1.2随机梯度下降法
- OCR手写数字识别什么软件好用?介绍一种
- 【FFmpeg】ffplay 源代码结构图+播放模式分析
- python opencv resize函数_python cv2.resize函数high和width注意事项说明
- OS模块--批量修改文件名字(一)创建和修改文件路径
- SpringSecurity: 不能混用authorizeRequests和6.0里的authorizeHttpReuests
- imp 00017 由于 oracle 错误 6550,imp 导入dmp文件报错 IMP-00017: 由于 ORACLE 异常 20005 求大神!...
- excel单元格内容拆分_EXCEL单元格里提取、删除或替换部分内容
- Nvidia Agx Xavier平台MIPI CSI-DHPY驱动调试