Android WebView判定網頁加載的錯誤

一 前言

在WebView加載網頁的過程中,有時會頁面加載不出來的情況,如下:


error

那么如何知道網頁加載錯誤了呢?

二 解決方法

webview.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView?, url: String?) {
        super.onPageFinished(view, url)
        Log.d(TAG, "onPageFinished: ")
    }

    override fun onReceivedError(
        view: WebView?,
        request: WebResourceRequest?,
        error: WebResourceError?
    ) {
        super.onReceivedError(view, request, error)
        Log.d(TAG, "onReceivedError: request= " + request.json())
        Log.d(TAG, "onReceivedError: error= " + error.json())
    }
}
webview.loadUrl("https://www.baidu.com/")

request輸出:

{"a":{"a":"https://www.baidu.com/","b":true,"c":false,"d":false,"e":"GET","f":{"User-Agent":"Mozilla/5.0 (Linux; Android 11; sdk_gphone_x86_arm Build/RSR1.200819.001.A1; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/83.0.4103.106 Mobile Safari/537.36","Accept":"text/html,application/xhtml+xml,application/xml;q\u003d0.9,image/webp,image/apng,/;q\u003d0.8,application/signed-exchange;v\u003db3;q\u003d0.9","Upgrade-Insecure-Requests":"1"}}}

error輸出:

{"a":{"a":-1,"b":"net::ERR_CACHE_MISS"}}

/**
* 需要注意的是:與老版本不同,新版本已經針對所有的資源加載錯誤都會回調*(iframe, image, etc.), 不僅僅是加載的主頁面
 */
public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
    if (request.isForMainFrame()) {
        onReceivedError(view,
                error.getErrorCode(), error.getDescription().toString(),
                request.getUrl().toString());
    }
}

所以,通過以上監聽,即可知道對應的錯誤內容,進而做相應的業務處理。

三 常見的錯誤案例分析

1.錯誤:ERR_UNKNOWN_URL_SCHEME

復現條件:打開百度新聞資訊網頁,并點擊評論

error.gif
載體 現象
App內置WebView 報錯:ERR_UNKNOWN_URL_SCHEME
UC、華為瀏覽器 停留在當前頁面狀態
Chrome瀏覽器 跳轉到百度APP內部打開

來看一下頁面加載shouldOverrideUrlLoading 中回調request輸出:

{"a":{"a":"baiduboxapp://v1/easybrowse/hybrid?upgrade\u003d1\u0026type\u003dhybrid\u0026tpl_id\u003dlanding_app.html\u0026newbrowser\u003d1\u0026style\u003d%7B%22toolbaricons%22%3A%7B%22tids%22%3A%5B%224%22%2C%221%22%2C%222%22%2C%223%22%5D%2C%22menumode%22%3A%222%22%2C%22actionBarConfig%22%3A%7B%22extCase%22%3A%220%22%7D%7D%7D\u0026slog\u003d%7B%22from%22%3A%22feed%22%7D\u0026context\u003d%7B%22nid%22%3A%22news_9777178803801641010%22%7D\u0026ch_url\u003dhttps%3A%2F%2Fmbd.baidu.com%2Fnewspage%2Fdata%2Flandingreact%3FpageType%3D2%26nid%3Dnews_9777178803801641010%26uk%3D%26sourceFrom%3DlandingShare\u0026commentInfo\u003d%7B%22topic_id%22%3A1066000039731532%2C%22opentype%22%3A2%7D\u0026logargs\u003d%7B%22source%22%3A%221020283l%22%2C%22channel%22%3A%221020283m%22%7D\u0026needlog\u003d1","b":false,"c":true,"d":false,"e":"GET","f":{"Accept":"text/html,application/xhtml+xml,application/xml;q\u003d0.9,image/avif,image/webp,image/apng,/;q\u003d0.8,application/signed-exchange;v\u003db3;q\u003d0.9","Referer":"https://mbd.baidu.com/newspage/data/landingpage?s_type\u003dnews\u0026dsp\u003dwise\u0026context\u003d%7B%22nid%22%3A%22news_9777178803801641010%22%7D\u0026pageType\u003d1\u0026n_type\u003d1\u0026p_from\u003d-1\u0026innerIframe\u003d1","Upgrade-Insecure-Requests":"1"}}}

可以發現協議不是http類開頭,而是百度自己定義的"baiduboxapp"。因此,不做處理,當然是識別不了的。

2.實現UC、華為瀏覽器處理的效果——>無視

webview.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(
                view: WebView?,
                request: WebResourceRequest?
            ): Boolean {
                Log.d(TAG, "shouldOverrideUrlLoading: ${request.json()}")
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    Log.d(TAG, "shouldOverrideUrlLoading: url->${request?.url}")
                    if (view != null && request?.url?.toString() != null) {
                        if (request.url.toString().startsWith("http")) {
                            view.loadUrl(request.url.toString())
                        }
                return true
            }

3.如何實現Chrome瀏覽器處理的效果——>能跳轉

假定這是百度適配Chrome的效果,而不是Chrome主動去適配百度的代碼頁面,那么說明客戶端的WebView也是能做到這樣效果的。

基于此,我們來urldecode一下協議內容來看看request有什么特殊:

baiduboxapp://v1/easybrowse/hybrid?upgrade=1&type=hybrid&tpl_id=landing_app.html&newbrowser=1&style={"toolbaricons":{"tids":["4","1","2","3"],"menumode":"2","actionBarConfig":{"extCase":"0"}}}&slog={"from":"feed"}&context={"nid":"news_9777178803801641010"}&ch_url=https://mbd.baidu.com/newspage/data/landingreact?pageType=2&nid=news_9777178803801641010&uk=&sourceFrom=landingShare&commentInfo={"topic_id":1066000039731532,"opentype":2}&logargs={"source":"1020283l","channel":"1020283m"}&needlog=1

整體來看,仍舊是符合URI規則的。這樣的話就可以考慮使用Intent處理的方式了。

webview.webViewClient = object : WebViewClient() {
    override fun shouldOverrideUrlLoading(
        view: WebView?,
        request: WebResourceRequest?
    ): Boolean {
        Log.d(TAG, "shouldOverrideUrlLoading: ${request.json()}")
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Log.d(TAG, "shouldOverrideUrlLoading: url->${request?.url}")
            if (view != null && request?.url?.toString() != null) {
                if (request.url.toString().startsWith("http")) {
                    view.loadUrl(request.url.toString())
                } else {
                    try {
                        Log.d(TAG, "shouldOverrideUrlLoading: 開始跳轉")
                        startActivity(Intent(Intent.ACTION_VIEW, request.url))
                    } catch (e: Exception) {
                        Log.d(TAG, "shouldOverrideUrlLoading: ${e.json()}")
                    }
                }
            }
        }

        return true
    }

運行查看效果如下:


resolved.gif

從結果來看,能跳轉至百度的App,假定成立。
也就是針對非http協議地址的情況,可使用 startActivity(Intent(Intent.ACTION_VIEW, request.url)) 之類來進行協議內容處理。

四 總結

最后,根據自家業務來定協議并處理,畢竟不是誰都愿意自家用戶跳出自家App的。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,837評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,196評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,688評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,654評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,456評論 6 406
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,955評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,044評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,195評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,725評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,608評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,802評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,318評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,048評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,422評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,673評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,424評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,762評論 2 372

推薦閱讀更多精彩內容