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嵌入H5之file頭像上傳檔案,適配所有版本
最近公司需要開發新的專案,為了節省時間成本,要求整體嵌入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進階之旅------>Android關於Log的一個簡單封裝
eight ron track 100% oid content amp 嚴重 center android.util.Log類,能夠方便地用於在編碼調試過程中打印日誌。可是在公布後的產品中,假設有太多的日誌打印。則會嚴重地影響性能。對android.util.Lo
我的Android進階之旅------>Android二級ListView列表的實現
cat -i gravity 寫真 技術分享 家政服務 個性 韓國 服務 實現例如以下圖所看到的的二級列表效果 首先是在布局文件裏,布局兩個ListView,代碼例如以下: <LinearLayout xmlns:android="htt
我的Android進階之旅------>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進階之旅------>Android中android:windowSoftInputMode的使用方法
onf ecif 標簽 ear evel per another not 行為 面試題:怎樣在顯示某個Activity時馬上彈出軟鍵盤? 答案:在AndroidManifest.xml文件裏設置<activity>標簽的android:win
我的Android進階之旅------>怎樣在多個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