Android 让 WebView 响应下载点击事件

来源:互联网 发布:中古欧洲民谣知乎 编辑:程序博客网 时间:2024/06/08 19:17

最近项目中的邮件模块需要与第三方进行对接并且利用 WebView 展示,测试的时候发现点击附件下载没有任何反应,但是 ios 端却可以直接点击预览,客户非常不开心。

百度之后发现 WebView 默认不提供下载响应(应该是为了安全性考虑),只要设置了webview.setDownloadListener() 方法我们就可以下载了。既然这么简单我们就赶紧试试吧。

webView.setDownloadListener(new DownloadListener() {    @Override    public void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {        // url 你要访问的下载链接        // userAgent 是HTTP请求头部用来标识客户端信息的字符串        // contentDisposition 为保存文件提供一个默认的文件名        // mimetype 该资源的媒体类型        // contentLength 该资源的大小        // 这几个参数都是可以通过抓包获取的        // 用手机默认浏览器打开链接        Uri uri = Uri.parse(url);        Intent intent = new Intent(Intent.ACTION_VIEW, uri);        startActivity(intent);    }});

我们这里先测试用系统默认的浏览器进行下载。在大多数的情况下这样已经满足要求了,网上的方法也确实是这样的,我怀着满心欢喜打开了项目,然后点击下载:”网页无法打开“。很郁闷。我又用手机的浏览器测试了一下,的的确确是没有问题的。那么问题出在哪呢?

继续抓包,发现了异样。在浏览器中,访问邮件与点击下载获取的 cookie 值是相同的,而在 WebView 中这两个值是不同的。似乎找到原因了!这个下载链接是需要验证 cookie 的。可是怎么把 WebView 的 cookie 传递给系统的浏览器呢?这个我确实不会,那么不如自己写个方法下载吧。

首先我们要获取到 cookie:

webView.setWebViewClient(new WebViewClient() {    @Override    public boolean shouldOverrideUrlLoading(WebView view, String url) {        view.loadUrl(url);        return true;    }    @Override    public void onPageFinished(WebView view, String url) {        super.onPageFinished(view, url);        CookieManager cookieManager = CookieManager.getInstance();        cookieStr = cookieManager.getCookie(url); // 获取到cookie字符串值    }});

然后我们自己写个下载类:

private class DownloadTask extends AsyncTask<String, Void, String> {        @Override        protected String doInBackground(String... params) {            String url = params[0]; // 要访问的链接            String fileName = params[1]; // 文件名            if (TextUtils.isEmpty(url)) {                return null;            }            File directory = Environment.getExternalStorageDirectory();            File file = new File(directory, fileName);            if (file.exists()) {                return fileName;            }            // 下载文件            try {                URL myFileUrl = new URL(url);                HttpURLConnection conn = (HttpURLConnection) myFileUrl                        .openConnection();                // 携带cookie请求,要写在请求开始之前                conn.addRequestProperty("Cookie", cookieStr);                conn.setDoInput(true);                conn.connect();                InputStream is = conn.getInputStream();                // 我们把文件保存在sd卡根目录                FileOutputStream out = new FileOutputStream(Environment.getExternalStorageDirectory().getAbsolutePath() + "/" +fileName);                byte[] buffer = new byte[1024];                int r;                while ((r = is.read(buffer)) > 0) {                    out.write(buffer, 0, r);                    out.flush();                }                is.close();                out.close();            } catch (Exception e) {                e.printStackTrace();                return null;            }            return fileName;        }        @Override        protected void onPostExecute(String s) {            super.onPostExecute(s);            // 这里可以对下载好的文件进行打开等操作        }    }

启动下载:

@Overridepublic void onDownloadStart(String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {    // 获取文件名称,在我的项目测试之后发现得到的是乱码    String fileName = contentDisposition.substring(contentDisposition.indexOf("\"") + 1, contentDisposition.length() - 1);    DownloadTask task = new DownloadTask();    task.execute(url, fileName);}

ok,工作完成。我测试了一下,成功下载!于是交付测试。



一段时间之后,被告知又出现了问题:有时可以下载,有时又无法访问链接。

这又是什么原因呢?有时可以下载说明这种解决办法的方向是正确的,可有时又不能下载,这个问题又出在哪里呢?既然之前无法访问是因为没有验证 cookie,那么这次首先想到的就是 cookie 验证失败了。

继续抓包,发现 cookie 是有实效性的,也就是一段时间之后 cookie 是会发生变化的,但是 WebView 却一直保留着同一个 cookie 值。找到了原因,那就让 WebView 每次loadUrl(your url)之前清除掉 cookie 。

webView.clearCache(true); // 清除资源缓存。请注意,缓存是每个应用程序的,所以这将清除所有使用的WebViews的缓存。false的话,只会清除RAM上的缓存。webView.clearHistory(); // 清除历史记录webView.clearFormData(); // //从当前关注的表单字段中移除自动填充弹出窗口webView.clearSslPreferences(); // 清除存储的SSL首选项表

为了保险起见,在onDestroy()方法中写上同样的方法。

@Overrideprotected void onDestroy() {    super.onDestroy();    tencent_webview.clearCache(true);    tencent_webview.clearHistory();    tencent_webview.clearFormData();    tencent_webview.clearSslPreferences();}

这样就基本解决了问题,测试正常。

对于 WebView 的了解和掌握,我要学习的还有很多很多,写的不对的地方,欢迎各位指教~

阅读全文
0 0
原创粉丝点击