Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
574 views
in Technique[技术] by (71.8m points)

android - WebViewClient not calling shouldOverrideUrlLoading

The problem is rather simple. In the application we want to keep track of the current url being displayed. For that we use shouldOverrideUrlLoading callback from the WebViewClient by saving the url into a class field for every update. Here is the relevant code:

    mWebView.getSettings().setJavaScriptEnabled(true);
    mWebView.getSettings().setDomStorageEnabled(true); 
    mWebView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            mCurrentUrl = url;

            // If we don't return false then any redirect (like redirecting to the mobile
            // version of the page) or any link click will open the web browser (like an
            // implicit intent).
            return false;
        }



        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            ...
        }
    });
    mWebView.loadUrl(mInitialUrl);

However, there is at least one scenario, where the callback never gets triggered and the mCurrentUrl field doesnt get updated.

The url: https://m.pandora.net/es-es/products/bracelets/556000

Last updated url (shouldOverrideUrlLoading never gets called when clicking the product): https://m.pandora.net/es-es/products/bracelets

I have tried with callbacks like onPageStarted(), but the url also gets filtered and there doesn't seem to be an accessible one upstream since its protected code.

Reading android documentation about WebView I found this:

https://developer.android.com/guide/webapps/migrating.html#URLs

The new WebView applies additional restrictions when requesting resources and resolving links that use a custom URL scheme. For example, if you implement callbacks such as shouldOverrideUrlLoading() or shouldInterceptRequest(), then WebView invokes them only for valid URLs.

But still doesnt make sense since the above url is generic and should meet the standard.

Any alternative or solution to this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

When you click a product on that web page, it loads the new content in with JavaScript and updates the visible URL in the address bar using the HTML5 History APIs.

From the above MDN article:

This will cause the URL bar to display http://mozilla.org/bar.html, but won't cause the browser to load bar.html or even check that bar.html exists.

These are sometimes called single-page applications. Since the actual loaded page doesn’t change, the WebView callback for page loads isn’t called.

In case you know precisely what kind of HTTP request you want to intercept, you could use the shouldInterceptRequest callback that gets called for each request. It’s likely that the web application loads some data from an API, for example when a product is shown, which you could then detect.

If detecting this isn’t possible, but you’re in control of the web application, you could use the Android JavaScript interface to invoke methods within the Android application directly from the web page.

If you’re not in control of the loaded page, you could still try to inject a local JavaScript file into the web page and observe when the history APIs are used, then call methods in your Android application over the JS interface. I tried observing these events in Chrome with the method described in the previous link and it seems to work fine.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...