Reputation: 9138
I have noted in the Android Market that many popular applications have backward compatibility to much earlier versions of Android. E.g.
Evernote - 1.6
Faceobook Messenger - 2.2
These applications look and work great but how can they do this and support much older API levels? Are they only using API features that exist in the lowest supported OS version, hardly? I'm assuming they must be using some features of the later API levels to provide a great UI and featurelist.
I can see two possible solutions:
Use Min/Target API levels in build. Then through code you check the OS version and implement the features using a supported method and degrade gracefully. This seems like a lot of work.
Have multiple app versions targeting various OS versions. E.g. A release for 2.2 and another for 4.0. Is this possible?
The reason for asking is I am planning a new app that should support 2.2 but I fear I may require API features that are only available in later releases? Should I just target 2.2?
EDIT: Also, what role do Compatibility Libraries play? Is this the key?
Thanks.
Upvotes: 5
Views: 4283
Reputation: 2594
We (Evernote) do extra work to support 1.6 and use as many new API's as we can. The main problem with supporting 1.6 is that Dalvik does a greedy search on your classes. This makes it impossible to use code like
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
prefEditor.apply();
} else {
prefEditor.commit();
}
Because it would throw a class verification error. This is caused when dalvik sees your method and tries to access it at runtime.
Instead you need to use a helper class to instantiate the appropriate class for the SDK. Yes this is much more work
public abstract class SharedPreferenceEditor {
private static SharedPreferenceEditor sInstance;
public static SharedPreferenceEditor getInstance() {
if (sInstance == null) {
/*
* Check the version of the SDK we are running on. Choose an
* implementation class designed for that version of the SDK.
*/
@SuppressWarnings("deprecation")
int sdkVersion = Build.VERSION.SDK_INT;
if(Evernote.DEBUG)Log.d("SharedPreferenceEditor", "sdkVersion=" + sdkVersion);
if (sdkVersion < Build.VERSION_CODES.GINGERBREAD) {
sInstance = new CommitSharedPreferenceEditor();
} else {
sInstance = new ApplySharedPreferenceEditor();
}
}
return sInstance;
}
public abstract void save(SharedPreferences.Editor editor);
}
Then you have one for the gingerbread + api level
public class ApplySharedPreferenceEditor extends SharedPreferenceEditor {
public void save(SharedPreferences.Editor editor) {
editor.apply();
}
}
and one for the < gingerbread level
public class CommitSharedPreferenceEditor extends SharedPreferenceEditor{
public void save(SharedPreferences.Editor editor) {
editor.commit();
}
}
I'd recommend supporting 2.1 and up so than you can take advantage of the improvements to Dalvik and use the first example I listed.
Upvotes: 15
Reputation: 22361
There's a few things you can do in order to support older versions of the Android platform while still taking advantage of the features in newer versions. The Android Training guide Supporting Different Platform Versions outlines a few and has sample code showing you how to implement them.
In no particular order:
You can set a seperate "minSdkVersion" and "targetSdkVersion". minSdkVersion is the earliest version of Android you want to support. targetSdkVersion is the the latest version you've tested on, and the most recent set of features/behavior you intend to include in your app.
You can check system versions at runtime, and only implement a feature if the requisite Android Platform version is running on the device. This looks like:
private void setUpActionBar() {
// Make sure we're running on Honeycomb or higher to use ActionBar APIs
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ActionBar actionBar = getActionBar();
actionBar.setDisplayHomeAsUpEnabled(true);
}
}
The support library (also commonly referred to as the compatibility library) contains features from new versions of Android, written in such a way that you can include them in your application, and they'll work even on older versions of Android. For instance, Fragments were introduced in Honeycomb (Api 11). But you can use the version of Fragments included in the support library on devices going back to Donut (Api 4)!
Upvotes: 1
Reputation: 1513
There are a few different strategies for mixing backwards support with the latest features. There's lots of references within the Android documentation, but maybe start here: Backward compatibility for Android applications.
But in general, I would strongly recommend you avoid publishing multiple versions if possible. Use your app's manifest to target a suitable range of OS versions and code accordingly.
And yes, there's also the standard Android Support (Compatibility) Library. Generally the purpose of the compat libraries is to allow your app to use some of the latest OS features while providing some comparable implementation for older platforms. You should definitely look into this.
There's also a few great 3rd party compatibility libraries. Here's a few I've used in my projects and definitely recommend:
Note that NineOldAndroids is actually included within ActionBarSherlock.
Upvotes: 6