57

In the Android SDK 23 onReceivedError(WebView view, int errorCode, String description, String failingUrl) has been deprecated and replaced with onReceivedError(WebView view, WebResourceRequest request, WebResourceError error). However if I put my phone in Airplane mode and load an url on my WebView, only the deprecated version of the method is called.

onReceivedHttpError (WebView view, WebResourceRequest request, WebResourceResponse errorResponse) is also not useful, as it only detects errors higher than 500, and I am getting a 109 status code.

Is there a non-deprecated way of detecting that my WebView failed to load?

Martin Epsz
  • 842
  • 1
  • 8
  • 16
  • make sure you are testing with Android SDK 23 – karan Sep 25 '15 at 11:36
  • @KaranMer, that is already the case. – Martin Epsz Sep 25 '15 at 14:26
  • 4
    Does the mobile device where you are testing actually run Android Marshmallow (API 23)? Even if you develop your app on API 23 SDK, but then run the app on Android Lollipop, you will still be getting the "old" `onReceivedError`, because it's the feature of the OS, not of an SDK. Also, the "error code 109" (I guess, this is net::ERR_ADDRESS_UNREACHABLE) is not an HTTP error code, it's Chrome's error code. `onReceivedHttpError` is only called for the errors received from the server via HTTP. When the device is in airplane mode, it can't possibly receive a reply from a server. – Mikhail Naganov Sep 26 '15 at 01:02
  • @MikhailNaganov that is helpful. if you post that as an answer, I will accept it. – Martin Epsz Sep 26 '15 at 20:36
  • So the solution is to override both methods in the client, and expect the OS to determine which one is called, I guess. – Richard Le Mesurier Aug 31 '16 at 13:23
  • @MikhailNaganov Wait, so does that mean if the app is targeted for API < 23 but is running on > 23, the *old* onReceivedError won't work? Because that would seem wrong - how the heck can you get the new one if the API doesn't support it? – Michael Nov 15 '16 at 03:25
  • @Michael It will. Take a look at the source: https://android.googlesource.com/platform/frameworks/base.git/+/master/core/java/android/webkit/WebViewClient.java#263 If the app didn't overload the new version of onReceivedError then the default implementation in WebViewClient will call it. – Mikhail Naganov Nov 15 '16 at 16:32

2 Answers2

138

You could also do following:

@SuppressWarnings("deprecation")
@Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
    // Handle the error
}

@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
    onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
}

Make sure you import android.annotation.TargetApi

Nimantha
  • 6,405
  • 6
  • 28
  • 69
xdevs23
  • 3,824
  • 3
  • 20
  • 33
  • 2
    this works! 30.11.2015 , on android 4x, with latest sdk for 5x – jmp Nov 30 '15 at 19:16
  • 13
    Please be aware that the new SDK 23 callback will be called for any resource (iframe, image, etc) that failed to load, not just for the main page... therefore your handling of errors may need to be modified accordingly. – k2col Apr 19 '16 at 06:30
  • Yep I guess the user could handle it in his own way, it might vary, depending on what you are using it for. – xdevs23 Apr 19 '16 at 19:45
  • does @TargetApi also work on new api, e.g. 24? does it override onReceivedError for all API >=23 or only API=23? – Lucker10 Jul 23 '16 at 17:26
  • 1
    It should override >= 23 @Lucker10 – xdevs23 Jul 24 '16 at 16:00
  • Is not dangerous about redirecting? – illusionJJ Aug 17 '16 at 12:41
  • No, it's not. At least not now. – xdevs23 Aug 19 '16 at 08:10
  • IMPORTANT NOTE: Google will not allow you to upload apk that uses the above code in playstore... avoid the above code. – Shahid Sarwar Dec 29 '16 at 06:11
  • 1
    Why ? @Shahid Sarwar – xdevs23 Dec 29 '16 at 17:15
  • 1
    I recently used the above code to publish my code but google rejected it.. they no longer allow the use of onReceivedError() directly or indirectly instead you will have to use onReceivedSslError() method: see this link http://stackoverflow.com/questions/36050741/webview-avoid-security-alert-from-google-play-upon-implementation-of-onreceiveds for proper solution.. any other solution won't work anymore. – Shahid Sarwar Dec 30 '16 at 13:03
  • 4
    @ShahidSarwar That's wrong! The problem you had is in no way related to the code discussed in this question. The `onReceivedSslError` callback and what you did there is an entirely different subject. – caw Feb 20 '17 at 15:30
  • @caw try publishing an app with onReceivedError() instead of onReceivedSslError() you will know what I mean. – Shahid Sarwar Feb 21 '17 at 07:00
  • Thanks for the info! @ShahidSarwar – AlexioVay Mar 23 '17 at 21:26
  • 3
    @ShahidSarwar tried publishing and it got published, now what? – Lalit Poptani Jul 05 '17 at 12:24
  • Maybe they found out that this could be necessary. – xdevs23 Jul 05 '17 at 19:19
  • 3
    @ShahidSarwar : Sorry, the link you shared here is a different topic, and it is not having any relevance in this context. The person who asked the question there used 'handler.proceed()'; blindly on the 'onReceivedSslError' callback. That's why Google rejected it, and I also met the same situation once. Anyway, the answer here by xdevs23 is the best, at-least for the time being. – Midhu Aug 04 '17 at 04:16
  • You MUST see https://stackoverflow.com/q/44068123/6120487 to use this method properly! – Lev Leontev Sep 29 '19 at 20:57
  • @k2col How can i handle this case only for the mainpage, as the event is getting triggered many times for one page load. – hemanth kumar Aug 03 '22 at 10:03
  • @hemanthkumar use the `req` parameter to get information – xdevs23 Aug 23 '23 at 21:00
26

Please note that the mobile device where you are testing needs to actually run Android Marshmallow (API 23). Even if you develop your app on API 23 SDK, but then run the app on Android Lollipop, you will still be getting the "old" onReceivedError, because it's the feature of the OS, not of an SDK.

Also, the "error code 109" (I guess, this is net::ERR_ADDRESS_UNREACHABLE) is not an HTTP error code, it's Chrome's error code. onReceivedHttpError is only called for the errors received from the server via HTTP. When the device is in airplane mode, it can't possibly receive a reply from a server.

Mikhail Naganov
  • 6,643
  • 1
  • 26
  • 26