Android build target – a controversy

Author is a professional software developer providing android development services. More info here.

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:

} 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 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 :)

Be Sociable, Share!

3 thoughts on “Android build target – a controversy”

  1. 1. I can say that both statements state almost the same thing, just phrased a bit differently.
    It is easy and falls down to simple decision on which features you want to use in your application.
    Then you should understand and know which is the lowest version that supports these (yes painful :) ). This way you are telling to android SDK to include just these classes and not include newer options, as well this instructs the application how to behave with the integrated android features at runtime.

    E.g. menu button existed before honeycomb and then in newer versions it is supported by “soft menu button”. Since this is not in design guideline anymore in order to instruct your app not to show it, you will have to set targetSDK=”11″ (or up).

    2. Thing with async tasks is bad, especially because it was promoted and there is not a very good replacement for it (you can always use Services.. but…).. So the best answer is to abstract away and use your own logic which will check which version your app is running and use the proper code, or use some of the great libraries out there like aquery.

    And there are much more problems with this backward compatibility, but then again this always arises when you want to support a lot of devices and a lot of version. (Apple though is very easy, simply go with latest ones, and do not think of backward compatibility a lot – which is possible if you are in a constraint environment, one cage where everybody wears the same t-shirt 😀 ).

    And the only way to know if your app is crashing is to test on multiple versions ( is very nice helper). But hey, when doing some cutting edge cool stuff for the cool kids with new phones and as well when you want to support the worker class citizens with their ZTEs you have to roll up your sleeves :)

    What I did not find is an easy way to know upfront which feature in Android manifest will cut out which devices in the market.
    E.g. in one app I had

    A code had a cool fallback which checked this and when tested app worked on devices with and without autofocus. The problem occurred when the app was deployed to Play store and I realized that there are a lot of devices which were excluded from delivery list. It took me some time to realize that it was this line. So be careful when you declare this features. They are informational only for Play store though, they are not checked when you install directly from .apk file.

    So as you can see Android development is a lots of fun! It makes you a true man! >:)

  2. Great response! I don’t know about aquery and I’l check it out ASAP. BTW this stupid commenting system removed part of your answer because of the formatting or something. I guess it was something like “uses feature” in android manifest but without “required=false”…

    I think you have a really god point there. Would it be so hard for google to make a webpage where you can upload your manifest and see exclusions and reasons for them…

Leave a Reply

Your email address will not be published. Required fields are marked *