Question

I understand there are (at least) two ways to do runtime checks to ensure my code doesn't call APIs that don't exist:

But I don't understand when one technique should be used in lieu of the other. Reflection seems necessary when trying to use Android classes that may not exist, since loading such a class referenced in my code will cause a fatal error. But what about calling a method belonging to a class that I know exists? For example, on a device running 2.2 (API 8):

protected void onCreate(Bundle savedInstanceState) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO) {
        ActionBar actionBar = getActionBar();
    }
...

Is this always safe, or are there circumstances where a crash will happen? Is there any reason to check if the "getActionBar" method exists in Activity using reflection instead of using the above version check?

Was it helpful?

Solution

But I don't understand when one technique should be used in lieu of the other.

Use the first bulleted technique.

Is this always safe, or are there circumstances where a crash will happen?

First, you need to change that to HONEYCOMB, as the ActionBar class was added in API Level 11.

Beyond that, so long as you are only supporting Android 2.0 and higher, you are fine. If you are supporting Android 1.x still, you would need to rewrite your code as:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    HoneycombHelper.doSomethingCoolWithTheActionBar();
}

where HoneycombHelper is another class you write that contains your API Level 11 code (e.g., ActionBar actionBar = getActionBar()).

This difference is because Dalvik on Android 1.x would fail fast, giving you a VerifyError as soon as you try loading a class that contains an unrecognized reference. Android 2.0+ will not fail until you actually execute the statement containing the unrecognized reference, and your if test should prevent this.

Is there any reason to check if the "getActionBar" method exists in Activity using reflection instead of using the above version check?

No. Just set your build target (e.g., Project > Properties > Android in Eclipse) to a value high enough to cover everything you want to refer to, and set your android:minSdkVersion to the level you are willing to support. Anything that you try using that is newer than android:minSdkVersion will be flagged with an error by Lint, and you can add your Java version guard block (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.WHATEVER)) and the @TargetApi() annotation to get Lint to stop complaining.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top