There are a lot of versions of Android out in the wild at the moment. The latest being the Jelly Bean up-date (4.2) and the earliest (worth targeting) is Froyo (2.2). As a developer, you always want to be sure that your application uses the very latest features. From a commercial perspective your application needs to reach the widest possible audience. Fortunately for us, these two are not mutually exclusive.
There are a number of neat tricks built into Android to enable us to do both. These are:
- The support API’s
- Version support in the resource system
- Version identification in the code
- Plain old Java reflection support
There is lots written on the specifics of these but for now, I want to focus on the big picture. To use new features and still work on old devices the developer needs to take the following steps:
- Build the application with the latest version of the API
- Configure the manifest
- Enable the Holographic Themes where available.
- Introduce conditional code to protect new API functionality
1) Build the application with the latest version of the API. You can’t access the new versions unless they are available to your code.
2) Configure the manifest. Specify the minimum API version you support as well as the optimum API to use with your application.
<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="16" />
3) Enable the Holographic Themes where available. If you want to use features from the latest API such as the Action Bar (and you need to!) then you have to use Holographic themes. The problem is that these do not exist in the old versions of the API.
If you specify a Holographic theme in the manifest:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/android:Theme.Holo.Light" >
You will get an error on devices with an API version of less than 11 because the theme
Theme.Holo.Light is not defined.
The solution is to specify your own theme in the manifest:
<application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >
The define that theme in the resource system. In res/values/styles.xml (create one if it’s not there) specify your theme with a non-holo parent:
<style name="AppBaseTheme" parent="android:Theme.Light"></style>
In res/values-v11/styles.xml (create one if it’s not there) specify your theme with a non-holo parent:
<style name="AppBaseTheme" parent="android:Theme.Holo.Light"></style>
The result of this is that if the API version is less than 11 your application won’t try to use a Holographic theme and hence won’t cause any errors. Above 11, the Holographic theme will be used correctly.
4) Introduce conditional code to protect new API functionality. Everywhere your code uses an API call which is not available in your minimum API version (as specified in the manifest) you need to prevent the call being made if the method is not available. There are a variety of nice tidy tricks that can be used here but they can be summarised as:
- Use the Java Reflection API to determine if the feature is available
- Check the API version by querying Build.VERSION.SDK_INT
Both of these techniques are straight-forward but for your initial attempts, I’d suggest using the
Build.VERSION.SDK_INT in simple
if tests. Once you’ve convinced yourself it all works, you can move on to reflection based wrapper classes.
If you keep these simple points in mind, backward compatibility on Android is easy.