Android WebView 302斗争之旅
一.背景
越来越多的业务接入,项目内多多少少会出现几个H5页面,只是单纯的提供WebView容器接入H5页面根本满足不了需求,他们需要登录态,需要制定协议控制Native的导航栏,或者需要JsBridge做一些更复杂的操作,这篇主要讲登录态出现的问题。
二.涉及的知识
Android WebView加载url的时候,我们是这样做监听的:
- 页面加载前会回调onPageStarted
- 页面加载完成会回调onPageFinished
- 当页面加载前且在onPageStarted后会回调shouldOverrideUrlLoading让我们决定是否自己处理这个url
public class PerformanceWebClient extends WebViewClient {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return super.shouldOverrideUrlLoading(view, url);
}
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
}
三.自定义返回栈
14年最初接触的项目,WebView页面是需要登录态的,处理方式就是shouldOverrideUrlLoading方法中,直接将url后面拼入参数,return true告知WebView组件url我们已经处理,你不用管了。
public class PerformanceWebClient extends WebViewClient {
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
}
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("http") || url.startsWith("https")) {
view.loadUrl(appendParamsToUrl(url));
return true;
} else if (isScheme(url)) {
return true;
}
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
}
}
简单的代码结构大致是这样,但是迅速暴露出一个问题:302页面返回栈。
我们主动load的页面会加入到返回栈内,而当我们webview.goBack()的时候,加载的时候还是一个302,导致无法正常关闭页面。
这时想到一个方法,自己定义返回栈。
问题是,一个url入栈的标准是什么?
举一个栗子:
A==302==>B==302==>C
加载A的url查看回调顺序是:
onPageStartedA==>onPageStartedB==>onPageStartedC==>onPageFinishedC
从这个角度来看,貌似onPageFinished中将url作为已加载的url挺靠谱的,但是现在存在一个问题,我每次回退栈都要以重新load的形式刷新页面,性能和流量都有耗费。
还存在一个问题,在实际情况中遇到,某一个业务url加载形式例如:
A==302==>B==302==>C==302==>D
加载A的url查看回调顺序是这样的:
onPageStartedA==>onPageStartedB==>onPageStartedC==>onPageFinishedC==>onPageStartedD==>onPageFinishedD
C页面是302到D的,但是也走了onPageStarted方法,猜测是做了某些操作再主动重定向的,这种url我们也不希望加入返回栈内,但是我们不能准确的检测到。
四.尝试优化
在后来接手的另一个项目中,也存在了302返回栈的问题,既要保留登陆态,又需要302不加入返回栈。
这时看到一个这样的处理方式:
class MerchantOnTouchListener implements View.OnTouchListener {
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
try {
WebView.HitTestResult hr = ((WebView) view).getHitTestResult();
if (hr != null && mLastUrl != null) {
switch (hr.getType()) {
case WebView.HitTestResult.SRC_ANCHOR_TYPE:
case WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE:
break;
case WebView.HitTestResult.UNKNOWN_TYPE:
return true;
break;
default:
return false;
}
if (previous.isEmpty() || !previous.get(previous.size() - 1).equals(mLastUrl)) {
previous.add(mLastUrl);
}
}
} catch (Exception ignored) {
}
return false;
}
}
当我们触摸屏幕时(通常就是开始点击链接)使用HitTestResult去看状态,如果得到的type是链接跳转类型,那么将最后加载的url加入返回栈。
实际效果是:302被避免了,但是页面内如果触摸的地方url有变化(比如params变了)也会加入返回栈,回退次数还是增加了,而且解决不了重新加载的问题。
就在这时得知了最开始接触的项目更换了登陆方式,App的登陆就是H5页面,登陆成功后拿到Cookie,Cookie既可以给Native访问Api使用,也可以在H5页面做登录态使用,页面栈全部交给WebView容器处理。
以为这就结束了么?
但是又出现了一个问题:运营商劫持
国内的网络环境大家比较了解,Headers的丢失率比较高,丢失了Cookie就等于丢失了登陆状态,这是其中一点;其次是如果业务发展已经很庞大,很难从Native Token 走SSO的方式转化为Cookie方式。
五.总结
目前经历了几个项目,一直没有很优雅的解决302的问题,目前的做法也有一些瑕疵,希望在以后的工作中能找到更好的方法。
最新文章
- Java 把 InputStream 转换成 String 的几种方法
- redis之(二十一)redis之深入理解Spring Redis的使用
- 使用generator生成排序动画
- 零拷贝传输(zero-copy transfer)——sendfile()
- [转]Android View.onMeasure方法的理解
- 页面加载后resize页面布局
- gitlab 配置
- js实现iframe自适应高度
- .net中类型转换的案例
- 使用BroadcastReceiver实现开机自动运行的Service
- jssdk微信图片上传功能
- C语言中的调试小技巧
- 字符函数库 cctype
- zoj 3659 Conquer a New Region The 2012 ACM-ICPC Asia Changchun Regional Contest
- Python爬虫(二十三)_selenium案例:动态模拟页面点击
- Mac mini 使用打印机
- Sparse Principal Component Analysis via Regularized Low Rank Matrix Approximation(Adjusted Variance)
- 【Python】【Web开发】
- [python] 初学python,级联菜单输出
- webpack react 错误整理
热门文章
- 任意多边形切割/裁剪(附C#代码实现)
- 我叫Twenty,我是要成为博客王的博客框架
- Google软件构建工具Bazel原理及使用方法介绍
- CSS currentColor 变量的使用
- 我们为什么不能只用O记号来谈论算法?
- C++ std::array
- 百度API ; 很多有用的接口及公用 数据
- ReactJs 报错 Element type is invalid: expected a string (from built-in components) or a class/function (for composite components) but got: undefined. Check the render method of `Me`.
- python资料
- 【Win 10 应用开发】透视效果