Friday, 10 June 2011

Configuring an Android Application's WebView Component

I recently started on a new project at work to build out a prototype Android application for one of our clients. I'm using the standard Eclipse IDE, Android SDK and ADT Plugin for Eclipse that the Android team recommends.

During development I came across a couple issues related to the WebView component (which is both a layout and a class) that caused a bit of confusion. In case you're not familiar with it, a WebView component can be embedded into an Activity and allows for the viewing of webpages (essentially it mimics the functionality that exists in the device's built-in browser application). I discovered that the WebView component requires some additional tweaking in order for it to behave in a similar manner to the device's built-in browser. The following are the problems and their solutions that needed to be implemented before the Android prototype worked as required:

:: Enabling Flash Content

When viewing a webpage with embedded Flash video content, a pop-up window would display informing the user that they needed to install the latest Flash plug-in. Even after installing the plug-in via the built-in browser and the Android Market App, the pop-up window still appeared and the Flash content was unable to be played. The phone's built-n browser however was able to play the Flash video content (without any pop-up being displayed).

The solution to this problem was that the WebView component needed to have JavaScript and any plugins explicitly enabled before the Flash video content would play. Here is what I included in my Activity's OnCreate method to explicitly enable both these properties:

WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setPluginsEnabled(true)

Note that the webView variable above was previously declared as a private instance variable of type WebView.

:: Initially Rendering in Zoomed Out Mode

When the WebView component loaded and became visible to the user, it arbitrarily rendered a webpage partially zoomed in. This gave a sub-optimal user experience and so the solution was to initially render the webpage in a fully zoomed out mode so that the user could view the whole webpage and decide for themselves if they wanted to perform a pinch gesture to zoom in on a particular area. Again, here is what I included in my Activity's OnCreate method so that the WebView component rendered any webpage fully zoomed out:

WebSettings webSettings = webView.getSettings();
webSettings.setLoadWithOverviewMode(true);
webSettings.setUseWideViewPort(true);

Again note that the webView variable above was previously declared as a private instance variable of type WebView.

:: Forcing WebView to Load all URLs

For a certain subset of URLs that I was trying to load within my WebView component, my application would quit and the phone's internal web browser would launch and load the webpage successfully. I therefore needed to find a solution that would force all URLs to load within my WebView instead of being launched externally on the phone's internal web browser.

The solution entailed creating a CustomWebViewClient class that extended WebViewClient and then wiring up the CustomWebViewClient to handle the shouldOverrideUrlLoading method. This allowed me to force the WebView within my application to render all URLs I was presenting to the user:

private WebView webView = new WebView();
private CustomWebViewClient webViewClient = new CustomWebViewClient();

protected void OnCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    webView.setWebViewClient(webViewClient);
}

private class CustomWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        view.loadUrl(url);
        return true;
    }
}

-------------------------------

:: Update

I recently found that the Android developer resources have a tutorial on setting up a WebView correctly. It goes into detail for some (but not all) of the items described above.

Wednesday, 8 June 2011

.NET Code Contracts: Invariants Explained

I have recently started using .NET Code Contracts. I love the streamlined approach to implementing pre-conditions and post-conditions that previously required multi-line if statements along with the ability to check coding assumptions statically and even at runtime (release or debug builds). .NET Code Contracts are another valuable tool in a software engineers arsenal to combat the growing complexity of software systems.

The latest MSDN magazine (June, 2011) has an thorough article on invariants which are an element of .NET Code contracts. The article will go into much more detail but essentially invariants allow for the verification of an object's internal state before and after a set of operations. To create an object invariant, a class simply needs to contain a new private method with the ContractInvariantMethod attribute and then specify any conditions within the private method that should hold true before and after any operation on the class or instances of the class. Here is an example of what the object invariant method would look like for a class called News which has internal state for the Title and Body of a news article:

[ContractInvariantMethod]
private void ObjectInvariant()
{
     Contract.Invariant(!String.IsNullOrEmpty(Title));
     Contract.Invariant(!String.IsNullOrEmpty(Body));
}

What this accomplishes for programmers is that if they inadvertently try to alter the internal state on an instance of the News class to something it should not be (such as setting Title = string.empty), the .NET Code Contract static checker will warn the programmer that they are violating the object's invariant.

Thus, programmers can now design and build classes with the help of .NET Code Contracts that enforce correct API usage. This is a very powerful feature that will avoid subtle bugs from ever occurring.