Friday, February 18, 2011

Why I Won't be Voting for President Obama in 2012

I voted for President Obama in 2008. My reasons were a little different than most. Given that and one look at this chart, it should be no surprise that he won't be getting my vote in 2012.

Money Spent on War

Seriously, if McCain had won do you really think this chart would look a lot different? The withdrawal of US troops from Iraq was widely hailed, but it has been made up for by increasing troops in Afghanistan and using more private military companies (mercenaries) in both Iraq and Afghanistan. Fool me once, shame on you; fool me twice...

Ginger Honey Ice Cream Mess

A few nights ago I was working at the Silicon Valley Android Meetup. eBay was hosting the meetup, and I had volunteered to help with the registration table. One of my co-workers was talking about how very few people had brought business cards with them to the event (there was a raffle and you could use your business card to enter it), and I commented that business cards were antiquated. I mentioned Bump as one of many more sophisticated alternatives. She quickly downloaded Bump to her Android phone, and we attempted to ... well ... Bump. We had a hard time mainly because the accelerometer on her phone was not very sensitive.

She remarked: "I really need a new phone."

I asked: "Yeah what's that thing running, like Android 1.6?"

She replied: "I wish, it's actually 1.5."

Now I was actually kind of amazed that Bump even worked on a 1.5 phone. But before I could make some witty comment about her phone...

She asked: "What is the latest version anyways?"

I replied immediately: "2.3"

She gasped is disbelief: "Holy crap, I've only had the phone for a year or so. Do they release a new version of Android every month or something?"

Who can blame her for her dismay at the velocity of Android? She went on to curse the phone maker (Samsung) and network (Sprint) for not putting out an update (though I think they did, but not OTA? Anyways, you should be able to guess the model now.) Of course who can blame handset makers and carriers for being slow to put out updates, again given the pace of Android. As soon as you get done getting one version ready to ship, another one comes out.

Of course that's part of the fun from a developer standpoint. And part of the pain -- a big part. However the mach speed evolution of Android in the past is starting to look downright soothing compared to the thinny before us. Let's recap briefly

In December 2010, Google announced Android 2.3 a.k.a. Gingerbread. This seemed all well and good at the time. Android 2.2 (Froyo) came out half a year earlier, so this seemed like a reasonable amount of time between releases. Of course we would later learn that the Android team was not pacing themselves, the long time between releases was a fluke. Anyways, the timing still seemed a little odd, as it was right before the holidays. The Nexus S was simultaneously released and it was running 2.3. Still there was no way any other Gingerbread running devices would be out in stores for the holiday season. Also, there seemed to be a lot of oft-rumored stuff missing from Gingerbread.

In early January (a month later), Android 3.0 a.k.a. Honeycomb was previewed at CES. Videos of Honeycomb in action were posted to YouTube. Three weeks later, a preview version of the SDK was made available to developers. It had a lot of the new UI features that had been rumored for Gingerbread. However, it didn't just bolt on new features or refine existing APIs. It added some very core fundamental things. There were Fragments: a new (better?) way to organize your application code. There was the app bar: a persistent UI element at the top of the screen where contextual extras could be placed. The app bar is what the menu should have been (nobody uses the menu.) There was also the system bar at the bottom of the screen. This is not directly accessible to developers, however it is where Honeycomb's new more powerful notifications originate from. Android already had the best notification system out there (sorry webOS and your new imitator, Windows Phone ... and iOS is not even in the conversation), but now you get notifications that the use can interact with without interrupting what they were doing. Anyways, 3.0 is a release unlike any other in Android's history, but mostly in a good way. However it was billed as being just for tablets, leaving us with two different "latest" versions of Android.

In February (just this week) we get comments from exiting CEO Eric Schmidt that Gingerbread and Honeycomb were merging together in the "I" release of Android. This was release has been "known" to be Ice Cream Sandwich for awhile. Would it be Android 2.4? Would it come out at Google IO?

But wait, it gets better. Apparently Android 2.4 will be released before Google IO, and it will not be Ice Cream Sandwich. We will have to wait for the sandwich until later in the year apparently.

So what the hell is going on? First let me say this. I have been using a Nexus S for about a month now. When it works (which is most of the time), it is fantastic, easily the best phone I've ever used. However, it is also the buggiest phone I have ever used. I've never had the reported spontaneous reboot happen to me during a call (by the way the call quality is excellent, the best I've ever had in a smartphone.) However, I often have to reboot it myself because it just hangs during a call. Or it will suddenly lose its network connection and never get it back until ... I reboot it. Or it will stop receiving email (service probably crashing and the OS putting it out of its memory I'm guessing) until ... I reboot it. Since this phone is very similar to the Galaxy S in terms of hardware, I am guessing that this is mostly a software issue. And since this baby is running "stock" Android, that makes it a Gingerbread issue. Maybe this explains why 2.3 has not been released to any phone? Maybe this explains the need for yet another major release before the Ice Cream Merge?

Besides the 2.3 issues, most of the rest of the craziness comes from the need to go after tablets in a big way. That's why a lot of in-flux, potentially undercooked code is being pushed out so quickly. That's why we all get to see git repo being forked and merged in such a public manner. Software development is scary and messy more often than not.

So back to the scorecard. It makes sense that 2.4 will not be Ice Cream Sandwich. It can't include the Honeycomb features and yet have a lower release number, right? Perhaps Ice Cream Sandwich will be 3.1, later this summer. Or maybe it will be 3.2, as I would not be surprised if there were a massive bug fix release after 3.0, given its obviously rushed nature. So maybe we can go 2.3, 2.4. 3.0, 3.1, 3.2 all in the span of what, 6 or 9 months? Yee haw!!

Sunday, February 13, 2011

Wither the Dashboard Pattern

Recently I barely managed to register for this year's Google IO conference. One of my favorite sessions from last year's conference was on UI patterns in Android.

It's a great video, you should definitely watch it. The first pattern that they talk about is the Dashboard. You can see their example of a dashboard in the video, but there was an even more concrete example: Twitter for Android. The Twitter app was released just before IO, and it was developed jointly by Google and Twitter. It showcased the UI patterns that Google wanted designers and developers to start using to help create some expectations for users. Here's the Twitter dashboard:

Ye olde Twitter with dashboard

The idea is simple. The home screen of your app provides shortcuts to all of the major components of the app. The combination of using this pattern in a popular app (Twitter has 5M+ downloads) and evangelizing it at the IO conference certainly had the desired results. Many other apps adopted the pattern, including every platform's most popular app, Facebook:

Facebook's dashboard

The pattern has been a hit with note-taking/organizer apps like Evernote:

Evernote's dashboard

Evernote's more recent competitor Springpad also uses a dashboard:

Springpad's dashboard

Evernote and Springpad are both popular apps, with more than 1.5M downloads between them. Another very popular app that uses the dashboard is Yelp:

Yelp's dashboard

Google's Yelp/Foursquare compettitor Places also uses the dashboard pattern:

Places' dashboard

Finally, there's my favorite Android music player MixZing:

MixZing's dashboard

MixZing shows that you can be a little creative with the dashboard pattern. So the pattern's been a big success, right? Users are familiar with it and developers have embraced it. So it was a little surprising to me to see that Twitter has now decided that the dashboard is not so good after all:

New Twitter, sans dashboard

There's no more dashboard in the 2.0 version of Twitter's app. The release notes allude to the major problem with the dashboard pattern: it forces the user to constantly go to the dashboard if they want to navigate to a different part of the app. It makes everything at least two taps away. Of course it makes it easy for the user to find things, since they can just go to the dashboard to find a shortcut to whatever they are looking for. For example, how do you think you find what's trending on the Twitter app now (go to search) or view your profile (gotta use the dreaded Android menu)? Maybe Twitter has found that their users rarely use these features, so the new design will be more effective for the vast majority of their users.

Speaking of the new design, it obviously uses a tab layout. This is a more common UI pattern in Android and has its own set of APIs to make it easy to use for developers. There are a lot of examples of tab layouts out there, such as Foursquare:

Foursquare likes tabs

Another example is one of my favorite apps, Bump:

Bump likes tabs

I won't bore you with more examples, as there are a lot. I think it's often very comfortable for a web app going native to use a tab design. It often mimics their website. That's why I picked Foursquare and Bump, two apps that are what I would consider mobile-first. Most people's first interaction with either company is through their mobile apps, not through their desktop web browser.

The other common pattern worth mentioning briefly is what I call Listomania. You start off with lists, and keep going from there like traversing a tree. Here's Google Reader:

Google Reader likes lists

And here's Kayak's listomania:

Kayak likes lists

Personally I don't find the Listomania format very user friendly. I think it is often a by-product of porting an iPhone app that makes heavy use of UINavigationControllers (in all fairness, many of the tab-using Android apps are the products of porting iPhone apps that used a UITabBarController). I think the dashboard usually solves the same kind of problem (lots of features, hierarchy) in a nicer way. The tab alternative is more of the Pareto principle, putting all of the focus on the most commonly used features. Anyways, it will be interesting to see if the dashboard pattern becomes less common now that it's poster-child has ditched it.

Friday, February 11, 2011

Android Notifications, C2DM, and The Way to Succeed and the Way to Suck Eggs

When it comes to Android Cloud-to-Device Messaging, I've found many new and exciting ways to fail and fail hard. So y'know, learn from my failure and stuff:

State: To Have or Not To Have, That is The Question

There are a lot of cool things you can do with C2DM, but of course notifications are one of the most common and most important things. Now remember that unlike on other inferior platforms, you get total control of what happens when a message is pushed to your application via C2DM. So you don't have to show a notification at all. In case you do though, the first thing you need to decide is if your notifications will be stateful or stateless.

What's the difference? Glad you asked. Let's take a simple scenario. A message is pushed to your app via C2DM, and you display a notification to the user. Now Android notifications do not force the user to either open or dismiss the notification. In my opinion that is a very good thing, and I think most folks agree. You might really be interested in a particular notification, but sometimes you've just gotta finish that game of Meteor Blitz or finish posting a crazy picture to picplz. That's not a problem on Android. The sound will go off, the ticker text will scroll across the status bar, and then a simple icon will appear up there and the user can deal with the notification at their convenience. However, let's say that a few minutes later that another message is pushed to your app via C2DM and once again you need to notify the user of this. If you choose a stateless system, then you will simply replace the current notification about message #1 with a new one about message #2. Alternatively you could post a new notification about message #2 that would sit along side the notification about message #1. However if you do this, then you are a schmuck. You've just created an application that can potentially flood the status bar with your notifications. Your app would have be to all kinds of awesome for me to keep it on my phone, especially if I can't turn off your notifications. So don't do that. So really there's only one option if you want to go stateless: most recent notification always wins and anything older goes to the trash.

Don't like that approach? Me neither. That first notification might have nothing to do with the second, and it might be more important. So that means we need to go stateful. With a stateful system, we can remember that we received message #1, and then replace it with a notification that indicates that we have received message #1 and message #2. How you do that will be very specific to your application of course, but you can figure something out. The point is that you persisted the state, that you had received message #1 and it has not been viewed yet, and you use this knowledge to provide a better experience for the user when message #2 rolls in. Of course now the real fun begins.

Watch out for the Clear Button

You need to not only keep track of the messages that you have received via C2DM, but also their state. Has the user seen them or not? What constitutes "seen" is again specific to your application, but it just means that at various places in your application you will need "mark as seen" for certain messages. There is gotcha here and that is the "Clear" button on the status bar. That should have the effect of marking all messages as seen. However, how do you know when the user taps this button? I thought that maybe there was an Intent fired and that I could receive this with a BroadcastReceiver with the proper action/Intent filter. I searched the docs and found no such action, but I still thought that this was probably the case and it was just not documented (there are a lot of such Intent/actions!) I was so stumped that I posted a question on StackOverflow and offered a 50 reputation point bounty. Turns out there is a very simple answer: the deleteIntent field on the Notification object. Talk about face-palm... Anyways you can set a PendingIntent here, and that PendingIntent can start a Service that does the "mark all as read" work for you.

Badging

Android provides a really easy way to badge your notification icons in the status bar. If you just set the number field on the Notification object, you get badging for free. However, badging looks a little ugly, and if you only have one message then you probably don't want it. In that case just don't set the number field and you are good to go. Then the next time a new message comes in, set the number field to 2. Try this out and rut it on your phone. Unless you have a Nexus S, you will notice a problem. The badging will not show up when you set the number 2 (or 3 or 4 or whatever.) This appears to be a bug with Android that was fixed in 2.3. That's why it works correctly on a Nexus S, but not on anything else (the NS is the only phone with 2.3 as of the time I wrote this.) So what do you do? Badge with a 1? Ugly. Don't badge at all? Less informative. The correct answer is workaround.

Actually you might get lucky and do it the "right" way to begin with. What I did was create a Notification with the same ID as the existing Notification, and then simply call notify on the NotificationManager service. That should replace the existing Notification with the new one, and you should get the right badging. This is the case on my Nexus S, so I'm guessing it's the case on Android 2.3+. This is not the case on previous versions of Android. Everything about the old Notification is replaced except for the badging. The work around is to remove the old Notification (using the cancel method on NotificationManager) and then create the new one using notify. That will work on all versions of Android.

Collapse Key

If you read the C2DM documentation, one of the seemingly innocuous things that it mentions is the collapse key. It says this is "An arbitrary string that is used to collapse a group of like messages when the device is offline, so that only the last message gets sent to the client. This is intended to avoid sending too many messages to the phone when it comes back online." Doesn't this sound like this is for the C2DM servers, so they can throttle the messages being sent to your app? Maybe so, but I found that it come in handy on the app as well, as C2DM passes it on to the app. The reason is simple. You may get the same message from C2DM twice. Well I suppose it might even come more than twice, but what's the difference? Regardless you should expect that dupes might be sent, and so you should de-dupe. The collapse key is perfect for this. A good way to keep track of these is to use a static HashMap (depending on how you implement the Service that processes the C2DM messages, you may not be guaranteed that there will only be one instance of that Service, hence a static HashMap) with soft keys, so that if it grows too large the GC will toss old collapse keys that you don't need anymore.

The Static Starter Pattern

One of my favorite things about Android is that it is not another MVC framework. Now some people find this as a weakness, but not me. I think MVC has its faults. Still many people think of application in terms of MVC, and for them Android's Activity class is as close to a controller as you will get. Pretty much every "screen" or "page" in an Android application has a single Activity behind it (there are exceptions, I know, but bear with me.) Inevitably you need to transition between Activities, and this is one of the places where Android can seem a little weird. You need to create an Intent and then pass that to the startActivity method on a Context object (usually the Activity that you are transitioning from.) That's not too bad. However, it is often the case that a given Activity expects some data -- a model if you like -- that it will use to create the UI (the view if you like.) Let's take a concrete example from Android in Practice. The MediaMogul application (chapter 11) allows the user to create a slideshow by selecting pictures, music, and video from their SD card. Then there is an Activity that plays the slideshow called SlideshowActivity. Here is code from the Activity that starts the SlideshowActivity.
Intent intent = new Intent(this, SlideshowActivity.class);
intent.putExtra("videoUri", videoUri);
intent.putExtra("imageFileNames", images);
intent.putExtra("selectedSong", song);
startActivity(intent);
And here is code from SlideshowActivity to retrieve this data:
Intent intent = getIntent();
ArrayList<String> images = intent.getStringArrayListExtra("imageFileNames");
Song song = intent.getParcelableExtra("selectedSong"); // custom Parcelable class
Uri videoUri = intent.getParcelableExtra("videoUri");
There is an obviously ugly issue here. Both Activities need to know the keys (imageFileNames, selectedSong, videoUri) to use to put/get from the Intent's extras. This is such a common thing in Android, even in the framework, that there is a simple pattern for dealing with it. Just use public constants declared in the class that will use the Intent extras:
public class SlideshowActivity extends Activity{
public static final String EXTRA_IMAGE_FILE_NAMES = "imageFilesNames";
public static final String EXTRA_SELECTED_SONG = "selectedSong";
public static final String EXTRA_VIDEO_URI = "videoUri";
...
Intent intent = getIntent();
ArrayList<String> images = intent.getStringArrayListExtra(EXTRA_IMAGE_FILE_NAMES);
// etc.
And then of course in the calling class you would now have:
intent.putExtra(SlideshowActivity.EXTRA_IMAGE_FILES_NAMES, images):
// etc.
Problem solved, right? Well not exactly. You still don't know what the types of the extras should, and you do not know if a particular extra is required or optional. Documenting your code can help with this:
public class SlideshowActivity extends Activity{
  /**
   * An ArrayList of Strings. Required.
   */
  public static final String EXTRA_IMAGE_FILE_NAMES = "imageFileNames";
...
}
So we put the type information and wether the field is required or not as a comment. Wait, doesn't this feel more like Ruby or Python instead of Java? Isn't there some way to use the language syntax and compiler to state this information in a better way instead of relying on code comments? That's where the Static Starter Pattern kicks in:
public class SlideshowActivity extends Activity{
  public static void start(ArrayList<String> images, Song song, Uri videoUri, Context ctx){
    Intent intent = new Intent(ctx, SlideshowActivity.class);
    intent.putExtra(EXTRA_IMAGE_FILE_NAMES, images);
    intent.putExtra(EXTRA_SELECTED_SONG, song);
    intent.putExtra(EXTRA_VIDEO_URI, videoUri);
    ctx.startActivity(intent);
  }
...
}
From this method signature, I know the types of all of the extras and I know that they are all required. If I wanted to make one of them optional, then I could simply overload the start method with only two of the parameters, removing the optional parameter. Of course, somebody could bypass this and still use an Intent.
Now this is not the best pattern for every Activity. The most obvious example is if you want your Activity to be started by other applications. Another application won't be able to invoke a static method. You will have to use the action/Intent-filter path for this. Of course this is pretty rare, how many of your Activities are meant to be started by other apps? Even if this is the case, you can still use the pattern for use within your app.
This pattern is also not limited to Activities. You can do it with Services as well, especially IntentServices:
public class AwesomeService extends IntentService{
  public static void start(String someString, int someInt, Context ctx){
    Intent intent = new Intent(ctx, AwesomeService.class);
    intent.putExtra(EXTRA_SOME_STRING, someString);
    intent.putExtra(EXTRA_SOME_INT, someInt);
    ctx.startService(intent);
  }
}
If your IntentService handles multiple actions, this can be built into the pattern:
public class AwesomeService extends IntentService{
  public static startUploadFile(String someFileName, Context ctx){
    Intent intent = new Intent(ctx, AwesomeService.class);
    intent.setAction(ACTION_UPLOAD_FILE); // ACTION_UPLOAD_FILE is a constant
    intent.putExtra(EXTRA_SOME_FILE_NAME, someFileName);
    ctx.startService(intent);
  }
}
You get the idea. You could extend this to BroadcastReceivers as well. I discussed this pattern a bit with my Android in Practice co-author, Charlie Collins. He liked it too, and pointed out that others have used it as well. Personally, I'm not a fan of static methods or of passing around the Context like that, but the positives seem to outweigh the negatives. What do you think? Useful? Over-engineered?

Monday, February 07, 2011

Some More Nexus S Comparisons

My last post about buying a Nexus S led to some interesting comments ... on Google Buzz of all places. Actually it was retweeted, I mean rebuzzed? err reposted by my friend Robert Konigsberg at Google... Some of the points there were about comparing the NS and the N1. I argued that the NS had a much better processor (because of its integrated GPU) as well as having the best screen on the market right now. I also incorrectly stated that it had more RAM than the N1, but actually both of them have 512 MB. Here are a few more notable comparisons:

The NS has 1 GB of "internal storage", but this actually part of its non-removable 16 GB of storage. The N1 has 512 MB of internal storage. As many apps only allow you to install them on internal storage (especially any app that has a homescreen widget because of this bug), you have twice as much space for such apps on the NS. However, you cannot upgrade the 16 GB. The N1 has only 4 GB included, but you can upgrade it. In fact, I had already upgraded it to 16 GB.

The biggest thing that I forgot to mention is the reception (both voice and data) on the NS. To me, the N1 and the iPhone 4 both got similar reception -- and that is horrible. The iPhone 4's poor reception is well documented, but I think the N1 was just as bad. If you consider that T-Mobile's network is a step below AT&T's, you get a nasty combination. The NS has much better reception than either of these phones. For that matter, it is much better than any other iPhone I have used (3G/3GS). I'm talking about consistently getting two more bars than the N1, and much clearer and louder reception on the phone. It seems obvious that the use of metal in the outer casing is the key here. Both the iPhone 4 and N1 use metal to destroy your reception.

Some folks have also asked me about battery life. I would say that the NS is slightly worse than the N1, and about the same as an iPhone 3GS. That makes it definitely worse than the iPhone 4. The most obvious culprit here is the screen. Bigger screen = more juice. I came across this amusing blog about switching to the Nexus S from an iPhone. This included a complaint about using the power widget to turn off Bluetooth, Wi-Fi, and even GPS on the phone in order to save battery life. This was kind of shocking to me. As an iPhone user, I almost never turned on Wi-Fi and kept Bluetooth off except when in the car. I had to do this on the 3GS, or I would not make it through the day on a single charge. In fact one of the things that I love about Android is how much easier it is to do these two tasks than on iOS. In fact I always thought that this was a big miss by Apple, but I guess that most people actually leave that stuff on all of the time? I don't understand how anyone who uses their phone much, especially if they receive lots of push email, could get away with leaving all of that stuff on all of the time and not run out of juice by 3 PM. I never tried to do this with the iPhone 4 and its awesome battery, just because I was so used to managing the power on my device. Similarly, I can't imagine NOT charging my phone when I go to bed every night. Anyways, if I manage the Wi-Fi and Bluetooth and charge each night as usual, then the Nexus S makes it through the day easily for me. If I play a lot of games on it or use it as a mobile hotpost, that changes things noticeably.

Finally, some folks didn't like that the NS does not have the glowing trackball that the N1 did. I liked the trackball on the N1. The LED lights weren't that useful, since I get email constantly. Still if I got a blue light, I would know that I got something from Facebook. The trackball was especially useful when there were small parts of the screen that needed to be tapped on. However, I have not found myself missing this on the NS, partially because the screen is bigger, but mostly because the touch accuracy on the screen is very good. I always found the N1 to be slightly worse than the iPhone 4 (which I think is slightly worse than the iPhone 3GS) when it comes to touch sensitivity/accuracy. I think the NS is a little better than the iPhone 4, about as good as the iPhone 3GS.

Thursday, February 03, 2011

Moving on

Recently I was in Los Angeles and took a cab from the airport to my hotel. When I got out of the cab, I left my iPhone 4 in the car. I called the cab company, but they were of no use. I had lost my iPhone. And no, I didn't have the Find My iPhone feature enabled on my iPhone. It's actually a pain to do that, if you don't use MobileMe.

Fortunately being a mobile developer, I had another phone with me, my Nexus One. I've been carrying two phones for awhile. I only used apps on the N1, and mostly just phone features on the iPhone (not a good use of an iPhone, especially the iPhone 4.) I stuck with most of my app usage on the N1, since I thought it would make me a better Android developer. Now all I had was an Android phone.
I moved my phone number to the N1, which was on T-Mobile. Just so you know, I immediately got hit with the dreaded early termination fee. I didn't get an option to keep paying for the line of service.
So now I was in no-contract land, and I had a lot of options. I could buy another iPhone, even one on Verizon. I could wait until some of the new Android phones announced at CES were out. I was in no hurry because I had my N1. Instead of doing those things, I decided to buy a Nexus S. Here's why.

I think the Super AMOLED screen is by far the best out there. I had the iPhone 4 for six months, and I wasn't very impressed with the Retina Display. You can't make use of all of those pixels on such a small screen. Yes text looks great, but the colors are washed out and I definitely noticed that a lot more than the awesome text rendering.

I love that the Nexus S runs stock Android. No crap on it. I dislike SenseUI. I can tolerate TouchWiz, but I'm no fan. There are also no carrier crap, like the NASCAR app on Sprint 's phones. The only disadvantage of stock Android is the camera app. In comparison, I think the camera app on the Galaxy S and Galaxy Tab is excellent. But hey it's Android, I can always customize.

I thought about getting a 4G phone. However I don't think it's worth it. Especially since I get to use the Nexus S's wireless hotspot feature for free. Plus I think all phones suffer when they transition from 3G to edge, and I think that problem would be much worse with 4G which will be spotty on any network for awhile.

Obviously the Nexus S is ideal for a developer as well. So the Nexus S it is! In fact, I wrote this blog post on it.