Archive for April, 2011

How To Check For Various Types Of Android Devices

This note explains how to get started with testing your Android app’s handling of the various types of hardware on Android phones and devices, like a touch screen, a directional pad (dpad), camera, etc.

Chances are good that you only have one, maybe two phones. What do you do to check that your app works on all the various types of phones and devices? Use the Android emulator, which allows you to set up different device configurations for testing.

Steps

First use the Android AVD Manager to set up a variety of devices with different hardware configurations. If you are not familiar with the AVD Manager, read the overview page and the hardware options section.

For my current Android work, my AVD Manager looks like the following. Figure 1 shows a list of six devices. Figure 2 shows one that has a dpad (directional pad) but no touch screen. Figure 3 is for a device without touch and without a dpad.

AVD Manager shows different examples

Figure 1 – AVD Manager

Figure 2 – Device with dpad and no touch

Device with no dpad, no touch

Figure 3 – Device with no dpad and no touch

Once you have your devices ready, it’s time to work on your code. Somewhere in your Activity class, probably in your onCreate method, you’ll need lines like the ones below. To understand this, you should read the javadoc for the Configuration class.

    Resources r = getResources ();
    Configuration config = r.getConfiguration ();
    int navHidden = config.navigationHidden;
    int configValue = navHidden;
    boolean hasTouch = (config.touchscreen == Configuration.TOUCHSCREEN_FINGER)
                       || (config.touchscreen == Configuration.TOUCHSCREEN_STYLUS);
    setHasTouchScreen (hasTouch);
    if (!hasTouch) toast ("To make a move, use keyboard or direction pad (dpad)"
                          +" to select a square. Then click Enter.", true);
    else toast ("To make a move, touch a square. "
                + "Then touch the Make Move button.", true);

I put this in my Activity’s onCreate method. That allows me to know what kind of device I have before I choose the layout and views for the activity.

For this code, which is for a simple game, I use toast to explain how to make a move.

My toast method:

public void toast (String msg, boolean longLength) {
    Toast.makeText (getApplicationContext(), msg,
                    (longLength ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT)).show ();
}

For a real application, you would want to do better than this, perhaps by providing a screen that explains how to use your app. The good thing is that you can customize the instructions for the specific device the user has.

References

For more on this topic, read the following:

Long Computations in the Main Android Thread

In an Android application, you should work very hard to keep your application responsive to user actions (clicks, touches, scrolling, etc.).  That means not doing time-consuming operations like database queries or long computations in the main thread in which an activity runs.

Here are some good references for understanding this topic:

  • Painless Threading
    This is a good article on the Android Developers website. It covers the basic concepts for good user interface performance.  It is a great place to start.
  • Designing for Responsiveness
    Another article from Android Developers website. The key point for me: “any method that runs in the main thread should do as little work as possible.”
  • Intro to Loopers and Handlers
    This is an excellent explanation of Looper and Handler classes, which are classes that you use when you move tasks out of the user interface thread. The author explains a pattern that he calls the “Pipeline Thread”.

Five Simple Steps

1. Set up your activity so other threads can send messages to update user interface elements. Change the activity so it implements the android.os.Handler callback interface.

public class MyActivity extends Activity
implements Handler.Callback

2. Add an instance variable in your activity to hold a Handler. Then add the following to your activity’s onCreate method.

// Create a handler so other threads can  communicate with this one,
//  which is where UI operations take place.
mHandler = new Handler (this);

3. Implement the Handler.Callback method. This will be the place where you update views and widgets to keep the user informed of progress.

public boolean handleMessage (Message msg)

4. Take expensive operations and start them in a thread. For example, in an onClick method, add the following code:

new Thread(new Runnable() {
public void run() {
…  // something time-consuming
}  }).start();

Somewhere in the code that runs inside that thread, arrange to send a message back to the main activity. The message should convey something about the status of the ongoing operation. Exactly what that is depends on your application.

Message msg = Message.obtain (mHandler, what, arg1, arg2);
mHandler.sendMessage (msg);

5. Back in your activity, make sure that the message receiver is ready to handle the different kinds of messages that get sent. The “what” argument can be used to indicate the type of message. Something like:

public boolean handleMessage (Message msg) {
int kind = msg.what;
int arg1 = msg.arg1;
int arg2 = msg.arg2;
// update user interface views

};

I was surprised how easy it was to do this. A bit of research on the topic and about an hour editing and debugging was all it took.



Follow

Get every new post delivered to your Inbox.

Join 73 other followers