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的问题,目前的做法也有一些瑕疵,希望在以后的工作中能找到更好的方法。
Android WebView 302斗争之旅的更多相关文章
- webview之如何设计一个优雅健壮的Android WebView?(上)(转)
转接:https://iluhcm.com/2017/12/10/design-an-elegant-and-powerful-android-webview-part-one/ 前言 Android ...
- 如何设计一个优雅健壮的Android WebView?(上)
转:如何设计一个优雅健壮的Android WebView?(上) 前言 Android应用层的开发有几大模块,其中WebView是最重要的模块之一.网上能够搜索到的WebView资料可谓寥寥,Gith ...
- Android WebView useragent
今天介绍一下Android WebView UserAgent, User-Agent(简称UA)是HTTP请求头部用来标识客户端信息的字符串, 包括操作系统, 浏览器等信息.为了建立手机客户端的信息 ...
- android webview开发问题及优化汇总
我们在native与网页相结合开发的过程中,难免会遇到关于WebView一些共通的问题.就我目前开发过程中遇到的问题以及最后得到的优化方案都将在这里列举出来.有些是老生常谈,有些则是个人摸索得出解决方 ...
- Android WebView 开发教程
声明在先:必须在AndroidMainfest.xml 里面声明权限,否则在Java里面编写的所有WebView浏览网页的代码都无法正常使用 <uses-permission android:n ...
- [Android] WebView内的本地网页,使用XMLHttpRequest读取本地档案
[Android] WebView内的本地网页,使用XMLHttpRequest读取本地档案 问题情景 在Android里,可以使用WebView来呈现本地或是远程的网页内容.但是在显示本地网页时,如 ...
- Android webview通过http get下载文件下载两次的问题及解决方法
一.现象 一般通过Android webview进行下载文件的方法是 1.重写DownloadListener的onDownloadStart方法,在onDownloadStart方法中弹出对话框提示 ...
- Android WebView常见问题及解决方案汇总
Android WebView常见问题解决方案汇总: 就目前而言,如何应对版本的频繁更新呢,又如何灵活多变地展示我们的界面呢,这又涉及到了web app与native app之间孰优孰劣的争论. 于是 ...
- android webview 底层实现的逻辑
其实在不同版本上,webview底层是有所不同的. 先提供个地址给大家查:http://grepcode.com/file/repository.grepcode.com/java/ext/com.g ...
随机推荐
- ASP.NET MVC 视图(一)
ASP.NET MVC 视图(一) 前言 从本篇开始就进入到了MVC中的视图部分,在前面的一些篇幅中或多或少的对视图和视图中的一些对象的运用进行了描述,不过毕竟不是视图篇幅说的不全面,本篇首先为大家讲 ...
- Redis集群搭建与简单使用
介绍安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟机都是 CentOS ,一台 ...
- Android开发学习之路-记一次CSDN公开课
今天的CSDN公开课Android事件处理重难点快速掌握中老师讲到一个概念我觉得不正确. 原话是这样的:点击事件可以通过事件监听和回调两种方法实现. 我一听到之后我的表情是这样的: 这跟我学的看的都不 ...
- 非阻塞/异步(epoll) openssl
前段时间在自己的异步网络框架handy中添加openssl的支持,当时在网络上搜索了半天也没有找到很好的例子,后来自己慢慢的摸索,耗费不少时间,终于搞定.因此把相关的资料整理一下,并给出简单的例子,让 ...
- vue源码解析阅读列表
https://zhuanlan.zhihu.com/p/24435564 开发vue(或类似的MVVM框架)的过程中,需要面对的主要问题有哪些? 剖析vue实现原理,自己动手实现mvvm 官网介绍
- 与大家分享robotium一个小问题。Test run failed:Instrumentation run failed due to 'java.lang.ClassNotFoundException'
今天和大家分享robotium一个小问题. 我们在运行自已经搭好的框架时,有可能会出现一个找不到类的错误(如上图所示). 问题是重签名工具给出的activity有误,这时我们可以用Appt命令查看重签 ...
- ASP.NET Web API与Owin OAuth:调用与用户相关的Web API
在前一篇博文中,我们通过以 OAuth 的 Client Credential Grant 授权方式(只验证调用客户端,不验证登录用户)拿到的 Access Token ,成功调用了与用户无关的 We ...
- 从零开始编写自己的C#框架(23)——上传组件使用说明
文章导航 1.前言 2.上传组件功能说明 3.数据库结构 4.上传配置管理 5.上传组件所使用到的类 6.上传组件调用方法 7.效果演示 8.小结 1.前言 本系列所使用的是上传组件是大神July开发 ...
- [C#] Linq To Objects - 如何操作文件目录
Linq To Objects - 如何操作文件目录 开篇语: 上次发布的 <LINQ:进阶 - LINQ 标准查询操作概述> 社会反响不错,但自己却始终觉得缺点什么!“纸上得来终觉浅,绝 ...
- 设计模式(六):控制台中的“命令模式”(Command Pattern)
今天的博客中就来系统的整理一下“命令模式”.说到命令模式,我就想起了控制台(Console)中的命令.无论是Windows操作系统(cmd.exe)还是Linux操作系统(命令行式shell(Comm ...