Android WebView flicker when using hardware acceleration on Android 3.0+

There is an Android bug where WebViews may present an ugly flicker when being used on 3.0+ devices with Hardware Acceleration enabled. I was busy with an update to an Android app I’m working on which makes use of a WebView that slides in and out (using this awesome Sliding Menu library), when I noticed the *delightful* surprise when sliding the WebView back in:

Not ideal, is it?

Not ideal, is it?

As much as I can’t believe this kind of bug still exists, especially considering it seems to have been around for some time, it lives with us and thus we need to use some kind of workaround.  I immediately turned to SO for help and found a possible workaround:

WebView “flashing” with white background if hardware acceleration is enabled (Android 3.0+)

The workaround involves using a method that is only available from API level 11 (HoneyComb), and considering my app is targeting a minimum level of 8 I used the following code:

/**
 * Initializes the WebView:
 * - Configures the WebView settings
 * - Adds a WebViewClient
 * - Custom config of the webview
 */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void initWebView()
{
	// Other init code
	
	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
	{
		// This is added as a work-around for the flicker which occurs in Android 3.0+
		// when hardware acceleration is enabled:
		// http://stackoverflow.com/questions/9476151/webview-flashing-with-white-background-if-hardware-acceleration-is-enabled-an
		getWebView().setLayerType(View.LAYER_TYPE_SOFTWARE, null);
	}
}

So pick your poison: reduced performance or flickering?

The iOS BlocksKit framework is awesome…

iOS Blocks are segments of code that can be passed around for later execution, in the same manner as a value or parameter can be passed to a function. At first, the syntax surrounding the use of blocks may seem a little confusing or unconventional, but once you begin to use them, you will find that they are in fact relatively straightforward and can speed up your development in many instances.

void (^simpleBlock)(void) = ^{ ..... eh??!!?

void (^simpleBlock)(void) = ^{ ….. eh?!!?

The really great thing about Blocks is that they give you a quick way to define a snippet of code that can capture and access the enclosing scope and its values, yet still be executed at later point in time when a particular event has occurred; all of this without the hassle of having to define excessive delegates or callbacks.

BlocksKit is a really neat framework which consists of lots of utility and category classes to make the use of blocks more accessible with existing framework classes such as NSDictionary and UIBarButtonItem. Below is just one example of where BlocksKit can come in handy.

Example: Presenting a ModalViewController

Let’s take the example of presenting an information screen (InfoViewController) to a user in a universal application. On an iPad we may want to present the information screen as a popover without a navigation bar, however, on an iPhone we may want to present the screen modally but provide the user with a ‘Done’ bar button in the navigation bar to dismiss the screen; furthermore, let’s say we wanted to do this without having to alter the .xib of the InfoViewController.

One method of doing this would be to modify the InfoViewController’s implementation to add a ‘Done’ button only if executed on an iPhone, such as:

- (void)viewDidLoad
{
    [super viewDidLoad];

    BOOL iPhone = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone);

    if (iPhone)
    {
        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissViewController:)];
        self.navigationItem.rightBarButtonItem = doneButton;
    }

    ...
}

This would result in a dismiss ‘Done’ button appearing in the navigation bar on an iPhone, but not when running on an iPad. Whilst this works, in some cases it’s not ideal that the InfoViewController itself has to be aware of how it is being presented, i.e. modally in this case; one would rather leave such logic to whatever is creating and using the view controller. Another (better) option would be to have the creator/user of the InfoViewController simply assign the navigation bar button itself and implement the button’s callback (selector) methods to dismiss the view controller. The downside here is having to implement unnecessary callback methods which clutter your class for such a simple purpose.

This is where blocks can come in really handy. For little tasks such as these, blocks containing the necessary operations to execute at a later stage can be defined and assigned in one place where it makes sense. Below is one example of how the above exercise can be implemented using BlocksKit:

    BOOL iPhone = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone);

    InfoViewController *infoVC = [self.storyboard instantiateViewControllerWithIdentifier:@"InfoViewController"];

    if (iPhone)
    {
        UINavigationController *modalController = [[UINavigationController alloc] initWithRootViewController:infoVC];

        // Present the view controller modally
        [self presentViewController:modalController animated:YES completion:^{

            // This block gets executed once the info view controller has finished presenting.

            // Create the done button for the navigation bar and implement the block that gets
            // executed when the button is tapped.
            UIBarButtonItem *doneBarButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone handler:^(id sender) {

                // When the button is tapped, dismiss the view controller
                [modalController dismissViewControllerAnimated:YES completion:nil];
            }];

            [infoVC.navigationItem setRightBarButtonItem:doneBarButton animated:YES];
        }];
    }
    else
    {
        // Show as a popover view controller
    }

And that’s it! Make sure to check out the BlocksKit framework for many useful classes that can make simple tasks quicker and cleaner IMO.

Simple Data Cache for iOS

I was searching for a simple cache to use for temporary storage of data from web-service calls when I came across EGOCache. Essentially I wanted something that provided the following features:

  • Simple key/value storage structure.
  • Time expiration of data.
  • Persistence of data in the cache.
  • Ability to easily store and persist custom objects.

So far EGOCache has worked really well for my purposes, and storing a custom object is as easy as implementing the NSCoding protocol on your object. The cache also provides an easy access mechanism to the global cache through the following call:

[EGOCache globalCache]

Although I recommend using the cache through a wrapper class; it will prevent coupling your code to the implementation and will safeguard your application code from changes to a different caching mechanism.

UIRefreshControl bug in landscape mode.

The iOS UIRefreshControl provides a standard “pull-down-to-refresh” mechanism for certain UIScrollView classes such as UITableView and UICollectionView.

The UIRefreshControl, however, has a bug in landscape mode on the iPhone whereby there isn’t enough room to pull down to trigger the refresh mechanism. Go here for more information on the bug and possible workarounds.

I ended up using the following code in my UIScrollViewDelegate implementation (both UITableViewDelegate and UICollectionViewDelegate conform to UIScrollViewDelegate):

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (self.collectionView.contentOffset.y < -80 && ![self.pullDownRefreshControl isRefreshing])
    {
        [self.pullDownRefreshControl beginRefreshing];
        // perform refresh operation...
    }
}

The “pull-down-to-refresh” animation isn’t as slick, but it’s a good workaround for now.

Using CocoaPods with an iOS static library

Static Libraries

When developing different iOS projects, you will most likely want to keep common code in a shared library that each individual project can make use of. A useful way of doing this is to package your shared code as a static library which can then be imported into each application project. One problem I had previously experienced when building my own static library a long time ago was the difficulty in bundling resources such as nib files within the library. I wanted to be able to share common code, but what good was it if the library wasn’t going to include all the bits and pieces I wanted, right?!

ponder

Fortunately, there is a great post available here which describes exactly how one can go about building a static library with resources for iOS. I’ve followed the process myself and it works really well. Once setup is complete, as part of building your project it will also build your library and link your project object files against the static library.

Some things to take note of:

  • When performing step 7 (Linking with the Library) of the static library process is to ensure that your library xcode project is closed when attempting to drag the library project from finder into your project navigation pane, otherwise it may not import correctly.
  • When adding new files to your static library, ensure that the header files are added to the Copy Files build phase of your target.

CocoaPods

CocoaPods is a neat tool for managing library dependencies in an Objective-C project. Just like Apache Maven, CocoaPods allows one to specify dependencies in a configuration file and will automatically fetch, install and configure the project with those dependencies.

When using a static library and CocoaPods with your iOS projects, it may be the case that your application project and static library make use of the same 3rd party external libraries. You may think to yourself that you will setup your CocoaPods configuration so that only your static library project includes the 3rd party libraries, in hopes that these will automatically be linked in when building your main project against your static library, however, this won’t work given the way CocoaPods structures your workspace. A static library is essentially just an archive of object files that ultimately get linked to create a final binary/application, so you need to explicitly include the 3rd party libraries in your application project for the linking to take place at build time.

Below are high-level steps to setup a workspace whereby a static library and application project make use of the same 3rd party library, for instance the AFNetworking library:

  • Create a static library project LibProject as shown above.
  • In the root folder of LibProject, create a CocoaPods configuration file Podfile with the following contents:

platform :ios, ‘6.0’

pod ‘AFNetworking’, ‘1.0’

  • Using the terminal, execute the command ‘pod install‘ in the root folder of LibProject.
  • Import the static library project LibProject into your main application project AppProject as explained in the first section of this post.
  • In the root folder of Approject, create a CocoaPods configuration file Podfile with the same contents as above.
  • Using the terminal, execute the command ‘pod install‘ in the root folder of Approject.
  • Make sure to open your project using  AppProject.xcworkspace instead of AppProject.xcodeproj.
  • Hopefully your project can now make use of AFNetworking and build correctly 🙂

CocoaPods Tip: whenever using ‘pod install‘ to setup your Cocoapods dependencies for a project, make sure not to use the superuser, i.e. ‘sudo pod install‘… this will lead to nasty permission problems later on!

Android WebView Scaling

Just as it’s important for an Android developer to understand how to support multiple screen sizes, so too is it important to understand how the Android framework handles the scaling of the content in a WebView.

To demonstrate the scaling that takes place within a webview, I’m going to use a basic example of a webview that displays a local image and some text underneath it – as some additional information, the device used in this example is a Galaxy Nexus with an xhdpi screen (320 dpi) and resolution of 1280×720. Below is the HTML and CSS used and the result of the app run on the said device:

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="sample.css" />
    </head>
    <body>
        <img src="localImage.png"/>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipisicing elit<br>
            bla bla bla
        </p>
   </body>
</html>

the CSS…

img
{
    display: block;
    margin-left: auto;
    margin-right: auto;
}

p
{
	background-color: #E4E4E4;
	padding:1em;
	margin:0.5em;
	border-radius: 15px;
	font-size: 1em;
}

and finally the result…

Web content with default scaling.

Web content with default scaling.

Immediately it becomes obvious that the 300×200 local image has been scaled up considering the resolution of the device. Essentially what the Android framework is doing is assuming that the web content is targeted at an mdpi density (which Android treats as the base density), and as a result scales the content up accordingly for the xhdpi test device so that the drawn elements match the physical size they would appear on an mdpi display. Unless you explicitly specify the density you are targeting, Android will scale up/down accordingly.

To adjust the scaling performed by the Android framework, one can use the viewport meta tag to specify properties regarding screen density support:

<meta name="viewport" content="target-densitydpi=device-dpi" />

The Android docs explain the target-densitydpi property as follows:

You can use this to specify the target density for which the web page is designed, using the following values:

  • device-dpi – Use the device’s native dpi as the target dpi. Default scaling never occurs.
  • high-dpi – Use hdpi as the target dpi. Medium and low density screens scale down as appropriate.
  • medium-dpi – Use mdpi as the target dpi. High density screens scale up and low density screens scale down. This is also the default behavior.
  • low-dpi – Use ldpi as the target dpi. Medium and high density screens scale up as appropriate.
  •  – Specify a dpi value to use as the target dpi (accepted values are 70-400).

So if we use this information and modify our HTML to prevent default scaling:

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="sample.css" />
        <meta name="viewport" content="target-densitydpi=device-dpi" />
    </head>
    <body>
        <img src="localImage.png"/>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipisicing elit<br>
            bla bla bla
        </p>
   </body>
</html>

and run the test app again, we get:

Web content with no scaling

Web content with no scaling

One can now see that no scaling has taken place; the image is displayed as one would expect a 300×200 image on such a device, and the text is significantly smaller. Without the scaling it becomes obvious that the graphic and styles used are not suitable for the xhdpi device, so these would ultimately need to change yet still cater for other densities.

In many simple cases like our example, all we want is to be able to develop and test the web content against a specific test device to ensure that it looks correct, and then allow Android to scale up/down from there. To achieve this, one can declare the specific target density (or even the exact dpi) for which your content is being designed. The following demonstrates this using our example designed for the Galaxy Nexus (320 dpi):

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="sample.css" />
        <meta name="viewport" content="target-densitydpi=320" />
    </head>
    <body>
        <img src="localImage.png"/>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipisicing elit<br>
            bla bla bla
        </p>
   </body>
</html>

 

img
{
    display: block;
    margin-left: auto;
    margin-right: auto;
}

p
{
	background-color: #E4E4E4;
	padding:1em;
	margin:0.5em;
	border-radius: 15px;
	font-size: 2em;
}

With the CSS modified a bit for the higher density and a new higher resolution graphic, we see the following result:

Web content targeted at xhdpi

Web content targeted at xhdpi

We are now happy with the look of the web content on our device, and because we have told the Android framework the specific density we are targeting it will automatically scale up or down for devices with higher or lower densities respectively. The following is a screenshot of the same HTML/CSS and graphic on a lower density emulator:

Web content on an hdpi emulator

Web content on an hdpi emulator

Having said all of this, YMMV with this basic approach. Allowing Android to perform scaling like this may have undesirable results with certain aspects, such as image quality. A more in-depth method for dealing with web content and multiple screen sizes and densities is to provide specific styles/graphics for different densities using the CSS media feature; more information about this can be seen here.

Otto Event Bus for Android

In case you haven’t already checked out this cool framework, Otto is an event bus designed to help parts of your application communicate more effectively and in a more decoupled manner.

With respect to Android, one particular area where the Otto event bus can be really useful is in the passing of complex data objects between the Activity andFragment objects in your application. For instance, when passing a data object between two fragments, traditional methods relied on passing the object via the parent activity or by using the setTargetFragment()/getTargetFragment() methods of the Fragment class; a downside to these approaches is that it couples your fragments/activities to one another. Whilst one can use Interfaces to alleviate the coupling, it requires additional boilerplate code and if more than a single object is required one can be faced with handling the code and coupling of many Interfaces, which is often excessive. The following is a simple Java example of how Otto can simplify the communication amongst components and reduce coupling and boilerplate code.

We have a weather service which periodically needs to provide weather updates to various components. Without the use of Otto, the following is an example of how this could be achieved:

WeatherService Class

 public class WeatherService
{
	private String weatherDescription;
	private List<WeatherListener> listeners = new ArrayList<WeatherListener>();

	
	public void weatherHasBeenUpdatedFromSomewhere(String weatherDescription)
	{
		this.weatherDescription = weatherDescription;
		
		if (listeners != null)
		{
			for (WeatherListener listener : listeners)
			{
				listener.weatherUpdated(weatherDescription);
			}
		}
	}
	
	public void addListener(WeatherListener listener)
	{
		listeners.add(listener);
	}
}

This class has to maintain a list of listeners which it publishes updates to. Notice that although it isn’t coupled with any concrete class, it still has to know about an interface which does very little. Also notice how a large amount of the code is concerned with managing the listeners.
 
WeatherListener Interface


public interface WeatherListener
{
	public void weatherUpdated(String weatherDescription);
}

A simple listener interface. This is largely just boilerplate code given how little this interface achieves.
 
WeatherScreen Class


public class WeatherScreen implements WeatherListener, SomeOtherRandomService
{
	private String weatherDescription;

	@Override
	public void weatherUpdated(String weatherDescription)
	{
		this.weatherDescription = weatherDescription;
		
		// Do something...
	}

	@Override
	public void randomAction(RandomObject randomObject)
	{
		// Do something...
	}
}

Nothing fancy here, the WeatherScreen class listens for weather updates and possibly information from other services. One can easily see how it’s possible for these publisher/listener connections to result in a lot of unnecessary coupling and boilerplate code.

If we take the same example and use the Otto event bus to manage a lot of these connections, we end up with something like the following:

OttoWeatherService Class

public class OttoWeatherService
{
	private String weatherDescription;
	private Bus eventBus;
	
	public OttoWeatherService(Bus eventBus)
	{
		this.eventBus = eventBus;
		eventBus.register(this);
	}
	
	public void weatherHasBeenUpdatedFromSomewhere(String weatherDescription)
	{
		this.weatherDescription = weatherDescription;
		
		// post the updated weather on the event bus.
		eventBus.post(weatherDescription);
	}
	
	@Produce
	public String produceWeatherUpdate()
	{
		return weatherDescription;
	}
}

When the OttoWeatherService class receives an update, it posts an event on the bus to notify all subscribers. Note that the service class now has less responsibility as it no longer needs to be concerned with a list of listeners and is immediately decoupled from the interface. Also note that this class is a Producer, meaning that as soon as an interested subscriber registers on the bus it will receive the latest update.

OttoWeatherScreen Class

public class OttoWeatherScreen
{
	private String weatherDescription;
	private Bus eventBus;
	
	public OttoWeatherScreen(Bus eventBus)
	{
		this.eventBus = eventBus;
		eventBus.register(this);
	}
	
	@Subscribe
	public void weatherAvailable(String weatherDescription)
	{
		this.weatherDescription = weatherDescription;
		
		// Do something...
	}
	
	@Subscribe
	public void randomObjectAvailable(RandomObject randomObject)
	{
		// Do something...
	}
}

The WeatherScreen class now receives updates from the various services by subscribing for these updates/events on the bus. Otto results in less classes having to be created and less code concerned with connecting your components up, allowing the existing classes to focus on performing core functions.

The above was just one example of how Otto can reduce the complexity surrounding communications/connections in your application. Coupling is reduced but strongly typed event production/subscription is still maintained.
 
I’ve created an OttoSample Android project on GitHub that provides a simple demonstration of how the Otto event bus can be used to communicate an object between two fragments. Please note that this project also makes use of the Android Annotations framework for object/view dependency injection; I plan to discuss and provide feedback on this framework in the near future.