Android’s WebViewClient.shouldInterceptRequest() is called only for the first time

Issue

I use a WebView in an Android app. A WebViewClient is used to intercept a target “https://” REST request so that I can do some custom handling on the native client side.

The problem is that WebViewClient.shouldInterceptRequest(WebView, WebResourceRequest) is called only the first time when the app is run. Subsequent network requests to the same REST service do not invoke shouldInterceptRequest() any more. I have to either uninstall the app or “Clear Storage” in the App Info system setting for it to call shouldInterceptRequest() again.

To rule out the possibility that the web site is caching the service response, I use Charles Proxy to monitor the network traffic. I can see that a new network request is made each time the web page is loaded, regardless shouldInterceptRequest() is triggered or not.

What could be the reasons that shouldInterceptRequest() is not called after the the first time?

Solution

It turns out that the web app I am trying to embed uses browser Service Worker. The network requests made by the Service Worker cannot be intercepted by the WebViewClient. In order to intercept Service Worker network requests, a ServiceWorkerClientCompat must be used.

The solution for me is to set up BOTH a WebServiceClient and a ServiceWorkerClient, since a service worker has it own lifecycle and may not be activated in some cases (e.g. first time the app is run).

Sample code as follows.

if (WebViewFeature.isFeatureSupported(WebViewFeature.SERVICE_WORKER_BASIC_USAGE)) {
   ServiceWorkerControllerCompat.getInstance().setServiceWorkerClient(
          object : ServiceWorkerClientCompat() {
              override fun shouldInterceptRequest(request: WebResourceRequest): WebResourceResponse? {
                  // custom handling
              }
   })
}

Answered By – hli

Leave a Comment