Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebView shouldOverrideUrlLoading() not called for invalid links

Tags:

There are two types of links in the HTML file:

(1) A normal link like http://www.bbb.com/q?type=normal
(2) A short link like /q?type=short.

For the first kind, just load the url. For the second kind, I should prepend it with a fixed address like http://www.abc.com before loading the url.

I am trying to do this with overriding the shouldOverrideUrlLoading() function in WebViewClient. However this function doesn't gets called for the second type of link. I tried prepending the "http://www.abc.com" to the second type of links in the HTML file. Then the function does get called when I click the second kind of link.

I think what's happening is WebView will first check if the link is a valid url. Only if it is valid will the function gets called. Am I right? How can I solve this? Thanks in advance.

        contentWebView = new WebView(context);

        webViewClient = new WebViewClient() {
            @Override
            public void onPageStarted(WebView view, String url, Bitmap favicon) {
                super.onPageStarted(view, url, favicon);
            }

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // String not in Logger.
                Log.d(TAG, "Here!");
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
                context.startActivity(intent);
                return true;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);
                if (hosted) {
                    contentWebView.setVisibility(VISIBLE);
                } else {
                    summaryTextView.setVisibility(VISIBLE);
                    articleLinkButton.setVisibility(VISIBLE);
                }

                progressBar.setVisibility(View.GONE);
            }
        };

        contentWebView.setWebViewClient(webViewClient);
        contentWebView.getSettings().setJavaScriptEnabled(true);
        contentWebView.loadData(fullString, "text/html", "utf-8");
        contentWebView.setVisibility(GONE);

More on this:

I tried changing

contentWebView.loadData(fullString, "text/html", "utf-8");

to

contentWebView.loadDataWithBaseURL("http://www.abc.com", fullString, "text/html", "utf-8", null);

Then the function gets called.

If I change the short link to a full link in the html string manually. Then the function also gets called.

So I think this is probably what is happening: The WebView checks if the link URL is valid. Only when the URL is valid will the shouldOverrideUrlLoading() be called.

like image 793
darklord Avatar asked Apr 25 '14 16:04

darklord


3 Answers

You're probably using the KitKat WebView. This is a known issue (I think it's outlined in the migration guide) where URLs that can't be resolved against the base URL are dropped on the floor (you won't get any callbacks for them, neither shouldOverrideUrlLoading nor onPageStarted).

The problem is that your base URL is a data url, so you're trying to resolve '/q?type=short' against 'data:text/html,...' which doesn't make much sense and so the whole attempt to navigate to the URL gets ignored.

This was different for the pre-KK WebView which used KURL instead of GURL for URL processing. GURL is generally more strict (and more secure) than KURL, which is the cause for some incompatibility between the two WebView versions.

like image 179
marcin.kosiba Avatar answered Sep 20 '22 02:09

marcin.kosiba


Maybe try using onPageStarted method

like image 10
michal.luszczuk Avatar answered Sep 20 '22 02:09

michal.luszczuk


solution that worked for me was to use loadDataWithBaseURL with an invalid baseUrl and detect that and remove it and replace with "http://" during setWebViewClient

public class MyActivity
    extends Activity
{
    private static final String badurl = "http://myappname.invalid/";

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        ...
        WebView wv = ((WebView)findViewById(R.id.webview));
        WebSettings settings = wv.getSettings();
        settings.setJavaScriptEnabled(false);
        settings.setSupportMultipleWindows(true);
        wv.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onCreateWindow(WebView view, boolean isDialog, boolean isUserGesture, Message resultMsg)
            {
                handleUrlview.getHitTestResult().getExtra());
                return true;
            }
        });
        wv.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) 
            {
                handleUrl(url);
                return true;
            }
        });
        wv.loadDataWithBaseURL(badurl,text,"text/html","utf-8",null);
    }

    private void handleUrl(String url)
    {
        if (url.startsWith(badurl))
            url = "http://"+url.substring(badurl.length());
        try {
            startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
        } catch (ActivityNotFoundException e) { }
    }
}
like image 7
SteelBytes Avatar answered Sep 20 '22 02:09

SteelBytes