Roger's Blog | Well, I think it's interesting.

Archive for July 2010

With CodeStock behind us I thought it would be a good idea to do a little post-mortem analysis of the CodeStock Android app to see what went right and what went wrong.

What Went Right

  • Scanning a QR code to link My Sessions with the web site’s Schedule Builder. I didn’t know ahead of time that the web site would generate a QR barcode to access the user’s schedule. I had started designing a layout to prompt the user to enter their website id but scanning the barcode is much more in keeping with the Android mantra of a seamless device experience. There were a few people that mentioned before and after the conference that they didn’t know you could do that with Android (having one application call another, unrelated app that returned data to your app.) Definitely cool.
  • Downloading speaker photos and caching them to the SD card. Downloading the photos on a background AsyncTask. and saving them to a directory on the SD card avoided having to download them multiple times. The trickiest part was figuring out how to avoid having the photos show in the device’s Gallery app. The solution was to add a file named “.nomedia” to the directory where the photos are stored. The file could be zero-length; it just needed to exist. It was also a surprise how flexible the TextView widget is. It can hold much more than just text by using Spannables and Editables. It’s something I want to spend more time understanding.
  • Parsing speaker bio’s and session synopsis. Many of the speakers originally uploaded their bio’s and their session’s synopsis with embedded Html formatting. A couple of speakers apparently used Save as Html from Microsoft Word and just pasted the document into the web site, complete with all the Microsoft object model junk. When I started the project I fully expected to have to write all sorts of nasty code to parse out this junk. Turns out the TextView widget combined with the android.text.Html and the android.text.util.Linkify classes is fairly forgiving of what you feed it. The Html.fromHtml() method will take nasty html and return something sensible for TextView to display while Linkify.addLinks() will scan the contents of the TextView and turn recognized text into hyperlinks. It was fairly simple to add a filter that extended Linkify.addLinks() to recognize Twitter handles and to add a handler to Html.fromHtml() to teach it to handle html tags it didn’t natively support. For a complete picture, see the code in DisplaySessionDetailsActivity.java, especially the displaySessionInfo() method and the MyTagHandler nested class.

What Went Wrong

  • Image icons on the start screen suck. No other way to state it. I’m not an artist and can’t draw to save my life (I’m so jealous of people that can create nice artistic images.) That’s one of the reasons I haven’t done much with ASP web pages because I can’t come up with a layout that doesn’t look like it was done by a developer.
  • Database access is fragile. The coordination of opening and closing the database was tricky to get right without the OS throwing a “Database leaked” exception and any changes to the app that involved db access would break the access. As I mentioned in my presentation you don’t have to use the “extending SQLiteOpenHelper” pattern. I’m going to try to refactor it to use some sort of singleton pattern, perhaps opening the database at app startup and closing it only when the app completely exits.
  • Handling orientation changes while AsyncTasks are running is fragile. Because Android basically kills then restarts your activity when the device orientation changes creating and showing a ProgressDialog in AsyncTask.onPreExecute() then dismissing it in AsyncTask.onPostExecute() can cause a Window Leaked exception. What happens is the recreated Activity knows nothing about the AsyncTask and the AsyncTask has an invalid reference to a non-existent activity. I changed My Sessions to download the Schedule Builder data using an AsyncTask but had the activity (MySessionsActivity.java) own the ProgressDialog instead of the GetScheduleBuilderSessions AsyncTask class. The class still sets the text in the ProgressDialog and shows and dismisses it but the dialog is owned by the activity. It seems to work fine and is much simpler than the mess in StartActivity.java.

What’s Next

The CodeStock data API will be staying up for at least a while so I plan to correct and refactor some of the above issues. I’m also planning to target Android 2.1 and higher so I can do some of the things I wanted to do but couldn’t because I didn’t want to leave the 1.5 and 1.6 users behind. I also have another idea that I’ll keep to myself for the moment. I’m also planning to port the application to Windows Phone 7. I do plan to blog about most of this.

Forty-nine people downloaded the app (28 of you still have it installed) and for the most part the comments were very nice. Several people come up to me during the conference to say they liked the app and used it all the time. Thank you for the kind words. If Michael wants me to I will definitely do another one for next year.

No tags

Theme Design by devolux.nh2.me