4

I have webView which overrides shouldInterceptRequest method:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) {
    WebResourceResponse response = proxy.getWebResourceResponse(request.getUrl(), request.getMethod(), request.getRequestHeaders());
    if (response == null) {
        return super.shouldInterceptRequest(view, request);
    } else {
        return response;
    }
}

@SuppressWarnings("deprecation")
@Override
public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
    WebResourceResponse response = proxy.getWebResourceResponse(Uri.parse(url), "GET", null);
    if (response == null) {
        return super.shouldInterceptRequest(view, url);
    } else {
        return response;
    }
}

The problem is that on Lollipop+ both methods are called. So I think that I should specify that deprecated version should be used only for old Android version. Exactly inverse of RequiresApi... If cause that can be solved with making copy paste classes and using if-else to choose class depending on Android version... But that's really ugly.

UPDATE. Updated to better reflect the problem.

Jehy
  • 4,729
  • 1
  • 38
  • 55
  • 1
    The @RequiresApi annotation is only a compile-time flag to suppress api-level errors and a note to the caller that it should check the version before calling the method. It does not do anything at runtime and so it is not comparable to if-else statements. – RobCo Mar 15 '17 at 08:34
  • You have to stick with `if-else` approach, where you check the API level and call the appropriate implementation. – azizbekian Mar 15 '17 at 08:39
  • 1
    What is your code exactly? The newer version of shouldInterceptRequest calls the older version in the base class. If you override shouldInterceptRequest completely (without super call) the older one should not be called, imho. – Stan Mar 15 '17 at 08:52
  • @Stan, I added complete code. It calls super, but with current implimentation so it should be fine... Also I see that deprecated method is called not from super but from this class. – Jehy Mar 16 '17 at 07:52
  • I'm not sure what you mean. When you calls `super.shouldInterceptRequest(view, request);` in your LOLLIPOP specific code, it calls your implementation of non-LOLLIPOP specific (deprecated) handler. See for example [here](https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/webkit/WebViewClient.java). – Stan Mar 16 '17 at 09:42
  • @Stan it should not call deprecated version because request argument is `WebResourceRequest`, not `String`. – Jehy Mar 16 '17 at 10:11
  • 1
    Please, see Android source codes. Newer handler's default implementation does invoke older handler with url as a string coming from request. – Stan Mar 16 '17 at 13:04
  • @Stan Yup, thanks! I could not expect that all it would do is to call deprecated method. Thanks! Please leave this as an answer so I can accept it. – Jehy Mar 16 '17 at 13:35

1 Answers1

6

The default implementation of WebViewClient in Android source codes invokes the deprecated version of shouldInterceptRequest from the newer one, passing current URL from the request as a string:

@Deprecated
public WebResourceResponse shouldInterceptRequest(WebView view, String url)
{
    return null;
}

public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request)
{
    return shouldInterceptRequest(view, request.getUrl().toString());
}

Since you call the default Lollipop-specific handler from your custom WebViewClient implementation (using super.shouldInterceptRequest(view, request) when request is null), it invokes, in turn, your overriden implementation of the deprecated handler.

You should not call the super method from your new implementation in order to eliminate the deprected method execution.

Stan
  • 8,683
  • 9
  • 58
  • 102