微博登录,分享都是很常用的功能。正在划水的某一天,测试MM突然提了个bug,说微博分享不能用了,纳尼,之前不是测试N遍,怎么突然不能用了。
仔细一看,是这样的。手机没有安装微博客户端,会走SDK内部网页分享,先登录,在分享。正常没问题。可是现在如图,登录完,跳转到配置的回调url SINA_REDIRECT_URI: "http://www.joyshebao.com/" 导致没有装微博,就不能用,这不能忍。
下图为bug流程
下图为正常逻辑,应该跳转到分享web界面
仔细排查了下,不是通用问题,目前只有小米8 (android9) 这部测试机会出现这个问题,sdk内置web授权分享无法使用。
发现问题,开debug,一步步找吧。
1,定位问题为新浪内部sdk流程有误,导致转发错误。开始一步步,排查,首先从SDK,分享入口开始。
当没有安装微博客户端时,会走到 com.sina.weibo.sdk.web.WeiboSdkWebActivity 界面,
初始化会走到initLoad方法,进而设置webClient ,WebViewClient 是监听web加载以及做拦截处理的,微博集成了WebViewClient,使用了策略模式,再次根据不同状态,设置不同的client。
通过调试代码,走到了AuthWebViewClient中,然后看一下代码,做了哪些工作。
微博SDK中AuthWebViewClient重写了onPageStarted() ,加载之前来判断是否需要做callback 处理。
if(url.startsWith(authInfo.getRedirectUrl()) && !this.authed) {this.authed = true;this.handleRedirectUrl(url);view.stopLoading();if(this.requestCallback != null) {this.requestCallback.closePage();}} else {super.onPageStarted(view, url, favicon);
}
内部这段核心逻辑,getRedirectUrl 有没有很眼熟,没错,就是微博要求配置的回调url(SINA_REDIRECT_URI)
可以看到,初次登录完成后,满足 !this.authed 并且满足配置的url匹配开头,就会停止当前webview 加载,结束并返回,然后加载新的分享界面。
bug就出现在此了,这里要跳转的url 与authInfo.getRedirectUrl() 不匹配,直接super.onPageStarted()。没有关闭,所以导致跳转到自己配置的url 界面了。
这种机制本来是检测app是否与官网填写的一致,更多安全性考虑。但是小米手机上不通用了。
调试发现返回的URL 是 https://xxxxx 而自己配置的是http://xxxx 这就尴尬了,小米8手机给替换成了https,测试其他品牌手机没有这个问题。不会替换,所以也就可以进入到if(true)控制逻辑,顺利结束返回。
既然问题找到了,解决方案就是保持一致呗
但是onPageStarted是系统级别的,找了半天没发现任何特出处理,推测应该是小米系统定制的时候内有处理了,把http默认统一为https。(随着https 大面积应用,普及率越来越高。这种设计也无可厚非,但是坑了老app,最早注册的http的)
既然没法弄,就想法该微博后台配置得了,最简单,设置为https 开头的。但是,这样就影响了线上已发版的app,毕竟它们都是配置的redirectUrl为http://,如果改了微博后台配置,那么大面积就没法用了。
要找到一个成本最低,不影响线上环境的方案。思来想去,还是要从app端入手。采用hook思想,使用AspectJ 切面,动态的拦截流程,把url再给改回来。
先上代码:
切面技术使用了AspectJ,一位android大佬封装的Aop。(具体用法可以自行百度)
之前已经找到bug原因,那么就针对这个方法,切入进去,使用@Around 来接管这个方法,监听到url为https://xxxx时,那么就改为http://xxxx ,然后再调用joinPoint.proceed();把本来的参数二次修改后,再传回去原方法。这样,就解决了微博web授权跳转异常问题。
经测试,兼容所有版本,小米8奇葩的异常解决了。下次发版,小米8用户就可以用了。最小的代价,去解决这个问题。
小结:还有建议最大可能的使用https,不论是安全性问题,还是一些手机系统解析问题,都会减少不必要的bug。
通过看微博SDK,也学到很多,比如策略模式的使用,观察者,委托。
一步步debug,找到核心,采用最小影响的方案,去解决。