1. 程式人生 > >Android WebView 302鬥爭之旅

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鬥爭

一.背景 越來越多的業務接入,專案內多多少少會出現幾個H5頁面,只是單純的提供WebView容器接入H5頁面根本滿足不了需求,他們需要登入態,需要制定協議控制Native的導航欄,或者需要JsBridge做一些更復雜的操作,這篇主要講登入態出現的問題。 二.涉及的知識 Android WebView載入url

Flutter接入現有Android工程踩坑

把Flutter作為一個模組接入到現有的Android工程,Flutter有官方推薦方案 Add Flutter to existing apps,通過這樣的工程配置,可以在debug支援HotReload,也可以輸出Release包供釋出。不過在使用過程中有一些需要調整的地方,特此記錄希望對大家能有借鑑意義

Android外掛化技術 1 開篇 - 實現啟動外掛與呼叫外掛中的Activity和Service

前言 Android技術如今已很成熟了,元件化、外掛化、熱修復等等框架層出不窮,如果只停留在單純的會用框架上,技術永遠得不到成長,只有懂得其原理,能夠婉婉道來,能夠自己手動寫出,技術才會得到成長,與其焦慮未來,不如把握現在。本篇將手寫教大家寫出外掛化框架,外掛化技術是Android高階工程師必備的技術之一,

Android WebView嵌入H5file頭像上傳檔案,適配所有版本

 最近公司需要開發新的專案,為了節省時間成本,要求整體嵌入H5介面。對,沒看錯是整體嵌入,心中一萬隻草泥馬奔騰,沒辦法大佬就是大佬,還是的照做。 今天來說說h5上傳頭像的問題吧。網上有很多的解決方案,開始我覺得好像很簡單,都有成功案例,等把程式碼copy下來,發現並不能執

Android WebView詳解檔案下載

1、佈局檔案activity_main.xml:線性佈局,TextView顯示頁面標題,WebView顯示頁面。 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

WebView爬坑2--a標籤是target="_blank"時建立新視窗

如果網頁裡連結的a標籤是target=”_blank”,而碰巧你的WebView又沒有處理,那這個時候就會出現狂點連結/button頁面卻無動於衷的情況,給人想砸手機的感覺… 好了,解決方案其實也挺簡

Android網路開發回顧 ① 在Android手機整合使用MQTT協議 ,實現搞掂移動控制硬體端。(附帶Demo)

一、認識MQTT協議。 如果你對MQTT協議的連線過程不熟悉,那沒關係;請看我前面的8266硬體上介紹的MQTT介紹 ,其實也沒啥難,這個MQTT的好處是短小,資訊傳遞快捷 ,適合在

Android APK瘦身

從APK的檔案結構說起 APK在安裝和更新之前都需要經過網路將其下載到手機,如果APK越大消耗的流量就會越多,特別是對於使用行動網路的使用者來講,消耗流量越多就代表需要花更多的錢去購買流量。同時一

Android網路程式設計實踐

(一):網路狀態檢測    一直以來本人都在做Android Multi-Media Framework下的Lib支援庫的開發和修改,終於最近告一段落,但根據專案要求,需要寫一個和網路相關的service,用java來實現。其實,在Framework及其之上的應用層用j

Android 源碼編譯

fin checkout 寫敏感 undefine -m nvi gen 保存 需要 目錄 前言 背景 安裝軟件 正文 Mac 分區

懶人模式開啟Android模組自動化Api

在將業務進行模組化時,避免不了模組頁面路由和模組通訊, 大多數我們會用到ARouter,EventBus三方庫。 模組化過程中有一個尷尬的問題擺在面前:Event事件、Router path放在哪裡? 因為很多業務module都需要收發Event事件,進行頁面路由,所以只能將Event, Router pat

我的Android進階------&gt;Android關於Log的一個簡單封裝

eight ron track 100% oid content amp 嚴重 center android.util.Log類,能夠方便地用於在編碼調試過程中打印日誌。可是在公布後的產品中,假設有太多的日誌打印。則會嚴重地影響性能。對android.util.Lo

我的Android進階------&gt;Android二級ListView列表的實現

cat -i gravity 寫真 技術分享 家政服務 個性 韓國 服務 實現例如以下圖所看到的的二級列表效果 首先是在布局文件裏,布局兩個ListView,代碼例如以下: <LinearLayout xmlns:android="htt

我的Android進階------&gt;Android編譯錯誤java.util.zip.ZipException: duplicate entry的解決方法

image bsp failed 進階 技術分享 san col get cep 今天在Android Studio中把另外一個項目引入當前項目,編譯的時候出現了java.util.zip.ZipException: duplicate entry錯誤。 錯誤例如以下

Android 學習--Android 體系結構

2015年 1.5 學習 gin 3年 哈哈 蛋糕 名稱 kit 一、Android 背景 背景就不說了,百度介紹很多,主要還是記一下每個Android版本對應的甜品名稱,我覺得這個挺好玩的,哈哈 1.5 Cupcake(紙杯蛋糕):2009年4月30日發布。 1.

Android學習--Android Studio

tro options png 進行 下載 setting 內存 com style 一、開發工具了解 Android Studio 是一個Android集成開發工具,基於IntelliJ IDEA. 類似 Eclipse ADT,提供了集成的 Android 開

我的Android進階------&gt;Androidandroid:windowSoftInputMode的使用方法

onf ecif 標簽 ear evel per another not 行為 面試題:怎樣在顯示某個Activity時馬上彈出軟鍵盤? 答案:在AndroidManifest.xml文件裏設置<activity>標簽的android:win

我的Android進階------&gt;怎樣在多個LinearLayout中加入分隔線

lai tex pre draw white 方法 utf == 技術分享 假設要適合於全部的Android版本號,能夠在多個LinearLayout放置用於顯示分隔線的View。比如,放一個ImageView組件。然後將其背景設為分隔線的顏色或圖像,分隔線

Android的DatePicker和TimePicker-android學習(三十八)

cursor ini lis drawable textview @+ type pin view DatePicker和TimePicker簡單介紹 DatePicker和TimePicker是從FrameLayout繼承而來。他們都是比較簡單的組件

11月廣州aNDROID求職

hao123 one ongl android motion cti event roi down MOTIONEVENTaCTION%5FDOWN http://music.hao123.com/songlist/495770244 http://music.baid