Android 让 WebView 响应下载点击事件

最近项目中的邮件模块需要与第三方进行对接并且利用 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);
            // 这里可以对下载好的文件进行打开等操作
        }
    }

启动下载:

@Override
public 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()方法中写上同样的方法。

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值