Android build target — a controversy

Here is a very good example why are android devs pissed off most of the time (you can find another in this post). Lets find an answer to this simple question: “What version of android should you build your project against?” I claim this should be set to maximum version your app is supporting (the latest existing one obviously) and a colleague of mine, a respectable senior developer, claims it should be a minimum version your app is supporting. And we are both right because android resources say one thing here and another there.

Why do I need newer API in the first place? Well, as most of the apps do, we are using AsyncTasks to download a lot of images for the first screen of the app (similar to Google Play first screen). Off course I would like to run these tasks in parallel so the smaller images won’t wait for a larger download to finish. I feel that this is a good UI pattern — to show things as quickly as you can. But here is the typical android situation (quote from AsyncTask class documentation)

When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.

So it was originally serial, but then they switched it to parallel and then again they switched it to serial. So what to do if you want your tasks to always go parallel and you want to support versions 2.2+ (current best practice recommendation)? I quote again:

If you truly want parallel execution, you can invoke executeOnExecutor(java.util.concurrent.Executor, Object[]) withTHREAD_POOL_EXECUTOR.

So a simple code snipet will make this happen, one possibly similiar to the folowing:

if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
task.execute();
} else {
task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params);
}

But in order to compile this code you’ll obviously have to set build target at least at honeycomb version. If you really don’t want to bring up build target then you’ll have to abandon async tasks and implement your multithreading in some other way.

If you are afraid that using methods newer than minimum sdk you are supporting could break your code you should know that it most certainly can. But you protect against it with if(hasSomeVersion) then XXX else YYY. I don’t like this kind of programming any more than the next dev but I strongly believe you should use the best code (feature, hardware, whatever) available on the current device and fall back to less powerful stuff on devices without newest android version, or autofocus, or whatever. I can almost hear some of you saying — “Yeah, but what if I forget that if statement?”. Well they got you covered (by they I mean Eclipse and Lint). Whenever you have some code from newer version than your minimum supported version (in upper snippet that would be on lines 1 and 4) the compiler is going to give you a nice red error. You will have to suppress this error with an annotation effectively saying “Yes, I am aware of that and I’ve taken care of things”. I think that’s about as far as tools should go protecting you from yourself.

I’ve spent considerable time investigating and I haven’t found one good argument not to set higher build target on your project. Just to be on the same page here, I’m talking about version of android you are using to compile your code, not the meaningless android:targetSdkVersion attribute that goes in the manifest. The build target has nothing to do with your project, versions you intend to support, etc. it is just configuring your environment (i.e. Eclipse) what to compile against. In case you’re wondering you can find this piece of configuration in your project.properties file along with target android library project references and the like.

If you check on offical android developer page, written by the very people building android you can find this quote:

When you are developing your application, you will need to choose the platform version against which you will compile the application. In general, you should compile your application against the lowest possible version of the platform that your application can support.

But if you pay attention while creating new android project in Eclipse, you will get completely different advice for your money (tooltip is for “Compile with” selection box):

This dialog comes form ADT plugin I believe, and the folks from google are developing ADT plugin AFAIK.

So there you go: one horse, one mouth but two opinions :) What do you think about this?

1. What build target do you specify on your project and why?

2. If it is minimum supported version and you want to do parallel downloads as previously described would you
a) set a higher build target
b) find another way, like handlers and threads, to acomplish the same thing with staying on minimum build target

Answers will win you android badges so don’t be shy :)