Android低版本WebView引起的BUG

日常玄学记录。目前我从事Java后端开发的工作,与移动App开发者对接API接口,App上线后发现有些机型无法正常登陆,为了排查问题使用了不同的模拟器安装App并且进行抓包分析,最终找到了问题所在,在此记录。

具体问题描述

最近上线的一个项目,Android客户端采用原生和非原生混合开发,后端API采用Session机制认证,出现部分Android机型无法使用WebView中加载的核心业务,通过抓包发现,某些客户端在使用WebView发起请求时没有带上登录时得到的SESSIONID,Android开发人员通过日志输出证实有把登录的SESSIONID同步设置给WebView的Cookie,并且通过cookieManager.getCookie方法能够取到同步设置的Cookie。于是我只能自己再进一步验证一下,最终找到问题所在。

测试发现主要问题


1.部分Android机型(部分厂商的7.x和8x的Android版本号)无法请求到Web页面,会被后端拦截
2.我用Android 5.x 到 9.x 的模拟器测试完全正常,抓包时请求头的Cookie中也正常携带SESSIONID,但是用户真实机型出现不携带Cookie的情况
3.Android开发人员确实把SESSIONID同步设置给WebView的Cookie了,客户端设置的Cookie也可以通过getCookie方法取出来,但是抓包发现在某些机型上WebView加载URL的时候请求头中并没有带上Cookie。

解决过程

大学研究了3年Android,也遇到过各种坑,这次问题我的第一反应就是不同机型的差异性导致的。回想了一下之前Android开发中曾经遇到的坑,于是用Android4.3版本的模拟测试了一下,发现请求头中果然也没带上Cookie
android4.3WebView加载接口地址时,请求头数据包如下图所示:

可以看到4.3版本的AndroidWebKit在请求头中存在不携带Cookie的情况
用android5.0版本的模拟器测试了一下,发现请求头中有携带Cookie


所以,这些机型的产商可能要摸一下自己的良心了,为了减少ROM的开发成本,是不是把部分低版本的WebKit内核直接照搬编译到新系统里了?

在网上经常可以看到一堆相互抄袭的文章,WebView同步Cookie的方法如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 同步cookie
*/
public static void synCookies(Context context, String url) {
CookieSyncManager.createInstance(context);
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
// 删除Cookie(可选)
cookieManager.removeSessionCookie();
cookieManager.setCookie(url, "登录时得到的SESSIONID");
CookieSyncManager.getInstance().sync();

// 可以日志输出再验证一下
String cookie = cookieManager.getCookie(url);
...
}


这段代码乍一看没什么问题,虽然getCookie可以取到设置进去的Cookie,但是请求时存在没带上Cookie的情况。
问题就出在同步方法上。如果刚好看过4.x的源码,会发现和现在的版本有比较大的不一样。
这里最大的区别是:
4.3版本的removeSessionCookie方法删除Cookie是异步的
sync同步设置Cookie也是异步的。
也就是说他可能在你设置了Cookie之后才执行remove操作,或者在WebView请求后才设置Cookie,
WebView发起请求时要么Cookie还没被设置,要么就是已经被删除。
所以在WebView加载URL发起请求时根本没有把Cookie带上。

一、Android5.0及以上的WebView操作Cookie后的时序图

二、Android4.3版本)操作Cookie后的时序图

解决方案


  1. WebView使用Post请求就可以在头部带上自定义参数,需要后端接口也跟着一起改
  2. Android客户端删除Cookie操作后面加上等待时间比如 Sleep 1000L。
  3. 上面这两种方案只是解决问题,但是并不是规范的,其实CookieSyncManager类和cookieManager的很多方法已经被标注为弃用
    https://developer.android.com/reference/android/webkit/CookieSyncManager 通过android官方文档可知,这些都被标注了@Deprecated,所以开发者在开发的时候要考虑兼容性问题,针对大众的产品要足够的细心

出现这些BUG的主要原因


在我写这篇文章时,Google官方虽然以及将Android更新到了9.0的版本,但是目前在中国市场还存在很多版本碎片化的问题,
网上有很多过时的API示例,国内的很多文章都相互抄袭,有的根本没有自己试验过就拷贝过来发表,这样的传播是非常不负责任的。

另外还有一个主要因素是很多厂商喜欢自己定制,曾经我还在开发Android应用时,就遇到某个厂商把摄像头拍照回调的API修改了,导致横竖屏切换的的问题,这种定制可以说是非常恶心来形容了,可能这也是我弃坑的原因之一吧。另外我真的非常喜欢写后台,所以现在能够写API接口感到很欣慰。

曾几何时,依稀记得在学校工作室的时光,曾经的方老师跟我们说过这样一句话“遇到问题不要说我是学Android的,后端的我不管…,不要说什么从Android开发转后端开发这样的话,你曾经学到的知识就是你自己的,没有转行,都是开发,能在一个领域有所成就取决于你有多专注”。原话虽然记得不是很清楚,但是大体就是这个意思,这句话到现在一直铭记在我脑海里。所以遇到问题我不怕,我的想法只有一个:找出问题,并解决它。

0%