Android Activity Lifecycle, Updated

A few days ago, I posted a diagram showing the Android activity lifecycle. I think that diagram can be improved, so here is my second attempt.

I like this format better because there is a logical top-to-bottom arrangement showing the activity progressing from the newest state at the top, down to the terminal state at the bottom.

Eclipse Leopard Glitches

I figured since the Android SDK comes with an Eclipse plugin, I should use Eclipse when learning Android. I think that’s probably a mistake.

Split Panes

Here is what split panes look like with Eclipse on Leopard:

I added the red box to indicate where you’d normally expect to drag the splitter up and down. While this works, the cursor does not change. So as you move your mouse over the splitter, it feels unresponsive. Even weirder, the cursor DOES change, but it is always about 15-30 pixels below the splitter. It’s as if they are adding some insets for a menu bar that does not exist.

Weird GUI Artifacts

Check out the glowing “Application Toggle” text on this screen:

GUI flaws like this seem to pop up all over the place with Eclipse on Leopard.

Android Plugin Weirdness

The screen above is from the Android Eclipse plugin. You should be able to click the Add… button to add additional activities. It worked for me once or twice (I think), but usually I see this:

Not only is the dialog blank, it is completely unresponsive. All I can do is hit Cancel.

Bring on IDEA

I guess I need to figure out what it takes to develop Android apps in IDEA. I do like that Eclipse automatically keeps R.java up-to-date, and I like that I can launch the emulator from the IDE. Hopefully those tasks are easy to do from the command-line so I can go back to IDEA.

Browsing Android Source in Eclipse

Google’s Android SDK includes android.jar, which contains the Android public API class files. They also provide an Eclipse plugin, making it quite easy to get started. What you will not find, however, is androidSrc.jar, so when you try to look at Android SDK source code in Eclipse, you get something like this:

Open Source to the Rescue!

Earlier this month, Google released the source code — all of it — and by the way, it’s HUGE. Anyway, to browse source in Eclipse, you need to visit http://source.android.com/ and follow their instructions to pull everything down using Git. Set aside an evening to do this, because having the full source makes it infinitely easier to understand how the SDK works.

Attaching to Eclipse…Not So Fast, Buddy

Now that you have the source, you can tell Eclipse where to find it. I tried right-clicking on android.jar and selecting Properties, but am greeted with this screen:

Hmm…”The current class path entry belongs to container ‘Android Library’ which does not allow user modifications to source attachments on its entries.” This really threw me for a loop. I generally use IDEA, so I was really stumped by this. So, I dug into the source code to find out a solution.

Examining the Source

When you download the Android source, you get EVERYTHING. This includes the OS, the Dalvik VM, the Eclipse Plugin, the public SDKs, etc.

In the com.android.ide.eclipse.adt.project.internal package, I found
a class named AndroidClassspathContainerInitializer.java. This has
the following code:

IPath android_src = new Path(AdtPlugin.getOsAbsoluteAndroidSources());

OK, fine. So looking inside AdtPlugin.java:

/** Returns the absolute android sources path in the sdk */
public static String getOsAbsoluteAndroidSources() {
    return getOsSdkFolder() + getOsRelativeAndroidSources();
}

/** Returns the android sources path relative to the sdk folder */
public static String getOsRelativeAndroidSources() {
    return AndroidConstants.FD_ANDROID_SOURCES;
}

And finally inside AndroidConstants.java:

public static final String FD_ANDROID_SOURCES = "sources";

I win!

Solution #1

Based on the above analysis, you need to create a directory named “sources” inside your Android SDK installation. So right next to your android.jar, create a sources directory.

Now that you have this directory, you can find the appropriate source directories in the Android sources that you pulled from Git. Google’s checkout directions suggest a directory named ‘mydroid’, so I’ll use that here. The public SDK source is found in mydroid/frameworks/base/core/java. Under that folder you’ll find an android directory, which should be copied (or symlinked) over to the sources directory in your SDK installation.

You’ll have to do some hunting around to find all of the source code, it’s kind of sprinkled all over the place in the mydroid directory tree. In the end, you should have something like:

SDK_PATH
  | android.jar
  +--docs/...
  +--samples/...
  +--sources
       +--android
       |      ...accounts, annotation, app, bluetooth, etc...
       +--com/android/etc...
       +--dalvik/...
       +--java/...
       +--javax/...

I grabbed all kinds of directories, and I didn’t take good notes, so I probably missed a few and inadvertently added too many. You probably only really need the public SDK sources, but I think it’s nice to also study implementation classes, as well.

Now when I browse into the Android SDK classes, I see the source code:

Solution #2

If you’d rather not copy (or link) all of those source directories into your SDK directory, you can also create an Eclipse User Library. At first, I tried creating my own library containing android.jar, but Eclipse complained about that being a duplicate .jar file. So instead, I picked an arbitrary JAR file as my user library, and then proceeded to attach all of the Android source directories to that library.

My user library seemed to do the trick, but I like having that sources directory because I don’t have to remember to add the user library to each new project I create.

Android Activity Lifecycle

I spent the evening studying the Android Activity Lifecycle. Here is the diagram I came up with using Omnigraffle:

This is roughly the same as Figure 2.3 in Hello, Android, although I corrected a bug and added the dashed lines for <<kill>>. Those indicate the OS may kill the Activity when resources are low, so onStop() and/or onDestroy() might not be called. I’m going to use this as a handout when I talk at next month’s OCI Java Lunch.

Confusing Docs

The documentation for Activity contains a confusing statement in the documentation for onRestart():

Called after onStart() when the current activity is being re-displayed to the user (the user has navigated back to it).

I think they mean it is called after the “original” onStart() when the activity was first created, because another part of that same page says this about the onRestart() method:

Called after your activity has been stopped, prior to it being started again. Always followed by onStart()

Studying the Code

Fortunately source code is available for Activity.java:

final void performRestart() {
    final int N = mManagedCursors.size();
    for (int i=0; i<N; i++) {
        ManagedCursor mc = mManagedCursors.get(i);
        if (mc.mReleased || mc.mUpdated) {
            mc.mCursor.requery();
            mc.mReleased = false;
            mc.mUpdated = false;
        }
    }

    if (mStopped) {
        mStopped = false;
        mCalled = false;
        mInstrumentation.callActivityOnRestart(this);
        if (!mCalled) {
            throw new SuperNotCalledException(
                "Activity " + mComponent.toShortString() +
                " did not call through to super.onRestart()");
        }
        performStart();
    }
}

Based on that, I think it is clear that onRestart() is always followed by onStart().

I’m Not The Only One

Figure 2.3 on page 30 of the new Hello, Android book seems to be based on the misleading comment, because that figure shows onStart() and onRestart() reversed. I submitted the errata here, so I suspect it will be fixed before the paper book is printed.

Now you know how I spend my Saturday nights!

Blue Cloud of Death

This was inspired by Dion Almaer’s tweet.

Twitter Killed the Blog

Several people have asked me why I don’t blog more. The truth is, Twitter is a lot more convenient. When something pops into my brain, I throw it onto Twitter. Here is my username:

@burke_eric

Twitter is mostly nonsense, just an outlet for me to say strange things while my computer is busy compiling or copying files. During those brief moments of down time, “Tweeting” is instantaneous, while posting to my blog takes more commitment.

By the time the day is over, my itch to write is mostly gone, so I write less here. I have the best intentions to spend more quality time blogging, but I’m not making any promises.

(I know I’m not the only one…someone I work with mentioned he created a Twitter account just to follow all the people he used to follow via their blogs. Apparently many blogs have gone dormant thanks to Twitter, which is a damn shame, because many thoughts require more than 140 characters.)

Copying Files

My wife’s ancient PC finally died; it was a $400 Gateway we bought many years ago. Fortunately the hard drive was OK, so here I am, transferring the files from the old hard drive to a different PC. This process takes forever and is really annoying when it comes to application migration.

Here’s something PC users might not realize about OSX: most apps are simply dropped into the applications directory. I assume that moving most apps from one Mac to another is as simple as copying these directories. (I could be wrong, my Mac hasn’t died yet, so I have not had to try this!)

This is certainly not the case on Windows, where each application builds a web of intricate registry references, requiring a fresh install when moving to a new PC. What a pain.

For most applications, the Windows Registry seems like a huge design flaw. Why does a simplistic application like Print Shop need the Registry at all? Can’t installation be as simple as unzipping into Program Files and storing user preferences under each user’s profile directory?

I’m done with my rant. I feel better. Files are still copying…this could be a long night.

Hands Free Restroom

WTF

EPIC



FAIL

Comments? No thanks. Submit your comments on Nov 4th.

Award Winning Journalism

I saw this gem a few minutes ago:

They are searching for a murderer who apparently wrecked his car at 3:00 AM a few blocks from my house, and is now on the loose. On my way to work this morning I drove down Bryan Road, where the police were stopping everyone and searching for the guy.

The comments on the article might be written by the same person: