I’ve been developing iOS apps since the end of 2010, so have only ever seen the world of Android from a distance. Where I’m from, you hear a lot of talk about the problem of fragmentation on Android. Whereas the adoption stats for new versions of iOS are pretty impressive (apparently iOS7 hit 33% iOS market share in just 24 hours, and 58% after one week) the situation on Android looks very different, with the second most popular Android version remaining Gingerbread, released in 2010.
With my iOS hat on, when PrayerMate launched on Android earlier this year, I assumed it would be far too much hassle for one independent developer working in his spare time to take on this fragmentation issue, so I decided to support only Honeycomb upwards – a major OS update which introduced some significant new changes to the core Android UI.
But what they don’t tell you over in iOS developer world is that the Android ecosystem provides some pretty impressive tools to make supporting older Android versions really easy. Let me give you a quick overview of just three reasons why adding support for older phones isn’t nearly as hard as you might imagine:
1. Compatibility-aware compiler
When you set up your Android project (I use Eclipse) you specify the minimum version your app supports. Out of the box, the compiler knows exactly which API level each feature was introduced at, and will throw a compiler error if you try to use functions that are too modern for the versions you claim to support. If you use conditional statements to alter behaviour by Android version, then you can use attributes in your code to say what API level a given function is designed to run against, to disable these compiler errors on just those bits of code. It also warns about deprecated APIs so that you can use more modern alternatives where appropriate.
This makes the situation so much easier than the native state-of-affairs on iOS. It wouldn’t surprise me if there was some way to figure out how to make XCode throw such compatibility errors, but out of the box you get no warning whatsoever if you use functions introduced in an iOS version later than the minimum one you hope to support, and the only way to discover this is through thorough testing and waiting for the crashes to happen (which needless to say is not very scalable!)
2. Compatibility support libraries
Another seriously impressive feature of the Android SDK is the compatibility support libraries. In many situations, where a new API has been introduced, the SDK then goes and adds an alternative implementation that conforms to the same method signatures but which ports the new functionality back so that it also works on older OS versions. This avoids the need to have lots and lots of conditional branches running separate codepaths on separate Android versions, and instead means you can just write one lot of code that works everywhere.
Ok, so this one isn’t native to the Android SDK (although a very similar library is) but there’s a great open source project out there called ActionBarSherlock which lets you add the “action bar” UI paradigm introduced in Honeycomb even when running on older Android versions. It requires a minimal amount of setup, and works almost identically to the real action bar. So, again, rather than having to invent two separate user interfaces depending on the Android version, you can have the same functionality running everywhere.
In conclusion, the Android fragmentation problem doesn’t seem nearly so scary to me as it once did. I managed to get PrayerMate to support Android versions all the way back to Froyo (v2.2) in a single (pretty relaxed) weekend, and because of support from the compiler I can be pretty confident of not having missed anything.