解決webview出現錯誤net::err_unknown_url_scheme 的問題

產生原因webview重定向,其定義沒有明確的官方解釋,發生的原因是請求的鏈接(url)在加載完成後發生了變化 (eg.比如你的代碼中設置webview加載的是網頁A,打開後發現加載的是網頁B); 關於 net::ERR_UNKNOWN_URL_SCHEME (如下圖所示),因爲webview只能識別http和https協議,遇到圖中這種"wvhzpj://"開頭的自定義協議時就無法識別,便會提示ERR_UNKNOWN_URL_SCHEME這樣的錯誤。

解決方法:重寫WebviewClient類中的 shouldOverriderUrlLoading 方法( 選取方法參數爲(Webview view , String url )的那種,如下圖),該方法可以對webview將要加載的url 進行處理,我們在此處對 會發生重定向的 url 和 不以 "http://"、"https//" 開頭的自定義協議 進行攔截處理。該方法的返回值爲boolean 類型,表示是否阻止webview繼續加載url,默認值爲 false。當返回false,表示不進行阻止,webview認爲當前的url需要進行處理,會繼續加載;返回 true,表示阻止webview繼續加載url,等待我們進行處理。

     那麼如何判斷 webview 將要加載的url會不會發生重定向呢?WebView中有個靜態類 HitTestResult,這個類中有一些被 final 修飾的 int 變量,這些變量表示webview加載的url所屬的網頁類型。還有兩個get方法 getType() 和 getExtra() , getType() 表示獲取加載url的網頁類型; getExtra() 表示根據url打開的網頁類型,返回一個extra信息,如果打開類型爲 UNKNOWN_TYPE(打開的內容未知) ,此時 url 就會通過requestFocusNodeHref(Message)方法異步重定向,則extra就沒有返回值,爲null。經過上面分析,我們可以對getType() 和 getExtra() 獲取到的返回值進行判斷,當 getType()==0 (打開內容未知) 或者 getExtra() 爲 null 時,就認爲webview加載的url會發生重定向,我們此時就在shouldOverriderUrlLoading方法中對其進行處理。

HitTestResult 類中變量值所對應打開的網頁類型

接下來看看如何判定加載的url是非 http/https 的自定義協議。很簡單,對shouldOverriderUrlLoading方法中的參數 String url進行判斷,url.startsWith("http://")||url.startsWith("https://") 即表示加載的url是 http/https 協議,不對其進行攔截處理,反之則進行攔截處理。

@Override
public boolean shouldOverrideUrlLoading(final WebView view, final String url) {

    WebView.HitTestResult hit = view.getHitTestResult();
    //hit.getExtra()爲null或者hit.getType() == 0都表示即將加載的URL會發生重定向,需要做攔截處理
    if (TextUtils.isEmpty(hit.getExtra()) || hit.getType() == 0) {
        //通過判斷開頭協議就可解決大部分重定向問題了,有另外的需求可以在此判斷下操作
        Log.e("重定向", "重定向: " + hit.getType() + " && EXTRA()" + hit.getExtra() + "------");
        Log.e("重定向", "GetURL: " + view.getUrl() + "\n" +"getOriginalUrl()"+ view.getOriginalUrl());
        Log.d("重定向", "URL: " + url);
    }

    if (url.startsWith("http://") || url.startsWith("https://")) { //加載的url是http/https協議地址
        view.loadUrl(url);
        return false; //返回false表示此url默認由系統處理,url未加載完成,會繼續往下走

    } else { //加載的url是自定義協議地址
        try {
            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
            context.startActivity(intent);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章