Android-X5WebView封装(含Cookie管理、优化
本文已独家授权 郭霖 ( 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地址),文章请勿滥用、开源项目仅供学习交流、也希望大家尊重笔者的劳动成果,谢谢。