×

Android-X5WebView封装(含Cookie管理、优化预加载、进度监听等策略)

96
骑小猪看流星
2018.03.14 15:05* 字数 2515

本文已独家授权 郭霖 ( guolin_blog ) 公众号发布!

撸完了上一篇Android-X5WebView简介 之后,有些大兄弟可能觉得不过瘾呐,说你那样的都是很基础的啊(的确很基础),项目里面用起来不爽啊(的确很不爽),不能让我直接CV啊(的确不能直接复制粘贴)等等,那这篇文章的目标就是怎么样快速封装X5WebView,如何有效的同步以及管理Cookie,如何使用IntentService优化预加载,如何监听进度条等一些在项目中的常用功能。

功能需求:

需求一:客户端账号密码登录成功以后,调用H5(也就是使用X5webView,以下简称X5)。H5界面也需要去记录你的状态。比如你客户端本地登录成功以后,H5界面也需要显示登录成功的状态。那么,客户端和H5如何去同步状态?

需求二:因为X5加载的时候,会有一段时间会显示空白或者卡顿,如何去监听并利用这个进度并优化?

需求三:如何简单封装X5WebView基本功能,方便日后快速使用?

需求分析:

需求一:

(针对需求一,真的是参考了很多哥们的技术博客,然后由于笔者上周也就是3月9号接到的开发需求,其中遇到了很多坑,所以我希望这篇博客可以把这个需求写的详细,尽可能的造福以后遇到同样需求的朋友让他们节约时间少走弯路)

对于Cookie,我们并不陌生,如果不是很了解的建议首先参考Cookie、Session、Token那点事儿  先大致掌握一下。这里多提一嘴,Cookie 简单理解,它主要是用来进程保活的,其具有时效性(持久化和非持久化),它是通过服务器的请求,在响应头里面拿到,然后在第二次http请求上以请求头的方式将参数带过去,优点是减少后台查库压力等等,更加具体的细节和说明可以参考上面的链接文章,那么,在Android中,也就是WebView中,我们如何去管理Cookie?

首先:CookieSyncManager与CookieManager

Android中关于Cookie的说明:

早期的cookie是由CookieSyncManager进行管理的,之后CookieSyncManager被抛弃了,换成了CookieManager来进行管理。两个版本的分割线就是Android SDK -- 21。

Android中Cookie的存储位置:

目前Android系统WebView是将cookie存储data/data/package_name/app_webview这个目录下的一个叫Cookies的数据中。

CookieSyncManager在内存和存储器之间同步浏览器的cookie。另外,CookieSyncManager的同步策略是在一个独立的线程里定时进行同步。

注意:每次同步的时间间隔是5分钟。

CookieSyncManager类下的常用API介绍

cookie同步策略:

CookieSyncManager.createInstance(context); 

CookieSyncManager.getInstance().startSync();

cookie停止同步:

CookieSyncManager.getInstance().stopSync()

cookie立即同步:调用了该方法会立即进行cookie的同步,代码如下:

CookieSyncManager.getInstance().sync()

删除cookie操作:

CookieSyncManager.createInstance(this);

CookieManager.getInstance().removeAllCookie();

CookieManager.getInstance().removeSessionCookie();

CookieSyncManager.getInstance().sync();

CookieSyncManager.getInstance().startSync();

CookieManager管理cookie:从sdk21之后,webview已经内置了cookie的同步操作了。虽然不再需要关注cookie的同步,但是依然需要掌握删除cookie的操作。

删除cookie操作:底层实现是异步清除数据库的记录

CookieManager.getInstance().removeAllCookies(null);

CookieManager.getInstance().flush();

立即同步:注意到这个flush()方法就是立即同步cookie的操作,本质上与CookieSyncManager中的sync()方法是一样的。于是乎,关于同步cookie我们可以有如下简单的写法:

cookie同步

然后,笔者就遇到了第一个坑,按照如下写法以后,cookie居然神奇的不同步(下面是伪代码,下面是伪代码)

cookie不同步

之前笔者通过字符串拼接,也就是append字符串 ,拼接字符串以后,我想直接通过cookieManager.setCookie(url, cookie); 在x5WebView.loadUrl(url);调用之前去设置cookie,

然后,cookie就是同步不了。没得办法,打印日志之后发现,手动设置的cookie值,神奇的只有一个分号 !

谷歌百度后,有哥们说是因为cookie Value的值在读取时,只会读取到第一个分号时,当发现第一个分号即认为读取结束。所以分号后面的cookie的值将不会读取,实际测试确实是这样。那么,我们该如何解决拼接cookie读取失败的问题?

解决办法如下图,我们可以一个个手动设置cookie,即可拼接完整的Cookie。(这种办法虽然笨拙,但的确可以有效解决分号切割问题)

setCookie解决办法

当然,我在公司项目里用的是Okhttp,(为什么这里用Okhttp,因为!这样就可以用Okhttp、Retrofit、OkGo等网络框架,直接集成 我在项目中给大家提供的拦截器、自定义CookieJar使用了)。通过自定义拦截器,实现CookieJar去完成同步客户端和H5的cookie状态。这里先上下最终效果图:(笔者的代码可能不是唯一实现功能需求的,但凑合还能用。实现方式有很多种,写的不好也请大家见谅)

Okhttp简单设置

关于AddCookiesInterceptor以及SaveCookiesInterceptor这两个拦截器,主要就是存Cookie和使用Cookie,具体说明可以参考 两个拦截器的说明 ,然后我们点进自定义cookieJar中的 SaCookieManger

SaCookieManger

这个类定义了一个context构造参数,在保存cookie的saveFromResponse方法中,调用了SaasCookieManager.loadCookie(cookies,url.host());方法,我们点进SaasCookieManager


SaasCookieManager

通过遍历添加到集合里面,然后一个个的setCookie( url ,cookie )、接着判断SDK版本号进行同步刷新即可,具体可以参考项目源代码。

当然大家也可以在这里面根据开发需求去增加自己的实际功能。

通过上面的步骤,我们就可以简单的实现 客户端与H5端同步cookie。

笔者的项目里面,是客户端登录成功以后,进入H5页面,H5页面上直接显示已登录状态。

拓展:有部分手机使用后可能还是无法同步,那么我们可以尝试,设置跨域读取cookie,开启webview对第三方cookie的支持。


跨域查询

当页面加载完毕的时候,我们可以通过下面的截图代码,去获取H5上面的cookie,我们也可以打印日志、进行同步

页面加载完毕


需求二:

监听进度,是这样,WebView里面的WebChromeClient这个类,里面有个onProgressChanged方法,重写这个方法就可以获取加载进度。获取到X5Webview的进度之后,还需要通过WebView的setWebChromeClient方法,将我们自定义的WebChromeClient对象传进去,即可完成进度监听。


监听进度

需求三:封装X5Webview基本功能

常用设置:

比如设置对JS的支持等等一些比较常用的,我们可以直接这样设置


常用设置

滚动条(内侧、外侧的设置),隐藏或显示的基本使用:


滚动条属性设置

处理预加载:

有的小伙伴说,X5预加载不是很友好。在加载X5内核的时候,X5内核需要进行一些初始化,这些初始化如果不明确指出运行的线程,它就会在你启动页面的时候,默认在主线程中执行,因此就会出现卡顿(这个现象时有时无,但是我们在代码层面尽可能的去规避使用风险),所以,我们可以写个 IntentService 去帮我们管理预加载问题:


IntentService

多提一嘴:IntentService是Service的子类,比普通的Service增加了额外的功能。

IntentService会创建独立的worker线程来处理所有的Intent请求;

会创建独立的worker线程来处理onHandleIntent()方法实现的代码,无需处理多线程的问题;

所有请求处理完成后,IntentService会自动停止,开发者无需手动调用stopSelf()方法停止Service;

写完之后我们在去自定义Application里面注册服务:(别忘了去清单文件配置Services)


Application使用service

返回键的处理:

这个就根据大家开发需求具体使用了,有的要求返回键按下两次才允许退出等等

生命周期的处理、释放资源的处理:这个就不说了,大家查阅资料集成功能即可

拦截广告的处理:

有些哥们说,使用这个经常会出现广告,解决这个办法有两个办法

1:使用Https

2:设计拦截url规则,对允许的url进行放行加载,不允许的url,WebView禁止加载

附录:项目地址

如果觉得这篇文章对你有帮助,希望点下一个小小的star,谢谢。

Ps:著作权归作者所有,转载请注明作者, 商业转载请联系作者获得授权,非商业转载请注明出处(开头或结尾请添加转载出处,添加原文url地址),文章请勿滥用、开源项目仅供学习交流、也希望大家尊重笔者的劳动成果,谢谢。

Android 原创印记
Web note ad 1