Android WebView 302鬥爭之旅

来源:http://www.cnblogs.com/pedro-neer/archive/2016/03/25/5318354.html
-Advertisement-
Play Games

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


一.背景

越來越多的業務接入,項目內多多少少會出現幾個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的問題,目前的做法也有一些瑕疵,希望在以後的工作中能找到更好的方法。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • DrawerLayout是V4包下提供的一種左滑右滑抽屜佈局效果。 實現效果如下: 因為是官方提供的,所以使用起來也相對的比較簡單。 DrawerLayout 提供 1、當界面彈出的時候,主要內容區會自動背景變黑,當點擊內容區的時候,抽屜佈局會消失 2、在屏幕邊緣手勢滑動 會拉出抽屜佈局 註意:當按 ...
  • 圖片輪播是一種常見的自定義控制項,也有多種實現的方法,這裡提供一種簡單的ViewPager實現的案例。 實現功能:圖片迴圈輪播,進度顯示,圖片點擊事件 實現只需三步: 1 添加類文件到項目中。 2 在xml佈局中引入標簽。 3 實例化並設置簡單參數。 具體使用方法,詳見代碼註釋。 ==========... ...
  • 1.先來看看效果,這裡做了三個功能 2.實現app之間的跳轉需要註意兩方面 3首先來講url和白名單的設置 4.實現跳轉的代碼 5.demo:https://github.com/TigerCui/MyAppJumpToYourApp.git ...
  • 在學習多線程之前需要瞭解什麼是進程? 進程是指在系統中正在運行的一個應用程式 每個進程之間是獨立的,每個進程均運行在其專用且受保護的記憶體空間內 可以通過“活動監視器”查看Mac中所開啟的進程 下一個問題什麼是線程? 一個進程想要執行任務,必須得有線程(每一個進程只收要有一個主線程) 一個進程中的所有 ...
  • 什麼是讀寫鎖 讀寫鎖是多線程下的一種同步機制, 它還有很多其他的名字,比如共用 獨占鎖等等。被它保護的資源有以下幾種狀態: 初始狀態 沒有線程訪問資源時所在的狀態 共用狀態 有多個讀線程訪問資源時進入共用狀態,這個時候允許新的讀線程訪問資源,但是寫線程必須等待 獨占狀態 寫線程訪問資源時進入獨占狀態 ...
  • 該篇文章是我自己從我的新浪博客上摘抄過來的, 原文鏈接為: http://blog.sina.com.cn/s/blog_dcc636350102wat5.html 在iOS開發中, 難免會集成別人的三方類庫, 當集成的三方類庫過多時, 難免會出現某些庫同時使用了同樣的函數庫,導致link的時候報錯 ...
  • 因為Pthread很少用到,所以對於Pthread的知識沒有摳那麼細緻,所以將Pthread和 NSThread放在了一起。 4.1 Pthread 4.1-1.0 創建線程 - pthread_create 4.1-1.1 __bridge 橋接 <!--?xml version="1.0" en ...
  • Messenger簡介 Messenger和AIDL是實現進程間通信(interprocess communication)的兩種方式. 實際上,Messenger的實現其實是對AIDL的封裝. Messenger適合於多進程單線程,AIDL適合於多進程多線程,需要開發者自己實現線程安全. goog ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...