I can’t possibly do this job unless I get my hands dirty with Android technology, and then keep them that way. To start this process I just wrote a little utility app called LifeSaver (source here), which scratches one of my own personal Android itches. It’s in the Android Market and maybe someone else will find it useful. I think the lessons I learned in the process are more interesting and useful than the app itself.

What It Does · When you get a new Android phone, you tell it your Google login and password and a few minutes later there are your email history and contacts and schedule, it’s slick as slick can be. What doesn’t come over from your old phone is the history of your phone calls and SMS messages. I don’t know about you, but that stuff is an important slice of my life.

So, you run LifeSaver on your old phone and it copies that slice of life onto your SD card. Move the SD card onto your new phone — a good idea because it’s probably holding your music and movies and so on anyhow — then run LifeSaver again, and it rebuilds your history.

LifeSaver in action

It doesn’t do much, but I immodestly think it looks kind of cool, with a certain amount of eye candy to entertain you while the data’s copied in and out (which can take quite a few seconds).

Now, it’s a great big stinking bug that I’m persisting onto an SD Card rather than into the cloud. In fact, I’m increasingly convinced that any data whose permanent canonical home is on a device that lives in your pocket and can fall into a toilet or the hands of a thief means You’re Doing It Wrong.

That granted, I’m now a person who’s going to be migrating from phone to phone pretty rapidly, and I’m going to find LifeSaver handy.

Elapsed Time · This took me five weeks to deliver, and even though I was distracted by working hard learning how to Google, there’s really not that much there there, and it could have been done in a handful of days if I hadn’t got distracted into working on how (or maybe how not) to iterate an Android Content Provider.

Well, that, and fit and finish. I spent at least 50% of my productive cycles on the appearance and interaction. This included:

  • Finding (at iStockphoto), buying, and Photoshopping the life-buoy pictures, in multiple sizes to support screens of varying density.

  • Getting the animations working.

  • Figuring out how to manage a good-looking progress bar.

  • Learning how to style Android text.

  • Getting all the screens and animations working properly in both portrait and landscape modes.

LifeSaver in action

What I Learned · In no particular order.

  1. All that beautification time was well-spent. This is important; I think that, at the moment, the iPhone community works harder at fit-and-finish, look-and-feel, and user experience than we do on the Android side. Which is unacceptable.

  2. But I didn’t really take this seriously, because if I did, I’d have hired a real designer to enhance my caring about the subject with actual professional taste and talent.

  3. ProgressBars are a bit more work than you might think, and aren’t that flexible (for example, it’s hard to have any color but yellow), but if a user’s ever going to have to wait for your software, you owe them a good one.

  4. If you want to use a ProgressBar, you have to do the work you’re reporting on in a background thread’s Runnable, and if you want to update the labels or whatever in the screen, you have to send messages to the UI thread. Can you smell concurrency bugs? I couldn’t, until one bit me. Don’t use an accumulator variable to accumulate the next total while a thread is still using it to refresh the screen with the last total. Sigh.

  5. Suppose for one reason or another you want to store a message you’ve just made up in the phone’s SMS log. The Content Provider’s address is content://sms/; then you use the ContentResolver’s insert() method. The trick is that the thread_id field has to be supplied and has to have a value of zero. Then the system will automatically create new SMS conversations as appropriate.

    The bad news is that I had to spelunk through the Telephony provider source code for some hours to figure these details out. The very good news is that, as will always happen in a reasonably complex piece of software, when the documentation misses a detail, in the world of Open Source you can eventually always find the missing piece.

  6. Earlier I wrote (twice, in fact) about my attempt to avoid writing repetitive ad-hoc code to pick data fields out of a Content Provider’s Cursor.

    My attempt to use reflection to sweep the details under an Iterable rug was slick, but involved heavy use of Reflection code which it turns out is just too expensive in Android today. My plan-B approach, which you can see in Columns.java and ColumnsFactory.java, is perhaps not as eye-pleasing, but seems to get the job done. I smell an opportunity for more innovation here.

  7. In general, the Android SDK could be a little more helpful when you lack a necessary permission. This time, I spun my wheels for the longest time, not because writing to the SD Card requires WRITE_EXTERNAL_STORAGE, but because on some occasions it doesn’t require that permission.

  8. This was my first time actually putting something in the Android Market. It makes you cross a lot of t’s and dot a lot of i’s, but there’s no real rocket science involved; you’ll get there eventually.

  9. Eclipse is probably a decent default choice for android SDK IDE just because there are a kazillion people out there who know how to use it, but I found it unsatisfying after several years of living largely in NetBeans, now an Oracle property.

    On the Mac, NetBeans is substantially faster and more complete and better integrated. And did I say faster? I hope we can keep the IDE space from becoming a monoculture, so there will be competitive pressures to help ease this sort of strain.

  10. Android’s Animations are just terrific; easy to use and snappy and composable and look great.

  11. For persisting the data, I encoded it in JSON. Worked great. The only irritant was the JSONObject class’ excessive propensity for checked exceptions.

  12. There’s just no excuse to have literal strings in your code, when it’s easy to stash ’em off in an XML sidecar and thus be set up for internationalization.

  13. I’ve written this before, but I eventually ended up doing almost all my test runs on a physical Nexus One USB’ed into my computer, rather than on the emulator. It’s about the same speed and immensely more satisfying. And if you need to test on a naked phone with no accumulated data, well, there’s the emulator.

  14. This project is largely TDD-free. Mea maxima culpa; I have no excuses. There is work going on to make TDD easier and more comprehensive for Android app developers, and I hereby promise that for my next project, whatever it is, I’ll put that through its paces.

The Important Lesson · Writing Android apps is, generally speaking, easy and straightforward. And it’s just total fun to watch your own code animating a screen that lives in your own pocket.



Contributions

Comment feed for ongoing:Comments feed

From: Rafa (Apr 26 2010, at 07:31)

Nice lesson, It seems appealing to write an android application, but a little scary the learning curve

[link]

From: Harry (Apr 26 2010, at 07:56)

re: backing up (almost) everything on your phone in the cloud, you might be interested in miqlive.com from Best Buy. An Android client is in beta right now.

[link]

From: Sean Long (Apr 26 2010, at 08:28)

Nice useful app but for your particular case wouldn't using Google Voice as your number solve this problem? You would get your call/sms history on each phone and also anywhere you have a net connection.

I am enjoying your Android adventures.

[link]

From: Dirkjan Ochtman (Apr 26 2010, at 08:54)

I have backups for several years of SMS messages now, going back two or three phones. I had yet to figure out a way to get them from my G1, but I think this will do the job just fine, so thanks!

(It seems many people who carefully hold on to their email and actual letter archive either don't care about SMS messages or don't know how to back them up... When for me, a whole lot of social life over the past 10 years is condensed into these short blurbs.)

[link]

From: Aaron (Apr 26 2010, at 09:23)

If you could use a DropBox folder, then you'd get cloud storage with very little effort. You should talk to those guys.

http://blog.dropbox.com/?p=439

[link]

From: Lawrence (Apr 26 2010, at 09:37)

All that time spent on beautification and the fonts are /still/ kerned horribly.

[link]

From: Beat Bolli (Apr 26 2010, at 09:46)

Re: cloud storage: How about sending a zipped JSON structure as a mail attachment and on restore reading through the mails and looking for this attachment?

[link]

From: Ryan Kennedy (Apr 26 2010, at 10:22)

Tim, the link to Columns.java is broken (it's actually going to Files.java).

Also, regarding lesson #13...a few points.

1) The emulator is very slow, especially to launch the first time. Maybe I just have a very slow machine, but it takes minutes to launch the emulator for me. Subsequent app launches are okay, but the first emulator launch is verrrrry slow. It would be nice if you could "hibernate" the emulator so it starts up more quickly the next time around.

2) I also debug using my physical device. Unfortunately, my physical device is also my actual phone. It would be nice if the SDK came with a way to "image" a physical phone. That way you can test without fear of losing anything (just restore the image) and (to further lesson #14) you have a known state you can always go back to for testing.

Thanks for the android posts, I'm enjoying them immensely.

[link]

From: Eric Mill (Apr 26 2010, at 11:40)

Even as a somewhat experienced Android dev, this article had some good nuggets. It is annoying how difficult it can be to do background tasks and manage progress, though I think you should look at AsyncTask rather than writing your own Runnable classes. It can cut down on the code by a lot.

[link]

From: Nick Johnson (Apr 26 2010, at 12:15)

You mentioned backing up to the cloud - if you're interested in a followup, I'd be more than happy to collaborate with you on building an App Engine app that handles it. Since you're already encoding your data in JSON, it ought to be a cinch.

If you're interested, you can find me internally in the usual fashion.

[link]

From: Dan (Apr 26 2010, at 13:31)

Neat app.

Though I understand how it would be nicer to be symmetrical to the other things that the phone backs up, I can't disagree more about the cloud, though. One of the things I love about my G1 is how it's managed to replace a USB drive in my daily carry, and having my personal data in a known location is somewhat comforting.

[link]

From: Ruben Berenguel (Apr 26 2010, at 15:58)

Looks like you spent most of the time where I also get trapped: GUI+bells&whistles. But the feeling of completeness when you have that beautiful idea implemented is terrific.

I'm glad you posted your 'problem roadmap', I'm sure it will be useful for a lot of people (not for me, at least yet... still own a 6 years old Nokia)

[link]

From: Tony Lavinio (Apr 26 2010, at 16:01)

On point 8, the following "It makes you cross a dot of i’s and cross a lot of t’s" should probably be "It makes you dot a lot of i’s and cross a lot of t’s". I’m pretty sure you don't want to cross i’s ;).

[link]

From: Tony Fisk (Apr 27 2010, at 07:23)

No TDD? Ummm-ah!

You just wanted to get the app out the door, didn't you?

[link]

From: Adam (Apr 27 2010, at 14:48)

Nice app...

Here is a more googley version though :)

"CallTrack" syncs all of your call logs up to your google calendar. I recommend creating a special calendar just for this.

"SMS Backup" Sync all of your sms/texts up to your gmail account with a label of "sms" or something. Searchable now and exportable later.

[link]

From: Mike (Apr 27 2010, at 18:22)

ProgressBars ... aren’t that flexible (for example, it’s hard to have any color but yellow)...."

They learned this from Apple. If you want consistent UI you need to make it more work for the developer to deviate from the standards.

[link]

From: Tony Fisk (Apr 28 2010, at 07:20)

Your next assignment(?):

http://www.worldchanging.com/archives/011114.html

(Bump might come in handy too)

[link]

From: Sam Penrose (Apr 29 2010, at 11:33)

"This project is largely TDD-free. Mea maxima culpa; I have no excuses. There is work going on to make TDD easier and more comprehensive for Android app developers ..."

The clause following "I have no excuses" would appear to be ... an excuse, and a pretty good one. Which is neither here nor there except that it begs the question of why "mea maxima culpa" is appropriate, as opposed to something more along the lines of your thoughts here: http://www.tbray.org/ongoing/When/200x/2009/06/23/TDD-Heresy .

A modest proposal: instead of alternating sin with church-going, how about leading us away from churches and towards a more modern model for professional organization? My current favorite candidate: Greg Wilson's work on Evidence-based software development: http://www.slideshare.net/gvwilson/bits-of-evidence-2338367

[link]

From: Gordon J Milne (Apr 29 2010, at 14:58)

Well, if you don't want to use Netbeans any more and Eclipse isn't the one for you, I am sure you could give JetBrains IDEA a try out. I was an Eclipse user before I switched over a few (5) years ago.

They even have a Community Edition you can use if you, or your employer, cannot afford the capital outlay this month. :-)

Mind you, I would have thought Google would have a site license or two around the place.

[link]

author · Dad · software · colophon · rights

April 25, 2010
· Technology (77 fragments)
· · Android (56 more)

By .

I am an employee
of Amazon.com, but
the opinions expressed here
are my own, and no other party
necessarily agrees with them.

A full disclosure of my
professional interests is
on the author page.