Archive for the ‘Android’ Category

State Capitals is Now Free

After several weeks on the Android Market, my State Capitals application is now free. I made ten sales. Of those ten, two were returned and one person’s credit card didn’t work.

At $2.00 for each of the seven completed sales, my app grossed $14. Subtract 30% for T-Mobile, and I get $9.80. Since I paid $25 to join the market, I am $15.20 in the red.

This is mildly disappointing, but I didn’t really expect to get rich selling state capital flash cards. I suppose I could try reducing the price to $0.99, but this feels like a dead end. I’d rather focus on game programming…and thus begins my next wild-goose chase.

Android Bouncing Ball Demo

I just added a new demo to my Android Game Examples project. This sample reacts to the accelerometer to control a ball. As you rotate the screen, the ball falls towards the earth. When it bounces off the edge of the screen, the phone vibrator kicks in for a few milliseconds.


Android Bouncing Ball on G1 from Eric Burke on Vimeo.

I’m doing this to learn how to write games. The source code demonstrates a few things:

  • Using the phone’s accelerometer
  • Activating the phone’s vibrator
  • Simulating gravity and acceleration
  • Painting graphics using Android’s SurfaceView
  • Writing a super simple “game loop” that updates physics in a background thread safely

Android Accelerometer

If you follow me on Twitter (@burke_eric), you may have seen me commenting on accelerometer problems with my G1 phone. In the Labyrinth Lite game, the ball always pulls hard to the right, even after calibration. See this video:


Android G1 Accelerometer from Eric Burke on Vimeo.

I initially thought my phone was defective, because the same game works for other people. But another game, Papi Jump, works fine after calibration. Before calibration, that game also pulls hard to the right.

Accessing the Accelerometer

You access the accelerometer via the SensorManager:

public class Accel extends Activity implements SensorListener {
...
  SensorManager sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
  boolean accelSupported = sensorMgr.registerListener(this,
        SENSOR_ACCELEROMETER,
        SENSOR_DELAY_UI);
...
}

That boolean result is true if the device supports the requested sensor, so it returns false on the emulator and true on the G1 phone.

The SensorListener has two methods: onAccuracyChanged(...) and onSensorChanged(...). My example updates the GUI whenever the sensor changes.

Disclaimer: if you update the GUI on every single event, your application will slow down, the garbage collector will kick in repeatedly, and your app will probably crash. The events from the sensor arrive very fast, faster than the GUI can display. If you check out the complete code, you’ll see I intentionally slow down the GUI updates to once every 100 milliseconds.

Calibration

The screen shot illustrates the “problem” with my phone and the Labyrinth Lite game. The X, Y, and Z values constantly change. When the phone rests on a level surface, X and Y should be around zero. On my phone, however, X is approximately 0.83.

My application stores three values representing the calibration. When you click the Calibrate button, I store the negative X, Y, and Z values in three variables: cx, cy, and cz. Those are the numbers shown in parenthesis. When I display the values for X, Y, and Z, I simply add cx, cy, and cz to the current sensor readings.

Papi Jump and Labyrinth

The Papi Jump game seems to calibrate just fine. I suspect they do exactly what I do: detect how far out of whack the phone’s sensor is, and apply that delta to the current sensor readings.

For whatever reason, Labyrinth fails to calibrate enough on my phone. I believe this is a bug in their application. Perhaps the phones they test with do not require as much calibration as my phone. I have read reports from several people who say Labyrinth works on their phones, and it works on my wife’s G1 as well.

G1 Tolerance?

My phone sensor clearly works, it just requires around -0.83 X-axis adjustment. Is this within acceptable tolerance? I do not know.

I do know, however, that game developers cannot assume all Android hardware is perfectly calibrated. Games like Labyrinth need to expect a wider range of hardware and adjust accordingly. Papi Jump does it, and my simple demo is able to calibrate with a trivial subtraction.

Source Code

The complete source code is available in my Android Game Examples project on GitHub.

Android Sensors

Android devices like the G1 phone support different sensors. Tonight I wrote some code that reports which sensors your Android device supports. Unfortunately, the emulator supports none:

When I run this on my G1, the program reports true for these sensors:

  • Accelerometer
  • Magnetic Field
  • Orientation
  • Orientation Raw
  • Tricorder (not really)

Sample Code

First, grab the SensorManager:

SensorManager sensorMgr = (SensorManager)
    context.getSystemService(Context.SENSOR_SERVICE);

Next, get a list of supported sensors:

int sensorIds = sensorMgr.getSensors();

And finally, test if the device supports the sensor your application needs:

boolean deviceSupportsAccelerometer =
  (sensorIds & SENSOR_ACCELEROMETER) == SENSOR_ACCELEROMETER;

Note that SENSOR_ACCELEROMETER is a constant in the SensorManager class.

The Complete Example

My SensorListAdapter produces the screen shown above. The complete project is available on GitHub.

Last.fm for Android

While waiting for dinner earlier tonight, I installed Last.fm on my G1. I don’t have a Last.fm account, so I signed up for a new one. While waiting for a response from the server, the UI froze. This screen is never good:

Android programmers need to know this: Never make network calls on the main application thread.

2009 Android Wish List

What would you like to see Google (and others) do with Android in 2009? Here are some things I came up with.

  • Multitouch.
  • Bluetooth APIs.
  • Explicit support for unit testing, with clear examples and IDE support.
  • Step-by-step OpenGL tutorials, along the lines of the excellent Notepad tutorial.
  • A first rate IDEA plugin.
  • A damn good GUI builder.
  • Winchester hard disk drive support.
  • Longer G1 battery life
  • The ability to install apps on the SD card, and make it obvious how to put SQLite DBs on the SD card.
  • More standard actions and reusable activities. For example, make it easy to select pictures from the filesystem, crop photos, etc. These pieces are all there, but not always included as public APIs. Over time, I hope to see more reusable building blocks, making application development easier.
  • A pre-built JAR file containing all the SDK sources, so I can download a single JAR and drop it into my IDE.
  • Improved navigation on the Reference Information web site. There are a large number of examples, but the web site is hard to navigate. At a minimum, some kind of breadcrumbs would be nice. It’s really easy to get lost on the current site.
  • Never, ever release another phone without a standard headphone jack.
  • Improved contact management. My main gripe is when editing contacts, I get duplicate email address conflicts, with no smart merging of the duplicate entries.
  • ** Update: Flash support (see Michael’s comment below)

I suspect we’ll have most of these items sometime in 2009.

Android Article Draft

I finished a rough draft for an article on an Android threading technique. If you want to see the draft, or are interested in being a tech reviewer, here it is:

android.pdf – the article
android.zip – should be ready to go in Eclipse

Setting Up The Examples

  • Download and unzip android.zip
  • Make sure you have Eclipse with the Android SDK and plugin installed.
  • I zipped up my entire workspace and project, so I’m assuming you can simply open it up in Eclipse. I still need to try this on someone else’s computer to verify this works, I’m no Eclipse expert.
  • If you’ve never done anything with Android, this example is going to be challenging. You might want to go through the Notepad tutorial first.

Final publication is scheduled for Jan 2, so I’ll need any tech reviews a few days before that. Thanks!

OCI Java Lunch: Android

The first 30 minutes of my OCI Java Lunch presentation on Android is on YouTube. We had to split it up into 3 10-minute segments due to YouTube size limits.

The remaining two segments are on the OCItv Channel.

I haven’t watched this myself…I think I was really nervous the first few minutes, but the talk really picked up steam in segments 2 and 3. The second part of the hour isn’t online yet. That’s when I did live demos with my G1, Eclipse, and the SDK. Mario is working on getting that online as well.

Android Lifecycle Triggers, Part 2

Yesterday I showed how lifecycle events fire in response to starting and stopping an Activity. Next, let’s see what happens when you change the display orientation:

That’s what happens without any customization. I marked two methods bold because they are different than yesterday’s diagram. See this comment from Ed Burnette for more details on customizing rotation behavior. Specifically, you can retain data by overriding onRetainNonConfigurationInstance(), or you can prevent activity destruction via the android:configChanges XML attribute.

Phone Call

Android is also useful as a telephone, believe it or not. This next diagram shows what happens when a phone call interrupts an Activity:

See Also…

Android Lifecycle Triggers, Part 1

This is Part 1 of a multi-part series explaining how events, such as clicking the Home button, trigger transitions in the Android Activity lifecycle. You might want to refer back to this Activity Lifecycle Diagram I posted 20 days ago.

This particular comment inspired me:

I like your diagram, the only thing its missing is what causes each transition to happen (i.e. User hits “back” button, user clicks “home” button etc…)

The activity lifecycle is a complicated state machine which cannot live completely in my head so i like having a diagram to reference, however without the transition events its not a complete reference.

This is indeed complex, and one diagram cannot capture all possible transitions. So I’ll split this up into several blog entries. Here is the first diagram I came up with:

To create this diagram, I wrote an Activity that overrides most of the onXXX() methods, writing log messages:

    @Override
    protected void onDestroy() {
        begin("onDestroy()");
        super.onDestroy();
        end("onDestroy()");
    }
    ...
    private void begin(String signature) {
        // super-hacky code to indent nested method calls
        StringBuilder sb = new StringBuilder();
        for (int i=0; i<indent; i++) {
            sb.append("  ");
        }
        Log.i(TAG, sb.toString() + "BEGIN: " + signature);
        indent++;
    }

    private void end(String signature) {
        indent--;
        StringBuilder sb = new StringBuilder();
        for (int i=0; i<indent; i++) {
            sb.append("  ");
        }
        Log.i(TAG, sb.toString() + "END: " + signature);
    }

I then ran the Activity in Eclipse, viewing the log in the DDMS LogCat window. (NOTE: DDMS is an Eclipse perspective, the LogCat window is in that perspective). I created the diagram using OmniGraffle.

I hope to create additional diagrams showing the sequence of method calls for a variety of events, such as:

  • An incoming phone call
  • The user hits the Menu button
  • Showing a dialog
  • Navigating to a different view
  • The phone going to sleep after inactivity
  • etc…

I suspect that learning the Activity lifecycle is one of the more challenging aspects of Android development. I hope this and future diagrams help.

See Also…