一.背景

越来越多的业务接入,项目内多多少少会出现几个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斗争之旅的更多相关文章

  1. webview之如何设计一个优雅健壮的Android WebView?(上)(转)

    转接:https://iluhcm.com/2017/12/10/design-an-elegant-and-powerful-android-webview-part-one/ 前言 Android ...

  2. 如何设计一个优雅健壮的Android WebView?(上)

    转:如何设计一个优雅健壮的Android WebView?(上) 前言 Android应用层的开发有几大模块,其中WebView是最重要的模块之一.网上能够搜索到的WebView资料可谓寥寥,Gith ...

  3. Android WebView useragent

    今天介绍一下Android WebView UserAgent, User-Agent(简称UA)是HTTP请求头部用来标识客户端信息的字符串, 包括操作系统, 浏览器等信息.为了建立手机客户端的信息 ...

  4. android webview开发问题及优化汇总

    我们在native与网页相结合开发的过程中,难免会遇到关于WebView一些共通的问题.就我目前开发过程中遇到的问题以及最后得到的优化方案都将在这里列举出来.有些是老生常谈,有些则是个人摸索得出解决方 ...

  5. Android WebView 开发教程

    声明在先:必须在AndroidMainfest.xml 里面声明权限,否则在Java里面编写的所有WebView浏览网页的代码都无法正常使用 <uses-permission android:n ...

  6. [Android] WebView内的本地网页,使用XMLHttpRequest读取本地档案

    [Android] WebView内的本地网页,使用XMLHttpRequest读取本地档案 问题情景 在Android里,可以使用WebView来呈现本地或是远程的网页内容.但是在显示本地网页时,如 ...

  7. Android webview通过http get下载文件下载两次的问题及解决方法

    一.现象 一般通过Android webview进行下载文件的方法是 1.重写DownloadListener的onDownloadStart方法,在onDownloadStart方法中弹出对话框提示 ...

  8. Android WebView常见问题及解决方案汇总

    Android WebView常见问题解决方案汇总: 就目前而言,如何应对版本的频繁更新呢,又如何灵活多变地展示我们的界面呢,这又涉及到了web app与native app之间孰优孰劣的争论. 于是 ...

  9. android webview 底层实现的逻辑

    其实在不同版本上,webview底层是有所不同的. 先提供个地址给大家查:http://grepcode.com/file/repository.grepcode.com/java/ext/com.g ...

随机推荐

  1. NodeJs 开发微信公众号(三)微信事件交互

    微信公众号有个规则,一旦开启了开发者模式,其他的常规功能就都必须通过接口调用完成.比如说自定义菜单功能,必须通过发送post请求的方式生成.本章就通过关注到取消关注的整个过程来谈一谈nodejs是怎么 ...

  2. 微信小程序开发初探

    一.关于微信小程序 1.1 小程序诞生的背景 张小龙说道: (1)一切以用户价值为依归→用户是微信的核心,所以微信中没有很多与客户无关的功能,比如QQ中的乱七八糟一系列东西. (2)让创造发挥价值→所 ...

  3. WCF : 如何将NetTcpBinding寄宿在IIS7上

    摘要 : 从IIS 7 开始, IIS增加了对非HTTP协议的支持. 因此, 自IIS 7之后, 可以将NetTcpBinding等非HTTP协议的Bindings直接寄宿在IIS上面. 本文将介绍如 ...

  4. 2000条你应知的WPF小姿势 基础篇<78-81 Dialog/Location/WPF设备无关性>

    在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000ThingsYou Should Know About C# 和 2,00 ...

  5. 工欲善其事,必先利其器 之 WPF篇: 随着开发轨迹来看高效WPF开发的工具和技巧

    之前一篇<工欲善其事,必先利其器.VS2013全攻略(安装,技巧,快捷键,插件)!> 看到很多朋友回复和支持,非常感谢,尤其是一些拍砖的喷油,感谢你们的批评,受益良多. 我第一份工作便是W ...

  6. ABP源码分析四十三:ZERO的本地化

    ABP Zero模块扩展了ABP基础框架中的本地化功能,实现了通过数据库管理本地化的功能.其通过数据库保存本地化语言及其资源. ApplicationLanguage:代表本地化语言的实体类.一种语言 ...

  7. Web网站中利用JavaScript中ActiveXObject对象获取硬件信息(显示器数量、分辨率)从而进行单双屏跳转

    前言:最近这两天工作上,要实现一个功能,在好友阿聪的帮助下,算是比较好的解决了这个需求. B/S的Web网站,需要实现点击按钮时,根据客户端连接的显示屏(监视器)数量进行,单双屏跳转显示新页面. 由于 ...

  8. MySQL中You can't specify target table for update in FROM clause一场

    mysql中You can't specify target table <tbl> for update in FROM clause错误的意思是说,不能先select出同一表中的某些值 ...

  9. scikit-learn 梯度提升树(GBDT)调参小结

    在梯度提升树(GBDT)原理小结中,我们对GBDT的原理做了总结,本文我们就从scikit-learn里GBDT的类库使用方法作一个总结,主要会关注调参中的一些要点. 1. scikit-learn ...

  10. c#官方推荐md5通用加密类

    /// <summary> /// MD5加密 /// </summary> /// <param name="input">需要加密的字符串& ...