I just read via engadget that Google is giving away Xoom tablets to attendees at the GDC. Originally, giving away free hardware was a great way to get devs to play around and build cool apps, but this cute gimmick has run it's course. People now expect to get free hardware from Google, and since the value of the hardware tends to exceed the ticket price of the conference, everyone and their mother are signing up.
I had planned on going to Google IO this year, and was patiently waiting for registration to open. I made the mistake of walking across the street to Panera for lunch with some co-workers, and by the time I got back registration had already opened and closed. Who cares you say? Maybe I'm just bitter because I wasn't one of the lucky few that made it.
Sorry, but there is more too it than that, dev conferences are supposed to be for developers. It's a chance to learn new stuff and get some important networking done. The job I have now at TuneWiki, in fact, came from a random encounter I had during a lunch break at a previous Google IO. Signing up for a Google IO event, should not be the online equivalent of going to Walmart on Black Friday.

Yes, I'm also aware of the Google IO Pre-Sale VIP list, which supposedly was to give deserving developers a guaranteed spot at the conference. Except that it failed, miserably, imo. Using myself as an example, I attended the very first Android event on the Google campus. I worked on two android projects that won top 10 placement in the first ADC (find someone else who can claim that). I attended the first device readiness event before the G1 was released. I sat front row at the G1 announcement press-conference as a special guest of T-mobile. My current work efforts not only include TuneWiki, but also the media player that's baked into every motorola device (before US carriers replace it with their crapware). Despite all this, I did not receive a VIP pre-sale invite. And if I didn't get an invite, you can bet your ass there are plenty of other deserving developers who didn't either.
In short, Google, I am disappoint.
UPDATE: For the record, I already have stacks of android devices on my desk, including unreleased evaluation devices, so anyone who thinks that I'm butthurt over not getting a tablet is only re-enforcing my point. People are now assuming getting a device is the reason I want to go to these events.
Wednesday, March 2, 2011
Google, please stop giving away hardware at your events!
Sunday, May 30, 2010
The limitations of AsyncTask
AsyncTask is a fine API, it's been said that it "holds your hand", and makes performing background operations painless. It pulls this off so well in fact, that I see people overusing it in situations where it's not really appropriate.
It's particularly unsuited for situations when you have a multiple tasks to perform concurrently. Imagine an Activity that needs to download about 30 small images from a remote server, and update the UI as these become available. AsyncTask uses a static internal work queue with a hard-coded limit of 10 elements. That means if you were to create an AsyncTask instance for each image, the work queue would quickly overflow and many of your tasks would get rejected. The best solution in this case is to create your own ThreadPoolExecutor instance that uses a queue that's large enough to hold all your tasks, if you need an unbounded queue, a LinkedBlockingQueue will work just fine.
Another severe limitation is that an AsyncTask can't survive your Activity being torn down and recreated on the other side. Even if you pass it to the new instance via onRetainNonConfigurationState, the internal Handler inside the AsyncTask is still going to be stale and it's not going to behave correctly. This is important to consider, and the Android documentation makes no mention of it all. I've already blogged this scenario in detail, so I won't flog a dead horse here.
There are a few other minor issues, such as the fact that you can't change the background threads execution priority. It's hard-coded to a low priority, which granted, is the sensible default. Also, exception handling is not very well supported.
So just to reiterate, AsyncTask is a nice API, but you should understand it's limitations and apply it appropriately. If you're serious about writing mobile apps, then you're going to need a few more tools in the toolbox to get the job done.
Saturday, May 22, 2010
Android 2.2 Highlights, A developer's perspective
Android 2.2 is the most significant upgrade to the Android OS that I can remember. Chock full of new goodies for both users and developers.
I thought I'd just do a quickie post to highlight the features for developers I'm most interested in.
1) Android Cloud to Device Messaging - this is one feature that's been sorely lacking from the Android platform and it's a welcomed addition. The demo at Google IO demonstrated how you can push a message to a device in real time, and have it fire off an Intent which can kick off any number of interesting and yet to be dreamed of services. This also opens up a new way for devices to communicate with each other in real time over the internet, I expect interesting things to come of this.
2) Android Application Error Reports - logging exceptions remotely that occur on a users device is a very useful thing and every mobile company I've worked at has done this in some form or another. The typically way to do it is to override the default exception handler and replace it with something that will log the exception. I myself just started building a new GAE project for this a few weeks ago http://github.com/jasonhudgins/Remote-Incident-Logger. The initial usefulness of this will be somewhat limited, due to the fact that many devices are going to be running older versions of android for the foreseeable future.
3) Stagefright media framework - I don't know much about Stagefright, I'll admit that right off the bat, what I do know is that I'm dreadfully tired with the limitations of the current MediaPlayer framework, and I'm really hopeful this can serve as an improvement / replacement for the API's we've been using up til now.
And lastly, I'd also like to mention the new support for Android Library Projects that are available in the newest SDK tools (SDK Tools r6). We will finally be able to share common resources between multiple projects, and since it's just build time magic, these new library projects are going to be backwards compatible with older platform versions.
Wrapping up, I'm really excited about android 2.2. Google has really raised the bar with this release, and it's going to be interesting to see how other mobile technologies evolve in response to this.
Wednesday, March 31, 2010
A Simple ProgressBar Tutorial
I came across another ProgressBar tutorial a few days back posted on helloandroid.com, and while it's certainly good enough to get someone started, it doesn't really go into any detail about how your non-ui thread should work, and how it should gracefully handle Activity restarts and what not. It uses a message handler to send notifications to the ui thread, but what if the Activity is paused and the message handler becomes stale?
So I'm taking this as a good opportunity to follow up on my previous Rebel Without A Context post.
The code is fairly short, so I won't go into a line-by-line explanation of it, but the general idea is that you have your own Thread implementation that maintains state, and you pass it from the old activity to the new activity via onRetainNonConfigurationInstance(). Also rather than updating the UI directly by sending a message from the background thread, the UI thread actively polls the background thread every 50 milliseconds with a handler loop, which updates the progress bar as necessary.
With this kind of approach, you can for example, flip orientations back and forth gracefully with no stale handlers or leaky window exceptions.
Saturday, March 20, 2010
HTTP Connections revisited
In a previous post entitled, HTTP connection reuse in android, I tossed out a code snippet for an HttpClientFactory that would spit out a DefaulHttpClient implementation suitably configured for re-using already open HTTP connections to serve multiple requests across multiple threads.
My hasty implementation from that post leaves a few things to be desired. Primarily, it's a singleton implementation which can lead to some problems. Since it's effectively a global resource, doing things like modifying the time out value, or forcibly closing the connection manager (as one commenter pointed out), could lead to the HttpClient to be in an invalid or undesired state when reused at a different time or a different part of your application.
So here's a simplified version without the singleton garbage:
The ideal place to use something like this is when you want to download multiple items from a single remote source, for example, if I needed to download a bunch of thumbnails to be displayed in a ListView, I could have a thread pool downloading images concurrently and all sharing this one HttpClient instance, reusing HTTP connections as they became available (all managed inside the HttpClient)
Friday, February 5, 2010
Rebel Without A Context
The scenario is common enough. You want to implement some task in a background worker thread, like fetching data from an HTTP server or whatnot, and then at a future point the UI needs to be updated, based on whatever has or is happening in the worker thread.
So here's your naive Thread/Runnable implementation :
And there you have it. That's the most succinct implementation of the anti-pattern many people use. And certainly I must concede my own guilt of having used it.
The problem is that your background thread, in order to update the UI, is now tightly coupled to the Activity/Context that created it. So when/if an event occurs (such as an orientation change) that causes your Activity to be restarted, your background thread will continue to happily chug along and then try to update the UI even though it's still referencing the old Activity/Context. Your app is then likely to experience leaked window exceptions and other types of nastiness.
I've seen this problem attacked in different ways, generally trying to enable the background thread to update the UI on the new Context. The droidfu library has an AsyncTask implementation called BetterAsyncTask that does exactly that.
But this isn't a perfect solution in my opinion. Imagine that an important event occurs in the background thread, one that is serious enough that the user absolutely should be informed if they continue to use the app. What if it happens in the middle of an orientation change, after the old Activity has been destroyed, yet before the new Activity is fully initialized? A quick glance at BetterAsyncTask's source suggests that the message would never get delivered:
Now before I get into what I don't like about this, I just want to say that I applaud the creators of droidfu for releasing an open source library, and I've never used it myself, but that's my five second synopsis of it's implementation. It probably works fine for a lot of people, but I demand something more robust.
The way I see it, this just doesn't escape the anti-pattern. The core point that I'm trying to make here is this:
It's your Activity's responsibility to update the UI, not the responsibility of the worker thread.
Let me say that again, your background thread should not try to update the UI. What it can and should do is track it's own internal state, and allow itself to be queried by the active Activity instance. The simplest way to accomplish this is to use onRetainNonInstanceConfiguration to pass your Thread/AsyncTask implementation to the newly created Activity. The Activity can then query the state of your thread and deal with any impending UI events that it needs to process.
A simple, but effective way to accomplish this is with a polling Handler loop running in the UI thread. Something like this will work fine as long as you remember to shutdown the loop as your activity exits.
If this isn't realtime enough for you, then another approach would be to have your Activity register listeners with your thread, much like binding to a service and registering a remote callback. In fact, that's exactly how you should think about your background thread, as a lightweight service, that is decoupled from any direct UI interaction.
And just a quick warning as I wrap up, If you go the listener route, you still must be aware that events can occur when your Activity is being restarted, and before the new activity can register another listener instance.
I hope this article helps a few of you out there, or at the very least, shows you a different approach to a common problem.
Monday, February 1, 2010
Android Sweater
We didn't want to be left out of the Android arts and crafts mania, you know, the
various android pillows and dolls, so grandma hand knitted this sweater for Maxim.