34

Does anyone know if there is a way to intercept a "page not found" or "page not loading error" in WebView?

According to the android documentation, onReceivedError() should be able to intercept. but i tested it in an app which I deleberately gave the wrong URL, and it didn't do anything.

I want my app to be able to give my own custom error message if the URL is ever unavailable for any reason.

this is the code that did nothing:

public void onReceivedError(WebView view, int errorCode,
        String description, String failingUrl) {

    // custom error handling ... show and alert or toast or something
}
Octavian Helm
  • 39,405
  • 19
  • 98
  • 102
Joe Winfield
  • 809
  • 4
  • 11
  • 18

4 Answers4

34

According to documentation and my experience it should work quite fine. You just have to set your WebClient with overriden method onReceivedError in your WebView.

Here is the snippet from some of my old test app:

 WebView wv = (WebView) findViewById(R.id.webView);
 wv.setWebViewClient(new WebViewClient() {
    @Override
    public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            Log.i("WEB_VIEW_TEST", "error code:" + errorCode);
            super.onReceivedError(view, errorCode, description, failingUrl);
    }
 });

I've tested it and it works quite fine. Check your logs and see what kind of code error do you get. Hope it helps.

androdevo
  • 752
  • 1
  • 8
  • 17
  • what i'm trying to do is make it do something else on error, super.onReceivedError(view, errorCode, description, failingUrl); myWebView.LoadUrl("www.someOtherSite.net"); but it doesn't do anything but give me the "Not Found" error page. – Joe Winfield Feb 15 '11 at 03:49
  • it would be too much code for this little window. but i used the code example you showed above. – Joe Winfield Feb 16 '11 at 19:15
  • 3
    You can try to load some alternative page with 'loadData(...)' method in 'onReceivedError'. It should quickly switch the content of the error page... – androdevo Feb 16 '11 at 22:01
  • 7
    It seems this method is only called on loading errors like timeouts, not on 404 errors. (A page successfully loads in this cases, just not with status 200 OK) – ToBe May 27 '13 at 13:04
  • You should be careful when using onReceivedError with a WebView. It may get triggered also on JavaScript errors after the page loads (e.g. the page loads fine but post document.Ready JS code tries to get to a Url and get Http 404, triggers the onReceivedError and your thinks there is a problem reaching the original URL). You should always check what error you got and if the URL is the same as the WebView's URL. – FunkSoulBrother Sep 01 '15 at 13:15
  • 6
    `onReceivedError` deprecated in API 23. Use `public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error)` – zackygaurav Nov 05 '15 at 12:44
  • onReceivedError does not fire in Lollipop. – user1841702 Oct 30 '16 at 06:13
13

I have tried using onReceivedError both inside shouldOverrideUrlLoading() and outside that method but in the WebViewClient. I even tried outside in the main Activity class. I was not happy with the inconsistent results. So I settled on using a test method, isOnline(), and calling that before calling loadUrl().

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getBaseContext()
            .getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo i = cm.getActiveNetworkInfo();
    if ((i == null) || (!i.isConnected())) {
        Toast toast = Toast.makeText(getBaseContext(),
                "Error: No connection to Internet", Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 0);
        toast.show();
        return false;
    }
    return true;
}

Then this onReceivedError is in the WebViewClient but outside the overloadurlthingy method. This seems to consistently prevent the stupid, smirking-android error pages.

    @Override
    public void onReceivedError(WebView view, int errorCode,
            String description, String failingUrl) {
        if (view.canGoBack()) {
            view.goBack();
        }
        Toast toast = Toast.makeText(getBaseContext(), description,
                Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.TOP | Gravity.CENTER, 0, 0);
        toast.show();
    }

Some people might consider this resource-heavy. Well, not heavy the way the Android Facebook and Google+ apps are. And not the way Google services are. I frankly don't mind using up a little of those apps oxygen. Call me a bad boy...

R Earle Harris
  • 985
  • 9
  • 17
2

You should use this after the on Page finished

 @Override
    public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error){
           //Your code to do
        Toast.makeText(getActivity(), "Your Internet Connection May not be active Or " + error , Toast.LENGTH_LONG).show();
    }
Harsh Mittal
  • 2,868
  • 1
  • 16
  • 21
1

Remember use both onReceivedError methods because the method with the description parameter is deprecated. We use this deprecated method for below API 23 support. Hence we can use it in all SDK versions.

Here how I do it -

   webview.setWebViewClient(new WebViewClient() {


        @SuppressWarnings("deprecation")
        @Override
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {

            try {
                webview.stopLoading();
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (webview.canGoBack()) {
                webview.goBack();
            }

            showkError();
        }

        @TargetApi(android.os.Build.VERSION_CODES.M)
        @Override
        public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
            // Redirect to deprecated method, so you can use it in all SDK versions
            try {
                webview.stopLoading();
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (webview.canGoBack()) {
                webview.goBack();
            }

            showError();
        }

        @Override
        public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
            super.onReceivedHttpError(view, request, errorResponse);

            try {
                webview.stopLoading();
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (webview.canGoBack()) {
                webview.goBack();
            }

            showError();
        }
  });
Smarpit
  • 99
  • 1
  • 13
  • While this code snippet may be the solution, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-‌​code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. – Johan Mar 01 '19 at 08:45
  • Actually, My grammar skills are worst than many developers out there. I am afraid to write anything wrong here. But I am improving my grammar. – Smarpit Mar 01 '19 at 10:01