Archive for the ‘Programming’ Category

Android Tip: Effective Intents

Monday, April 5th, 2010

Prefer to distinguish intents using data rather than extras.

The forthcoming release of OneBusAway for Android will fix a long-standing bug with launcher shortcuts. Many people like to have shortcuts to stops on their home screen. Let’s say you have shortcuts to Stop A and Stop B, and you do the following steps:

  1. Tap on the shortcut for Stop A to see the arrival info for Stop A.
  2. Press the Home key (not back) to get back to the launcher.
  3. Tap on the shortcut for Stop B.

You would think that you’d see the arrival info for Stop B, right? Wrong. What you’d see is the info for Stop A.

At this point you’ll either say, “oh well, I guess it’s a bug”, or “I don’t care, what’s the point of this story”, or “I’m interested to know why that happens.” If you are the first or second type of person, you may want to stop reading and perhaps go watch cats on Roombas. If you’re the third type, allow me to explain:

Intents are one of the fundamental concepts in Android, and one of the first things you learn when starting Android programming. Intents are, simply put, abstract message objects that describe an operation your application wants to do. How the operation is done, and what the operation does, is very much dependent on the content of the intent. However, the majority of intents will be used to run Activities, the other fundamental concept in Android that mostly describe each screen of UI in your application. So from one Activity, if you want to run another Activity, you’ll often see code like this:

// From within source activity
Intent i = new Intent(this, ShowInfoActivity.class);
startActivity(i);

More often than not, however, you want to pass some data to the activity — for instance, if it wants to access something out of the database, you may want to provide it with the ID of the database row. If you’ve made your way through the Notepad example, you may think the best and easiest way to do this is through an Extras, bits of stuff passed along in your intent that you can define yourself:

// From within source activity
Intent i = new Intent(this, ShowInfoActivity.class);
i.putExtra(ShowInfoActivity.EXTRA_ROWID, rowId);
startActivity(i);

Indeed, this is the easiest and, for the most part, a perfectly acceptable way.

Then at some point in your development you decide: “wouldn’t it be great if users could link directly to their info directly from their home screens.” So you learn how to create shortcuts, you re-read that part of the documentation on intent filters you glossed over the first time, and you whip up the following code:

void returnShortcut(int rowId, String shortcutName) {
    Intent i = new Intent(this, ShowInfoActivity.class);
    i.putExtra(ShowInfoActivity.EXTRA_ROWID, rowId);
    Intent shortcut = new Intent();
    shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, i);
    shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortcutName);
    setResult(RESULT_OK, shortcut);
    finish();
}

Fantastic! You’ve made your user’s life easier. Unfortunately you’ve also just created the bug I described earlier.

Why? Read that part on intent filters again. You may also want to read the documentation about tasks. But the short explanation is that, for the purposes of intent resolution, extras are ignored when determining whether two intents are equal. So Android will match solely on the Activity name, find the same Activity on the top of your task stack, and just decide to resume that activity rather than creating a new one with the new data.

Fortunately, there’s a solution. The better way is to put the row ID as part of a URI, rather than as a part of an extra. So the previous code becomes something like this:

void returnShortcut(int rowId, String shortcutName) {
    Intent i = new Intent(this, ShowInfoActivity.class);
    i.setData(ContentUris.withAppendedId(BASE_URI, rowId));
    Intent shortcut = new Intent();
    shortcut.putExtra(Intent.EXTRA_SHORTCUT_INTENT, i);
    shortcut.putExtra(Intent.EXTRA_SHORTCUT_NAME, shortcutName);
    setResult(RESULT_OK, shortcut);
    finish();
}

BASE_URI can be anything, but it should be something that’s specific to your application. The point is that the Data URI is used in determining whether or not two intents are equal, so the system will end up creating a new Activity for this, even if the same Activity with different data is on your task’s stack.

This is also made easier if you decide to put your data behind a content provider.

As I said, this lesson was learned through personal experience, and only really after the bug was reported by an adept user. The problem is that in order for the bug to be really fixed for users, they will have to recreate all of their shortcuts. Don’t let this happen to your users. When using shortcuts, make sure they aren’t just using extras.

About

I like wearing different hats. Follow me on Twitter. Connect with me on Google+

The C++ Programmer Problem

Tuesday, March 30th, 2010

I’ve spent the great majority of my career writing code in C++. After using the language for 14 years, I would consider myself very fluent in the language. I might even say “expert-level,” but the trouble with being even close to an “expert” in C++ is that no one believes you.

In that way it seems C++ is somewhat unique: I don’t think that people who claim to know Python or Ruby would engender the same level of distrust.  It seems to be only C++ where if you claim you know it, you are by default treated as though you are lying. Why is this? Perhaps because C++ is something a lot of people claim to know because recruiters think it’s good. Or it could be because those who have some level of expertise in the language know just how complex it really is and by default assume you don’t? It might also be the general distrust shown in an interview setting — numbers on resumes don’t mean anything, and you are guilty of being a non-programming programmer until proven innocent.

Of course I’m not saying that I’m at the same level of Bjarne Stroustrup or Herb Sutter. There are always some language internals I have to look up, like vtable-layout in multiple inheritance or the finer points of overload resolution. I use C++ as a tool, just like any other language. That said, ever since reading  Modern C++ Design by Alexei Alexandrescu I have explored the breadth and complexity and the language quite a bit, using advanced features of the language to make writing code easier and less error-prone by finding bugs at compile-time rather than at run-time. When you understand that C++ templates are far, far more than just “containers of T,” you have taken your first step into a larger world.

But what number of developers have made it to the second peak of C++ understanding vs. those who consider themselves “experts” when they are just using C++ as “C with classes”? Hard to say, but it’s understandable that most programmers on the second peak would find it implausible that he or she is meeting someone who has made the summit as well. And so despite 14 years of experience with C++, despite having written one’s own versions of std::string and std::vector, those unlucky few of us must still explain what a virtual function is.

There should be some questions from the other side: what types of questions would only a true expert know? Here are some thoughts:

1. Write out the pointer-to-member syntax from memory.

2. Give an example of partial template specialization.

3. What does SFINAE stand for, and what does it mean?

4. Explain what is meant by “two-phase name-lookup.”

I’m sure there are others. And perhaps your expert programmer wouldn’t know these off-hand, but would at least have had experience with them.

C++ isn’t the most glamorous or “in” language these days, and whatever “coolness” it may have had in the past has been supplanted by scripting languages like Ruby and Python, as well as functional languages like Scala and Erlang. So perhaps it is the fate of those who are truly proficient in C++ to remain a scattered lot, silently practicing and honing their craft, forever to be underestimated.

About

I like wearing different hats. Follow me on Twitter. Connect with me on Google+