Feb 01 2009

Intercepting page loads in WebView

Category: Android,WebView examplesAleksander Kmetec @ 6:20 am

It is time for another WebView example. This time on how you can intercept any attempts at loading a web page and redirect the user to a different URL instead.

This can be achieved simply by registering a WebViewClient which overrides the shouldOverrideUrlLoading() method in which you tell the WebView to load a different URL from the one the user had requested.

The example below loads lexandera.com first, but when the user clicks any link on the page, he is redirected to yahoo.com:


WebView browser = (WebView)findViewById(R.id.browser);
browser.setWebViewClient(new WebViewClient() {
    /* On Android 1.1 shouldOverrideUrlLoading() will be called every time the user clicks a link,
     * but on Android 1.5 it will be called for every page load, even if it was caused by calling loadUrl()! */
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url)
    {
        /* intercept all page load attempts and load yahoo.com instead */
        String myAlternativeURL = "http://yahoo.com";
        if (!url.equals(myAlternativeURL)) {
            view.loadUrl(myAlternativeURL);
            return true;
        }
        
        return false;
    }
});

browser.loadUrl("http://lexandera.com/");

Please note that calling loadUrl() does not trigger the shouldOverrideUrlLoading() method, which means that we do not need to worry about endless recursion when calling loadUrl() from within shouldOverrideUrlLoading()!

UPDATE: The above statement is no longer true for Android 1.5! Calling loadUrl() will now also trigger the shouldOverrideUrlLoading() method! This means that you need to make sure that you are not creating an infinite loop when calling loadUrl() from shouldOverrideUrlLoading()!

Reblog this post [with Zemanta]

Tags: , ,


Jan 29 2009

Extracting HTML from a WebView

Category: Android,Semantic Web,Uncategorized,WebView examplesAleksander Kmetec @ 8:30 pm

Here’s another Android WebView tutorial for those of you who are looking for a way to get the source code of a page loaded in a WebView instance.

This example is a bit more complicated than previous ones, so let me explain it step by step:

  • First, a class called MyJavaScriptInterface is defined. It implements a single public method showHTML() which displays a dialog with the HTML it receives as a parameter.
  • Then, an instance of this class is registered as a JavaScript interface called HTMLOUT. The showHTML() method can now be accessed from JavaScript like this: window.HTMLOUT.showHTML(‘…’)
  • In order to call showHTML() when the page finishes loading, a WebViewClient instance which overrides onPageFinished() is added to the WebView. When the page finises loading, this method will inject a piece of JavaScript code into the page, using the method I described in an earlier post.
  • Finally, a web page is loaded.

final Context myApp = this;

/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface 
{
    @SuppressWarnings("unused")
    public void showHTML(String html)
    {
        new AlertDialog.Builder(myApp)
            .setTitle("HTML")
            .setMessage(html)
            .setPositiveButton(android.R.string.ok, null)
        .setCancelable(false)
        .create()
        .show();
    }
}

final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */ 
browser.getSettings().setJavaScriptEnabled(true);

/* Register a new JavaScript interface called HTMLOUT */
browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");

/* WebViewClient must be set BEFORE calling loadUrl! */
browser.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url)
    {
        /* This call inject JavaScript into the page which just finished loading. */
        browser.loadUrl("javascript:window.HTMLOUT.showHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }
});

/* load a web page */
browser.loadUrl("http://lexandera.com/files/jsexamples/gethtml.html");

WARNING
Unfortunately, this approach suffers from a major security hole: if your JavaScript can call showHTML(), then so can JavaScript from every other page that might get loaded into the WebView. Use with care.

Reblog this post [with Zemanta]

Tags: , , ,


Jan 27 2009

Adding alert() support to a WebView

Category: Android,JavaScript,WebView examplesAleksander Kmetec @ 9:54 pm

As promised earlier, here is an example of how to add support for alert() function to a WebView in your Android application:


final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */ 
browser.getSettings().setJavaScriptEnabled(true);

final Context myApp = this;

/* WebChromeClient must be set BEFORE calling loadUrl! */
browser.setWebChromeClient(new WebChromeClient() {
    @Override
    public boolean onJsAlert(WebView view, String url, String message, final android.webkit.JsResult result) 
    {
        new AlertDialog.Builder(myApp)
            .setTitle("javaScript dialog")
            .setMessage(message)
            .setPositiveButton(android.R.string.ok,
                    new AlertDialog.OnClickListener() 
                    {
                        public void onClick(DialogInterface dialog, int which) 
                        {
                            result.confirm();
                        }
                    })
            .setCancelable(false)
            .create()
            .show();
        
        return true;
    };
});

/* load a web page which uses the alert() function */
browser.loadUrl("http://lexandera.com/files/jsexamples/alert.html");

Code for adding support for confirm() and prompt() is almost identical and can be found in Mosembro’s source code.

Reblog this post [with Zemanta]

Tags: , , ,


Jan 20 2009

Android WebChromeClient

Category: Android,WebView examplesAleksander Kmetec @ 4:30 am

My blog stats are telling me that many visitors are arriving here looking for examples on how to implement WebChromeClient on Android. I don’t (yet) have a nice article about how to do it, but you can have a look at how I implemented WebChromeClient in Mosembro, if you came here for that reason. Just use your browser’s search functionality and look for “new WebChromeClient”.

Reblog this post [with Zemanta]

Tags: , , , ,


Jan 02 2009

Injecting JavaScript into a WebView

Category: Android,JavaScript,WebView examplesAleksander Kmetec @ 7:05 am

Back in early ’08, while the Androd developer challenge was in full swing, a fairly common question which went without a satisfactory answer was: “How can I manipulate the contents of a WebView?”. I now finally have the answer, thanks to a couple of lines of code I stumbled upon while looking at the source of Jeffrey Sharkey‘s OilCan.

The solution is actually very simple: wait for the original page to finish loading, then inject your own JavaScript code into it by calling webview.loadUrl(“javascript:your-code-here”) when your webvew’s onPageFinished() event is triggered. Loading an URL beginning with “javascript:” is the exact same approach used by bookmarklets.

Here’s a simple example which loads a page and then sets its text color to red:


final WebView webview = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
webview.getSettings().setJavaScriptEnabled(true);

/* WebViewClient must be set BEFORE calling loadUrl! */
webview.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url)
    {
        webview.loadUrl("javascript:(function() { " +
                "document.getElementsByTagName('body')[0].style.color = 'red'; " +
                "})()");
    }
});

webview.loadUrl("http://code.google.com/android");

That’s it.

Please note though that alert() and confirm() JavaScript functions will not work unless you also register a WebChromeClient which implements the required methods.

Reblog this post [with Zemanta]

Tags: , , , ,