Saving the Android WebView cache on the SD card

Android Published on January 27, 2012 by Andrea Bresolin No Comments »
Source code

It could be useful to save the cache of an Android WebView on the SD card (or integrated external memory) especially for devices with a limited amount of internal memory, but how can you do that? Well, it’s simple. You know that some Android browsers already do it and here I’m going to tell you a way to do it in your own app as well. This solution is made to work with Android 2.1 and higher, so I’m not going to use the API that was introduced only in a later version of the OS.

The key is the getCacheDir method of the ContextWrapper class. This is what is used by the cache manager to decide where to store the cache files. The behavior is slightly different for Android 2.1 and Android 2.2 and higher, so we’ll also keep this in mind.

I’ll explain everything going through the source code of the example application that you can download through the link on top of this post. Let’s start with the mainfest file:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.devahead.androidwebviewcacheonsd"
	android:versionCode="1"
	android:versionName="1.0">

	<uses-sdk android:minSdkVersion="7"/>

	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
	<uses-permission android:name="android.permission.INTERNET"/>
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

	<application
		android:icon="@drawable/ic_launcher"
		android:label="@string/app_name"
		android:name="com.devahead.androidwebviewcacheonsd.ApplicationExt">
		<activity
			android:name=".MainActivity"
			android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN"/>
				<category android:name="android.intent.category.LAUNCHER"/>
			</intent-filter>
		</activity>
		<activity
			android:name=".SecondActivity"
			android:label="Second activity"/>
	</application>

</manifest>

Here we have the permissions to write to the SD (the external storage) and access the web. We also have a custom Application class extension called ApplicationExt and a couple of activities, MainActivity and SecondActivity.

The ApplicationExt class is where most of the things are done to have the cache on the SD:

package com.devahead.androidwebviewcacheonsd;

import java.io.File;

import android.app.Application;
import android.os.Environment;

public class ApplicationExt extends Application
{
	// NOTE: the content of this path will be deleted
	//       when the application is uninstalled (Android 2.2 and higher)
	protected File extStorageAppBasePath;

	protected File extStorageAppCachePath;

	@Override
	public void onCreate()
	{
		super.onCreate();

		// Check if the external storage is writeable
		if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
		{
			// Retrieve the base path for the application in the external storage
			File externalStorageDir = Environment.getExternalStorageDirectory();

			if (externalStorageDir != null)
			{
				// {SD_PATH}/Android/data/com.devahead.androidwebviewcacheonsd
				extStorageAppBasePath = new File(externalStorageDir.getAbsolutePath() +
					File.separator + "Android" + File.separator + "data" +
					File.separator + getPackageName());
			}

			if (extStorageAppBasePath != null)
			{
				// {SD_PATH}/Android/data/com.devahead.androidwebviewcacheonsd/cache
				extStorageAppCachePath = new File(extStorageAppBasePath.getAbsolutePath() +
					File.separator + "cache");

				boolean isCachePathAvailable = true;

				if (!extStorageAppCachePath.exists())
				{
					// Create the cache path on the external storage
					isCachePathAvailable = extStorageAppCachePath.mkdirs();
				}

				if (!isCachePathAvailable)
				{
					// Unable to create the cache path
					extStorageAppCachePath = null;
				}
			}
		}
	}

	@Override
	public File getCacheDir()
	{
		// NOTE: this method is used in Android 2.2 and higher

		if (extStorageAppCachePath != null)
		{
			// Use the external storage for the cache
			return extStorageAppCachePath;
		}
		else
		{
			// /data/data/com.devahead.androidwebviewcacheonsd/cache
			return super.getCacheDir();
		}
	}
}

In the onCreate method we start by checking if the external storage is actually mounted and we can write on it, then we build the base path of the app on the external storage. This path is {SD_PATH}/Android/data/com.devahead.androidwebviewcacheonsd because com.devahead.androidwebviewcacheonsd is the package declared in the manifest file and using this path structure makes sure that the entire path and all its content will be automatically deleted by Android 2.2 and higher in case the app is uninstalled avoiding to have garbage files on the SD. Note that this works only in Android 2.2 and higher, while in Android 2.1 the path will not be deleted by the OS so you’ll have to deal with it on your own. The full path for the cache files will be {SD_PATH}/Android/data/com.devahead.androidwebviewcacheonsd/cache, so the base path plus the cache directory. We must also make sure that the path is actually available before using it, so we create all the directories with the mkdirs method in case they don’t already exist.

Now that we have the cache path on the SD, we’re ready to use it and all we have to do is override the getCacheDir method inside our ApplicationExt class. This method is invoked by the cache manager when the application is started so basically we’re saying that the cache will be stored on the SD if it’s available and writeable, while we use the default path in case we’re allowed to use only the internal memory. Android stores all the cache data for our app in the /data/data/com.devahead.androidwebviewcacheonsd/cache directory by default on the internal memory.

We’re done with the implementation for Android 2.2 and higher, but what about Android 2.1? For that version of the OS the cache manager doesn’t use the getCacheDir method of the Application context, but it uses the one of the Activity context instead. So to make our solution work also with Android 2.1, we must override the getCacheDir method inside our activities.

To immediately understand how it works with Android 2.1, let’s take a look at the activities of the example application. We start with the MainActivity: Read the rest of this entry »

Preserving the state of an Android WebView on screen orientation change

Android Published on January 22, 2012 by Andrea Bresolin No Comments »
Source code

If you’ve tried to use a WebView inside your app, you know that the standard behavior on screen orientation change is not satisfactory in most cases because the full state of the WebView is not preserved. Here I’m going to show you a possible implementation to keep the full state of the WebView every time you rotate the screen. This is the same implementation I used in my own app (FWebLauncher) for the internal web browser.

Standard implementation (the state is not completely preserved)

Let’s start by taking a look at what a standard implementation would look like. This is how you would usually implement the state saving for a WebView according to the Android documentation:

public class StandardImplActivity extends Activity
{
	protected WebView webView;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.standard_impl);

		// Retrieve UI elements
		webView = ((WebView)findViewById(R.id.webView));

		// Initialize the WebView
		webView.getSettings().setSupportZoom(true);
		webView.getSettings().setBuiltInZoomControls(true);
		webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
		webView.setScrollbarFadingEnabled(true);
		webView.getSettings().setLoadsImagesAutomatically(true);

		// Load the URLs inside the WebView, not in the external web browser
		webView.setWebViewClient(new WebViewClient());

		if (savedInstanceState == null)
		{
			// Load a page
			webView.loadUrl("http://www.google.com");
		}
	}

	@Override
	protected void onSaveInstanceState(Bundle outState)
	{
		super.onSaveInstanceState(outState);

		// Save the state of the WebView
		webView.saveState(outState);
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState)
	{
		super.onRestoreInstanceState(savedInstanceState);

		// Restore the state of the WebView
		webView.restoreState(savedInstanceState);
	}
}

So we call the saveState and the restoreState methods in the onSaveInstanceState and the onRestoreInstanceState methods of the Activity.

The WebView is declared directly in the layout file for the activity:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">

	<WebView android:id="@+id/webView"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"/>

</LinearLayout>

The main problem with this implementation is that, whenever you rotate the screen, the WebView is created again because the activity is destroyed and its saveState method doesn’t save the full state, but only a part of it like the URL of the page that was loaded and the browsing history. So it happens that for example the zoom and the scroll position are not preserved after the screen orientation change and sometimes the page is reloaded from the web.

State preserving implementation (a possible solution)

I tried many different solutions to preserve the full state of the WebView on screen rotation and the following one proved to be a reliable one that solves our problem. The main point is that the activity must not be destroyed and we must handle the screen orientation change by ourselves. Let’s start by taking a look at the layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">

	<FrameLayout android:id="@+id/webViewPlaceholder"
		android:layout_width="fill_parent"
		android:layout_height="fill_parent"/>

</LinearLayout>

You immediately notice the difference with the standard implementation. Here we don’t declare the WebView inside the layout file, but we declare a placeholder instead. It is the position where our WebView will be placed inside the activity.

Also the code inside the activity will be different of course and here it is: Read the rest of this entry »

Recycling objects in Android with an Object Pool to avoid garbage collection

Android Published on December 18, 2011 by Andrea Bresolin 1 Comment »
Source code (LICENSE)

If you need to reduce the work of the garbage collector in Android, like in games development for example, all you can do is reduce the amount of objects you create and recycle those you’ve already created. One of the ways to do this is the implementation of the Object Pool design pattern.

An Object Pool could be implemented in many different ways depending on the needed features. What I’m going to show here is an implementation that respects the following requirements:

  • during its execution, the Object Pool doesn’t allocate new objects other than those contained in the pool itself (we prefer plain arrays instead of Java collections);
  • the Object Pool must be efficient in terms of execution speed;
  • the Object Pool is responsible for initializing and finalizing the objects it contains (the objects must be ready to use when retrieved from the pool and they must free any unneeded resource when they are put back in the pool);
  • if there’s no more room for new objects in the pool, then new objects must be created anyway if requested, but they’ll not be stored in the pool when freed;
  • the Object Pool must be able to handle every type of Object (we only ask the objects to implement an interface to make them ready for the pool);
  • sharing the pool between multiple threads doesn’t have to be a problem.

And now, straight to the source code. We start with the definition of the PoolObject interface:

/**
 * Interface that has to be implemented by an object that can be
 * stored in an object pool through the ObjectPool class.
 */
public interface PoolObject
{
	/**
	 * Initialization method. Called when an object is retrieved
	 * from the object pool or has just been created.
	 */
	public void initializePoolObject();

	/**
	 * Finalization method. Called when an object is stored in
	 * the object pool to mark it as free.
	 */
	public void finalizePoolObject();
}

This is the interface that an object must implement to let the pool perform two operations: the initialization and the finalization. We use an interface so we can easily extend every other class and make the pool able to handle different objects.

The Object Pool creates the needed objects through a factory class that implements the PoolObjectFactory interface:

/**
 * Interface that has to be implemented by every class that allows
 * the creation of objectes for an object pool through the
 * ObjectPool class.
 */
public interface PoolObjectFactory
{
	/**
	 * Creates a new object for the object pool.
	 *
	 * @return new object instance for the object pool
	 */
	public PoolObject createPoolObject();
}

The factory class must decide how to create a new PoolObject instance whenever the pool needs it.

All we need to see now is the ObjectPool class, so let’s take a look at it:

/**
 * Object pool implementation.
 */
public class ObjectPool
{
	protected final int MAX_FREE_OBJECT_INDEX;

	protected PoolObjectFactory factory;
	protected PoolObject[] freeObjects;
	protected int freeObjectIndex = -1;

	/**
	 * Constructor.
	 *
	 * @param factory the object pool factory instance
	 * @param maxSize the maximun number of instances stored in the pool
	 */
	public ObjectPool(PoolObjectFactory factory, int maxSize)
	{
		this.factory = factory;
		this.freeObjects = new PoolObject[maxSize];
		MAX_FREE_OBJECT_INDEX = maxSize - 1;
	}

	/**
	 * Creates a new object or returns a free object from the pool.
	 *
	 * @return a PoolObject instance already initialized
	 */
	public synchronized PoolObject newObject()
	{
		PoolObject obj = null;

		if (freeObjectIndex == -1)
		{
			// There are no free objects so I just
			// create a new object that is not in the pool.
			obj = factory.createPoolObject();
		}
		else
		{
			// Get an object from the pool
			obj = freeObjects[freeObjectIndex];

			freeObjectIndex--;
		}

		// Initialize the object
		obj.initializePoolObject();

		return obj;
	}

	/**
	 * Stores an object instance in the pool to make it available for a subsequent
	 * call to newObject() (the object is considered free).
	 *
	 * @param obj the object to store in the pool and that will be finalized
	 */
	public synchronized void freeObject(PoolObject obj)
	{
		if (obj != null)
		{
			// Finalize the object
			obj.finalizePoolObject();

			// I can put an object in the pool only if there is still room for it
			if (freeObjectIndex < MAX_FREE_OBJECT_INDEX)
			{
				freeObjectIndex++;

				// Put the object in the pool
				freeObjects[freeObjectIndex] = obj;
			}
		}
	}
}

The structure of this class is very simple. There are only three methods, the constructor and two other methods to create and free the object instances.

The constructor accepts two parameters, the factory instance and the maximum number of objects that can be stored in the pool.

The newObject method retrieves an object from the pool and returns it to the caller after initializing it. If there are free objects in the pool, then one of those is returned, otherwise a new one is created through the factory. In this way we put a limit on the maximum number of instances in the pool, but only the needed amount is actually created.

The freeObject method puts an object instance back in the pool making it available for subsequent calls to newObject. Before storing the object in the free objects array, its finalization method is called to let it free any unneeded resource if necessary. If there’s no room in the pool for the object, then only its finalization method is called.

Both the newObject and the freeObject methods are synchronized so the interaction between the pool and different threads is managed correctly.

We have all we need, so let’s take a look at an example to see how our new tool can be used and what is its benefit. Let’s say that we need to work with Point instances for a graphic application. We need to have many points, but we want to avoid to keep on creating them and try to reuse the instances if possible. We need to define a PoolObject first: Read the rest of this entry »

Coding for performance and avoiding garbage collection in Android

Android Published on December 11, 2011 by Andrea Bresolin No Comments »
Source code (LICENSE)

Post updates:

  • [December 18th, 2011] added TEST 10: OBJECT POOL

You know how much important it is to always keep in mind the performance of your application when developing for mobile devices with limited resources. This is important especially for game developers that need to reach two goals:

  • write high performance code
  • avoid having the garbage collector work too much because it might have a negative impact on the user experience (you don’t want the users to see small pauses while playing a game)

In this post I’m going to show some tests I made for the Android platform. You can repeat the same tests on your own downloading the test app source code through the link on top of this post.

Here is my test environment:

  • Samsung Galaxy S II
  • Android 2.3.3 (Gingerbread)
  • Airplane mode on (to avoid network connections that could affect the test results)

NOTES:

  • these tests are not meant to be a 100% exact measure of performance differences between different solutions, they are made to show and verify what could be the best implementation choice depending on the context and they give only a rough measure of the difference in performance (specific to the test cases); the final conclusion is still true for similar implementation cases so a faster implementation is always faster, maybe not as much faster as shown in a test case, but still faster;
  • these tests are made for the Android platform, so a common good practice for a Java virtual machine might not be valid for the Dalvik virtual machine.

The structure of this post is simple. A series of tests will be described giving information about what is the best choice for a software developer and why. Are you ready? Let’s go!

TEST 1: FOR LOOP OVER ARRAY

When writing a for loop over arrays, the common way of implementing it is use the length property of the array in the termination condition. But instead of asking the array its length on every single iteration of the loop, we could just read it before entering the loop and cache it in a local variable.

What we test: is there a difference between using a local variable to cache the length of an array instead of using the length property in a termination condition of a for loop?

Standard implementation

// arr is an int[] array

for (int i = 0; i < arr.length; i++)
{
	// Do something
}

Optimized implementation

// arr is an int[] array

int arrLength = arr.length;

for (int i = 0; i < arrLength; i++)
{
	// Do something
}

Test results

The results show the average time taken to loop over an array with length = 3000000. The loop is repeated 100 times to check the average time taken for each complete loop.

  Average loop time Result
Standard 58 ms  
Optimized 43 ms 26% faster than standard

Conclusion

Caching the array length in a local variable is faster than reading the value for every single loop iteration. If you know that the length of an array will never change during the loop execution, then caching its value is a good idea to improve the execution speed.

TEST 2: FOR LOOP OVER ARRAYLIST

Like TEST 1, when writing a for loop over ArrayList, the common way of implementing it is use the size method of the ArrayList in the termination condition. But instead of asking the ArrayList its size on every single iteration of the loop, we could just read it before entering the loop and cache it in a local variable.

What we test: is there a difference between using a local variable to cache the size of an ArrayList instead of using the size method in a termination condition of a for loop?

Standard implementation

// arr is an ArrayList<Object>

for (int i = 0; i < arr.size(); i++)
{
	// Do something
}

Optimized implementation

// arr is an ArrayList<Object>

int arrLength = arr.size();

for (int i = 0; i < arrLength; i++)
{
	// Do something
}

Test results

The results show the average time taken to loop over an ArrayList with size = 3000000. The loop is repeated 100 times to check the average time taken for each complete loop.

  Average loop time Result
Standard 262 ms  
Optimized 233 ms 11% faster than standard

Conclusion

Caching the ArrayList size in a local variable is faster than reading the value for every single loop iteration. If you know that the size of an ArrayList will never change during the loop execution, then caching its value is a good idea to improve the execution speed. An ArrayList is generally slower than a simple array because of the method invocations involved in reading and writing values from and to the collection. Different collections have different performances (think about the access time to the elements of a HashMap), so different tests are necessary to test them. Read the rest of this entry »

Creating a custom Android button with a resizable skin

Android Published on August 2, 2011 by Andrea Bresolin No Comments »
Source code

If you are developing your own Android application, maybe you would like to give it a custom skin with a defined set of colors for all the interface elements. Here I’m going to show how to customize Android buttons. This is the same kind of customization I made for my own app which is called FWebLauncher and you can download for free from the Android Market. In this post I’m going to quickly describe the steps that have to be performed to obtain our result, but I recommend you to download the whole example application with all the resource images through the link on top of this post.

First of all, you need to decide how your buttons will look in different states, so you’ve got to define the corresponding skin images for the Normal, Pressed, Focused and Disabled states. Of course, if you don’t need all the states, you can just define some of them. In the following image you can see how our buttons will look like:

We want the skin to be resizable, so the button can adapt its size depending on the content (i.e. the text) without making the skin look weird. To do this, we need to define a 9-patch for each image. There’s a tool installed with the Android SDK that you can find in ${ANDROID_SDK_INSTALL_DIRECTORY}\tools\draw9patch.bat. Execute that batch file and you’ll have the following application running:

As you can see I’ve already loaded the PNG file for the Normal state of our buttons and I’ve defined the 9-patch with the black lines that you can see on every side of the image. As written in the Android developer’s documentation, the top and left lines define the stretchable area used to resize the image, while the bottom and right lines define the area where the content must be placed. With the 9-patch tool, I created a new file for each image of the button skin, so for example, if the skin image for the Normal state of the button is called button_normal.png, then the corresponding 9-patch file will be button_normal.9.png and we need only this inside the resources folders of our application.

The next thing to do is creating a selector that tells Android how it should deal with the skin images depending on the button state. The selector is just an XML file that looks like this:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<item android:drawable="@drawable/button_disabled" android:state_enabled="false"/>
	<item android:drawable="@drawable/button_pressed" android:state_pressed="true"/>
	<item android:drawable="@drawable/button_focused" android:state_focused="true"/>
	<item android:drawable="@drawable/button_normal"/>
</selector>

In the selector you define which skin image should be used to render each button state. So if the selector XML file is called button.xml, you can just write something like this to have your button skin working:

<Button android:id="@+id/textBtn"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="Text in the button"
	android:background="@drawable/button"
	android:textColor="#ffffffff"/>

This is just a simple button with some text in it. In case you need a button with an image, like an icon, and you want it to resize proportionally, then you don’t need to define a 9-patch and you need to use something different like an ImageButton: Read the rest of this entry »

Using the standard Android icons in your own application

Android Published on July 18, 2011 by Andrea Bresolin No Comments »
Source code

When you make your own Android application, you usually put also your own graphic elements in it like custom icons and images, but it’s still a good idea to keep the standard Android icons for common user interactions. This helps the user to immediately understand the meaning of the options inside your application and it gives a familiar environment that is consistent with the Android platform. So, how do you get the standard Android icons? How do you deal with different Android versions (the style of the icons might change)?

There are two different options to accomplish this task:

  1. reference the icons with android.R.drawable;
  2. copy the standard Android icons from the SDK to your own application’s resources folder.

OPTION 1 – The good points about this option is that you automatically have the correct resource for the platform version where your application is running and the size of the application package doesn’t become higher in case you’re using more standard Android icons. This looks like the perfect solution, so why look for another one? Well, not all the icons are defined in android.R.drawable so you are forced to copy them locally in case you can’t find them in the class. Another bad point is what is explicitly stated in the guidelines documents for the menu icons and the status bar icons:

Warning: Because these resources can change between platform versions, you should not reference these icons using the Android platform resource IDs (i.e. status bar icons under android.R.drawable). If you want to use any icons or other internal drawable resources, you should store a local copy of those icons or drawables in your application resources, then reference the local copy from your application code. In that way, you can maintain control over the appearance of your icons, even if the system’s copy changes.”

OPTION 2 – You can find all the standard Android icons in your SDK local installation following the path ${ANDROID_SDK_INSTALL_DIRECTORY}\platforms\android-${PLATFORM_VERSION}\data\res, so let’s say that you installed the SDK under C:\AndroidSDK and you want the resources for the version 7 of the Android platform (i.e. Android 2.1), you can find everything under C:\AndroidSDK\platforms\android-7\data\res. You can copy for example the hdpi version of the icons from C:\AndroidSDK\platforms\android-7\data\res\drawable-hdpi. Following this approach, you need to copy the icons for different versions of the Android platform in case their style changed between one version and another. This is what happened for example for the menu and status bar icons, since Android 2.3 (platform version 9) the style changed, so you need a copy of the standard icons for Android 2.3 and higher and for Android 2.2 and lower. To do this, in your own application you need two different folders (this example refers to the hdpi icons):

/res/drawable-hdpi (for Android 2.2 and lower)
/res/drawable-hdpi-v9 (for Android 2.3 and higher)

Now let’s see a simple example application that uses the standard icons getting them in both ways. Here is the layout of the main activity: Read the rest of this entry »

Creating an Android dialog and maintaining its state on screen orientation change

Android Published on July 11, 2011 by Andrea Bresolin No Comments »
Source code

You want to create a custom dialog in Android, but you also want to maintain its state on screen orientation change when it’s already open and the Android device is rotated. How do you do that? If you use the standard methods that Android provides inside activities, it’s straightforward. Here I’m going to show how to create a completely custom dialog with its own custom layout and interface elements.

Let’s start with the basics. What do you need inside your Android activity?

  • implement the onCreateDialog method;
  • implement the onPrepareDialog method;
  • keep a constant with the custom dialog ID;
  • call the showDialog method to display the dialog;
  • call the removeDialog or dismissDialog methods to remove the dialog from the screen.

And now straight to the source code with an example application. The layout of our custom dialog will look like this (custom_dialog.xml resource file):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:orientation="vertical">

	<ScrollView
		android:layout_width="fill_parent"
		android:layout_height="wrap_content">

		<LinearLayout
		  android:layout_width="fill_parent"
		  android:layout_height="wrap_content"
		  android:orientation="vertical"
		  android:paddingLeft="3dip"
		  android:paddingRight="3dip">

			<TextView
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:text="Field 1:"
				android:layout_gravity="left"
				android:textColor="@android:color/primary_text_dark"/>

			<EditText android:id="@+id/cdField1Edit"
				android:layout_width="fill_parent"
				android:layout_height="wrap_content"
				android:gravity="left"/>

			<TextView
				android:layout_width="wrap_content"
				android:layout_height="wrap_content"
				android:text="Field 2:"
				android:layout_gravity="left"
				android:layout_marginTop="10dip"
				android:textColor="@android:color/primary_text_dark"/>

			<EditText android:id="@+id/cdField2Edit"
				android:layout_width="fill_parent"
				android:layout_height="wrap_content"
				android:gravity="left"/>

		</LinearLayout>

	</ScrollView>

	<LinearLayout
	  android:layout_width="fill_parent"
	  android:layout_height="wrap_content"
	  android:orientation="horizontal"
	  android:layout_gravity="center_horizontal">

		<Button android:id="@+id/cdOKBtn"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:layout_weight="1"
			android:text="OK"
			android:layout_gravity="center_vertical"/>

		<Button android:id="@+id/cdCancelBtn"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:layout_weight="1"
			android:text="Cancel"
			android:layout_gravity="center_vertical"/>

	</LinearLayout>

</LinearLayout>

We simply have two text fields (cdField1Edit and cdField2Edit) and two buttons to confirm our input (cdOKBtn) or to cancel the dialog (cdCancelBtn).

Inside the main activity we can set a default value for cdField2Edit in the dialog (through cdField2DefValEdit) and we have a button to display the dialog (showCDBtn):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:orientation="vertical"
	android:layout_width="fill_parent"
	android:layout_height="fill_parent">

	<LinearLayout
	  android:layout_width="fill_parent"
	  android:layout_height="wrap_content"
	  android:orientation="horizontal"
	  android:paddingLeft="3dip"
	  android:paddingRight="3dip">

		<TextView
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="Field 2 default value:"/>

		<EditText android:id="@+id/cdField2DefValEdit"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:layout_marginLeft="10dip"/>

	</LinearLayout>

	<Button android:id="@+id/showCDBtn"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Show Custom Dialog 1"
		android:layout_marginTop="20dip"/>

</LinearLayout>

The MainActivity class is the place where we’re going to implement the logic to manage the creation and intialization of our custom dialog: Read the rest of this entry »

Extending the Android Application class and dealing with Singleton

Android Published on June 19, 2011 by Andrea Bresolin 2 Comments »
Source code

In this post I’m going to show the basic steps to extend the Android Application class and I’m also going to talk about why it could be useful to extend it in dealing with the Singleton design pattern.

The first thing to do is to create a MyApplication class that extends android.app.Application.

package com.devahead.extendingandroidapplication;

import android.app.Application;

public class MyApplication extends Application
{
	@Override
	public void onCreate()
	{
		super.onCreate();

		// Initialize the singletons so their instances
		// are bound to the application process.
		initSingletons();
	}

	protected void initSingletons()
	{
		// Initialize the instance of MySingleton
		MySingleton.initInstance();
	}

	public void customAppMethod()
	{
		// Custom application method
	}
}

In this class you can, for example, override the onCreate method to perform your initializations at the application startup and you can also implement your own methods to make them available to the rest of your application components. As you can see here we initialize also the singletons in case there are some in our application. I’ll talk later about why I do this here, but now let’s go on with the custom Application class.

The next thing we need to do is to open the AndroidManifest.xml file of our application and add a reference to MyApplication in the android:name attribute of the application tag, so in the end the manifest file will look similar to this one:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="com.devahead.extendingandroidapplication"
	android:versionCode="1"
	android:versionName="1.0">

	<uses-sdk android:minSdkVersion="7"/>

	<application android:icon="@drawable/icon" android:label="@string/app_name"
		android:name="com.devahead.extendingandroidapplication.MyApplication">

		<activity android:name=".MainActivity"
			android:label="@string/app_name">
			<intent-filter>
				<action android:name="android.intent.action.MAIN"/>
				<category android:name="android.intent.category.LAUNCHER"/>
			</intent-filter>
		</activity>

	</application>
</manifest>

That’s it. We now have a custom Application class that can be used to suit our needs. We can access to it from any Activity through the getApplication method (the same getApplication method is available also in a Service).

package com.devahead.extendingandroidapplication;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity
{
	protected MyApplication app;

	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		// Get the application instance
		app = (MyApplication)getApplication();

		// Call a custom application method
		app.customAppMethod();

		// Call a custom method in MySingleton
		MySingleton.getInstance().customSingletonMethod();

		// Read the value of a variable in MySingleton
		String singletonVar = MySingleton.getInstance().customVar;
	}
}

As you can see there are references to the MySingleton class also here as an example like there were in the MyApplication class, but we haven’t seen the singleton yet, so here it is:

package com.devahead.extendingandroidapplication;

public class MySingleton
{
	private static MySingleton instance;

	public String customVar;

	public static void initInstance()
	{
		if (instance == null)
		{
			// Create the instance
			instance = new MySingleton();
		}
	}

	public static MySingleton getInstance()
	{
		// Return the instance
		return instance;
	}

	private MySingleton()
	{
		// Constructor hidden because this is a singleton
	}

	public void customSingletonMethod()
	{
		// Custom method
	}
}

The initInstance method lets the internal instance be initialized only once and this is done in the MyApplication class as we saw earlier. The getInstance method allows to access the instance from every part of our application and the MySingleton constructor is kept private because we don’t want to allow the creation of multiple instances. Read the rest of this entry »

Flex exceptions are suppressed in MXML data binding expressions

Flex Published on September 15, 2010 by Andrea Bresolin No Comments »
Live demoSource code (LICENSE)

While using data binding expressions inside MXML tags, you may have noticed that sometimes there seem to be strange behaviors during expressions evaluation, for example it could happen that an expression is not updated like you expect it to be when a value of a bindable variable changes. Whenever someone new to Flex starts to work with it, I noticed that sooner or later he asks me always the same question: "Why is the value of that label not being updated? I think that my expression is correct…" I had the same problem too at the beginning, because it’s not something obvious, but it’s important to keep a rule in mind.

This is the thing to know: exceptions are suppressed in MXML data binding expressions! And it’s very important to keep in mind this rule: every data binding expression must be written in a way that avoids exceptions, considering all the possible values that each variable in the expression can get.

The reason why an expression sometimes is not evaluated is usually the fact that there has been an exception during the evaluation. In this case using some if statements in the expression generally solves the problem. Let’s take a look at an example application to show what we’re talking about.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	pageTitle="Flex exceptions are suppressed in MXML data binding expressions - devahead BLOG"
	layout="vertical" horizontalAlign="left"
	viewSourceURL="srcview/index.html">

	<mx:Script>
		<![CDATA[
			[Bindable]
			protected var myVar1: String = "a string";

			[Bindable]
			protected var myVar2: String = "i = 0";

			[Bindable]
			protected var i: int = 0;

			protected function testFunc(value: String): String
			{
				value = value.toUpperCase(); // Exception if value == null

				i++;

				myVar2 = "i = " + i;

				return value;
			}
		]]>
	</mx:Script>

	<mx:Label text="{'(WITH EXCEPTION) The value of myVar1 is: ' +
		myVar1.toUpperCase()}"/>

	<mx:Label text="{'(WITH EXCEPTION FROM FUNCTION) The value of myVar1 is: ' +
		testFunc(myVar1)}"/>

	<mx:Label text="{'(WITHOUT EXCEPTION) The value of myVar1 is: ' +
		(myVar1 != null ? myVar1.toUpperCase() : 'NULL')}"/>

	<mx:Label text="{'myVar2: ' + myVar2}"/>

	<mx:Spacer height="16"/>

	<mx:Label text="Test exception in MXML tag with data binding expression:"/>

	<mx:Button label="Set myVar1 = NULL" click="{myVar1 = null}"/>
	<mx:Button label="Set myVar1 = 'a string'" click="{myVar1 = 'a string'}"/>

</mx:Application>

In the application we use some data binding expressions inside curly braces. The value of myVar1 is displayed in three labels, but only in the last one there’s an if statement that actually checks if its value is null. Since in every expression we try to use the function toUpperCase on the variable, there is clearly an exception if the variable is null. If you try to set myVar1 = null clicking on the corresponding button, you’ll see that the only label that is correctly rendered is the one with the if statement, because it’s data binding expression avoids generating an exception. The function testFunc has the purpose of demonstrating that the value of i is never increased whenever there’s an exception in the first line of the function’s body and the exception is never thrown because it is suppressed automatically. If you keep on clicking on both the buttons, you’ll see that the value of i is increased only when there are no exceptions in testFunc, i.e. the value of myVar1 is not null.

So if you notice some strange behaviors in your data binding expressions evaluation, keep in mind what we’ve seen here, because you will never get a message telling you that there has been an exception, even with the debug version of the Flash Player.

Setter is not invoked when a bindable Flex property doesn’t change

Flex Published on May 15, 2010 by Andrea Bresolin 2 Comments »
Live demoSource code (LICENSE)

You’ve probably been using the Bindable metadata tag a lot of times with properties in your Flex applications. When a property is defined through getter and setter functions, you may take for granted that each time you set the value of the property, the corresponding setter is invoked, so you can perform your own operations in it. Well, this is not totally true with bindable properties. What I’m going to show is just something to remember whenever you use the Bindable metadata tag with properties defined through getter and setter. It is much easier to explain everything if we immediately look at the example application.

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
	pageTitle="Setter is not invoked when a bindable Flex property doesn\'t change - devahead BLOG"
	layout="vertical" horizontalAlign="left"
	viewSourceURL="srcview/index.html">

	<mx:Script>
		<![CDATA[
			private var _notBindableProp: String = "";

			public function get notBindableProp(): String
			{
				return _notBindableProp;
			}

			public function set notBindableProp(value: String): void
			{
				_notBindableProp = value;

				logValueChange("notBindableProp", _notBindableProp);
			}

			private var _bindableProp: String = "";

			[Bindable]
			public function get bindableProp(): String
			{
				return _bindableProp;
			}

			public function set bindableProp(value: String): void
			{
				_bindableProp = value;

				logValueChange("bindableProp", _bindableProp);
			}

			private var _bindableEventProp: String = "";

			[Bindable("bindableEventPropChanged")]
			public function get bindableEventProp(): String
			{
				return _bindableEventProp;
			}

			public function set bindableEventProp(value: String): void
			{
				_bindableEventProp = value;

				logValueChange("bindableEventProp", _bindableEventProp);

				dispatchEvent(new Event("bindableEventPropChanged"));
			}

			protected function logValueChange(propertyName: String, newValue: String): void
			{
				logArea.text += propertyName + " setter invoked: " + newValue + "\n";
			}
		]]>
	</mx:Script>

	<mx:Form>
		<mx:FormItem direction="horizontal"
			label="New value for the NOT BINDABLE property:">
			<mx:TextInput id="notBindablePropText" width="150"/>
			<mx:Button label="Set" click="{notBindableProp = notBindablePropText.text}"/>
		</mx:FormItem>

		<mx:FormItem direction="horizontal"
			label="New value for the BINDABLE property:">
			<mx:TextInput id="bindablePropText" width="150"/>
			<mx:Button label="Set" click="{bindableProp = bindablePropText.text}"/>
			<mx:Label text="{bindableProp}" fontWeight="bold"/>
		</mx:FormItem>

		<mx:FormItem direction="horizontal"
			label="New value for the BINDABLE property WITH CUSTOM EVENT:">
			<mx:TextInput id="bindableEventPropText" width="150"/>
			<mx:Button label="Set" click="{bindableEventProp = bindableEventPropText.text}"/>
			<mx:Label text="{bindableEventProp}" fontWeight="bold"/>
		</mx:FormItem>
	</mx:Form>

	<mx:Label text="Log:"/>

	<mx:TextArea id="logArea" width="400" height="300"/>

</mx:Application>

The property called notBindableProp is just a simple not bindable property. Whenever you set its value, the setter is invoked. bindableProp is a standard bindable property. If you try to set its value, you’ll quickly find out that the setter is invoked only if the new value is different from the value returned by the corresponding getter. So you cannot rely on doing something inside the setter when the new value is exactly the same as the previous one. What if you still want a bindable property, but you need to perform some operations in the setter every time a value is set, even if it’s equal to the previous one? You can simply define a custom event name in the Bindable metadata tag as you can see in the bindableEventProp. Every time a value is set for that property, the setter is invoked and you can perform your operations and then dispatch your own event.

WP Theme & Icons by N.Design Studio
©2009-2012 Andrea Bresolin. All rights reserved. - Privacy Policy
Entries RSS Comments RSS