webview自定義404、500、斷網(wǎng)、timeout頁面的問題

轉載請標注原創(chuàng)地址:


現(xiàn)在混合開發(fā)的app越來越多,Google對webview也越來越重視,在早期的版本webview有很多的bug,例如404、500等請求錯誤碼我們無發(fā)直接獲?。ㄟ@個bug早在2008年就有人提交過issue給Google),好在Google在Android6.0修復了這個問題。根據(jù)google官網(wǎng)提供的最新的官網(wǎng)文檔,我們可以重寫onReceivedHttpError()方法可以捕獲http Error。

@TargetApi(android.os.Build.VERSION_CODES.M)
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
    super.onReceivedHttpError(view, request, errorResponse);
    // 這個方法在6.0才出現(xiàn)
    int statusCode = errorResponse.getStatusCode();
}

這是google關于這個issue的:</br>
https://code.google.com/p/android/issues/detail?id=968

下面是google開發(fā)人員回復:

Google雖然在Android6.0解決了這個問題,但是Android6.0以下的手機市場占有率還是很多的,所以我們就要自己手動去解決這個問題。

處理404、500

在Android6.0以下我們是不能直接獲取到404或者500的,Android6.0谷歌解決了這個問題。那么在Android6.0以下的系統(tǒng)我們如何處理404這樣的問題呢?

兩種解決方案:

方案一(推薦)通過獲取網(wǎng)頁的title,判斷是否為系統(tǒng)默認的404頁面

我們可以在WebChromeClient()子類中可以重寫他的onReceivedTitle()方法</br>

Android6.0以下判斷404或者500:

@Override
public void onReceivedTitle(WebView view, String title) {
    super.onReceivedTitle(view, title);
    // android 6.0 以下通過title獲取
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
        if (title.contains("404") || title.contains("500") || title.contains("Error")) {
            view.loadUrl("about:blank");// 避免出現(xiàn)默認的錯誤界面
            view.loadUrl(mErrorUrl);
        }
    }
}

Android6.0以上判斷404或者500:

@TargetApi(android.os.Build.VERSION_CODES.M)
@Override
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
    super.onReceivedHttpError(view, request, errorResponse);
    // 這個方法在6.0才出現(xiàn)
    int statusCode = errorResponse.getStatusCode();
    System.out.println("onReceivedHttpError code = " + statusCode);
    if (404 == statusCode || 500 == statusCode) {
        view.loadUrl("about:blank");// 避免出現(xiàn)默認的錯誤界面
        view.loadUrl(mErrorUrl);
    }
}

判斷斷網(wǎng)和鏈接超時

@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
    super.onReceivedError(view, errorCode, description, failingUrl);
    // 斷網(wǎng)或者網(wǎng)絡連接超時
    if (errorCode == ERROR_HOST_LOOKUP || errorCode == ERROR_CONNECT || errorCode == ERROR_TIMEOUT) {
        view.loadUrl("about:blank"); // 避免出現(xiàn)默認的錯誤界面
        view.loadUrl(mErrorUrl);
    }
}

方案二(極力不推薦) 通過HttpURLConnection請求url獲取狀態(tài)碼

在webview加載url前先通過HttpURLConnection獲取請求碼,這種方案有時候不會觸發(fā)shouldOverrideUrlLoading()方法,但是網(wǎng)上還有很多的呼聲。

private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        int code = msg.what;
        if (code == 404 || code == 500) {
            System.out.println("handler = " + code);
            mWebView.loadUrl(mErrorUrl);
        }
    }
};

new Thread(new Runnable() {
    @Override
    public void run() {
        int responseCode = getResponseCode(mUrl);
        if (responseCode == 404 || responseCode == 500) {
            Message message = mHandler.obtainMessage();
            message.what = responseCode;
            mHandler.sendMessage(message);
        }
    }
}).start();

mWebView.loadUrl(mUrl);

mWebView.setWebViewClient(new WebViewClient() {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                int responseCode = getResponseCode(mUrl);
                if (responseCode == 404 || responseCode == 500) {
                    Message message = mHandler.obtainMessage();
                    message.what = responseCode;
                    mHandler.sendMessage(message);
                }
            }
        }).start();
        view.loadUrl(url);
        return true;
    }
}

HttpURLConnection獲取請求狀態(tài)碼

/**
 * 獲取請求狀態(tài)碼
 *
 * @param url
 * @return 請求狀態(tài)碼
 */
private int getResponseCode(String url) {
    try {
        URL getUrl = new URL(url);
        HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection();
        connection.setRequestMethod("GET");
        connection.setReadTimeout(5000);
        connection.setConnectTimeout(5000);
        return connection.getResponseCode();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return -1;
}

方案三(推薦) 服務器后臺是能獲取404、500的,最好的辦法是讓后臺捕獲

這里就不說了

測試用的500的test.jsp頁面

完整代碼和測試頁面:

http://download.csdn.net/download/lsyz0021/9760751

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容