Sunday, May 29, 2011

Android Fragmentation and Build/Target API Level

Android is a great platform for mobile apps. However, Fragementation becomes a problem when Google’s releases API and new features at a lightning speed, that is, much faster than hardware vendors’ ability to patch their devices.
See Google’s official platform distribution.

 

Android Build Option Matrix

Here’s a table that shows the total accumulated device coverage for each API level. Device coverage should be one of the key factor for picking a target API for Android development.

Build API Level Distribution Device Coverage
1.5 3 1.3% 100%
1.6 4 2.0% 98.7%
2.1 7 15.2% 96.7%
2.2 8 55.9% 81.5%
2.3 9 0.6% 25.6%
2.33 10 23.7% 25%
3.0 11 0.4% 1.3%
3.1 12 0.7% 0.9%
3.2 13 0.2% 0.2%

Note: Base on data available on 8/01/2011.

Base of on the device coverage alone, 2.1 is the best choice to date. Note that platform 1.6 have similar coverage, but lacks the all important “AccountManager” feature.

So is 2.1 the best choices? Are we forced to develop on an API, that is, 7 iterations old? Can we build an app with the latest API and yet able to run on lower API devices?

Yes, there’s a way.

Work Around

There’s a well known work around among developers, but it’s tricky and must be exercised with care.
If you build an app with a higher level API, you can still deploy that to lower level devices, except that you must not make higher API calls when running on lower API runtime.

Configuration Setup:

In side the app AndroidManifest.xml:
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="12"/>
minSdkVersion - Specify min version to be the lowest API you want your app to run with.
targetSdkVersion - Specify the latest api version you want to compile your app with.
When you build the app, go ahead and build with the latest SDK.

Code Workaround Example:

   1: public void activityTransition(){
   2:  
   3:     if(android.os.Build.VERSION.SDK_INT >= 5){
   4:         overridePendingTransition(R.anime.enter, R.anime.exit);
   5:     }
   6:  
   7: }

In this example we check the current API level, if it’s greater or equal to 5, we go ahead and call overridePendingTransition, which is only available for API 5+.

However, If this is handled incorrectly, your app will crash. Some variety of runtime exception will be thrown.
 

AQuery

A simpler solution is just use a library. AQuery provides an easier way to handler these cross-api-levels calls. It abstract away all the details and make sure the operation fallback gracefully when a feature is not available.
Here are some examples.

Enable hardware acceleration:

   1: @Override
   2: protected void onCreate(Bundle savedInstanceState){
   3:         
   4:         //My API level 4 onCreate setup here... 
   5:         
   6:         AQuery aq = new AQuery(this);   
   7:         
   8:         //Enable hardware acceleration if the device has API 11 or above        
   9:         aq.hardwareAccelerated11();
  10:         
  11: }
Set activity transition animation:
   1: @Override
   2: protected void onCreate(Bundle savedInstanceState){
   3:         
   4:         AQuery aq = new AQuery(this);   
   5:         
   6:         //Override activity transition for device with API level 5      
   7:         aq.overridePendingTransition5(R.anim.slide_in_right, R.anim.slide_out_left)
   8:         
   9:         //API level 4 onCreate setup here... 
  10:         
  11: }

Handling cross-api-level calls is just one of the feature available from the open-source AQuery library. Read more about AQuery here.

Feedback

Any feedback is welcomed!

What aspect of Android development you want us to blog about?
Leave a comment below and subscribe to the blog. :)