Backward Compatible Android Apps
This codelab will walk you through the steps of building an Android app with a consistent user experience on devices ranging from tablets running the latest version of Android back to simple handsets running Android 2.2 (API level 8).
We’ll cover the following topics:
- Action Bar
- Fragments
- Loaders
- Resource switching
Step 1: Requirements
This is an intermediate-level code lab and expects a familiarity with creating Android apps.
Please ensure you have the following software installed, can create a new Android project, and run it in the Emulator or on your Android device:
In addition to this we will be using the ActionBarSherlock third-party library. Please download version 4.1.0 of the library and unzip it somewhere on your computer.
Step 2: Project Setup
We will start with an application created for Android 4.0.3 (Ice Cream Sandwich, API level 15) and extend support back to Android 2.2 (Froyo, API level 8).
- Unzip the file somewhere on your computer
- Import the project in Eclipse by choosing File → Import → Existing Project into Workspace
- Choose Next, specify the location you extracted the sources to, and choose Finish
- Build the app and deploy to an ICS+ device or emulator
- Create, edit and delete some notes
- Add the widget to your homescreen
- Read through AndroidManifest.xml and get acquainted with the components that make up the application
- Open this project which provides diffs for each step of this lab
Step 3: Become backwards compatible
Change the minSdkVersion attribute in AndroidManifest.xml to allow the app to be installed on API level 8 and newer devices.
Run Android Lint to look for errors
- Alternate Instructions
- You will see many ‘Call requires...’ errors, we will spend the rest of this lab resolving these!
- Open UiUtils#setActivatedCompat.
- Observe that this functionality will only be called on API 11+ but there are still Lint errors
- View the quick fixes offered by Eclipse (hover over the error or place the text cursor on the error and press ⌘+1)
- Select ‘Add @TargetApi(11) to setActivatedCompat’
At the end of this step you should see ~80 Lint errors (depending upon your ADT setup)
Step 4: Use API gating
Some new functionality just cannot be backported so we need to gracefully degrade functionality when running on older platforms. The StackView widget is one example of this. To remove the widget on older platforms:
- Add a new folder to your project: res/values-v11
- Copy bools.xml from res/values to res/values-v11
- Set the preHoneycomb and postHoneycomb boolean resources
- Remember, the resource system will only use these values when running on a Honeycomb (API 11) or later device, so preHoneycomb and postHoneycomb should reflect this [learn more]
- In AndroidManifest.xml set the enabled property of the StackView widget’s service and receiver to @bool/postHoneycomb to disable them on pre-Honeycomb devices
- This technique of conditionally enabling or disabling application components only works for values that switch on API level. You would not be able to conditionally disable components based on screen size, for example.
- Edit WidgetProvider#updateWidget, add a condition to only update if running on Honeycomb or higher. Hint: Use the UiUtils class.
- Add @TargetApi(11) to both WidgetProvider and WidgetService classes as we have now guaranteed that they will not be called on earlier platforms.
- Move the StackView widget layout resources to a folder where they will only be used on Honeycomb+ devices
Bonus:
- Add an alternative widget that is only available pre-Honeycomb
At the end of this step you should see ~75 Lint errors (depending upon your ADT setup)
Step 5: Use the Support Package
Google provides a Support Package which includes static implementations of key functionality so that you can use it on older platforms. Go ahead and add it to your project.
- Right click on the project then choose Android Tools → Add Support Library
Now that we have added the Support Library to the Honeypad project we can start using it. Support classes aim to be API compatible with the platform implementations. We need to go through the project switching to use the Support Library:
- Note that Lint will also flag problems with the Action Bar that we will not fix in this step.
- Eclipse pro-tip: Ctrl+Shift+O / ⌘+⇧+O to Organize Imports
- Change activities to FragmentActivity
- Change fragments to android.support Fragment (and ListFragment)
- Change getFragmentManager calls in activities to getSupportFragmentManager
- You would do the same for getLoaderManager calls in activities, but we only use Loaders in fragments, which automatically use the support versions of loader manager
- Change FragmentTransactions to android.support FragmentTransactions
- Change LoaderManager, Loader, CursorLoader, SimpleCursorAdapter references to android.support (only NoteListFragment)
Bonus:
- Add a ViewPager to implement swiping between notes
- Use TaskStackBuilder to add correct navigation behaviour
- At the end of this step you should see ~10 Lint errors (depending upon your ADT setup)
Step 6: Use ActionBarSherlock
ActionBarSherlock [ABS] provides a back port of the Ice Cream Sandwich Action Bar for devices on Eclair and above.
- Import ABS into your workspace
- Choose File → New → Android Project → Create project from existing source
- Locate and choose the “library” subdirectory of the unzipped ActionBarSherlock download.
- Change the Project Name to ActionBarSherlock
- Add the Support Library to the ABS project
- Right click on project and choose Android Tools → Add Support Library...
- Ensure that it is building against API 15 and as a Library project
- Right click on project and choose Properties → Android
- Eclipse protip: select the project and hit Ctrl+I / ⌘+I)
- Ensure that Build Target is API 15 (Android 4.0.3)
- Ensure that ‘Is Library’ is checked
- Add the ABS library to the Honeypad project as a dependency
- Right click on Honeypad project and choose Properties → Android
- In the Android preferences, press Add in the Library section and choose ActionBarSherlock.
Now that we have added ABS to the Honeypad project we can start using it. ABS aims to be API compatible with ICS. We need to go through our project and switch to using ABS:
- Change your application’s theme (res/values/themes.xml) to inherit from Theme.Sherlock.Light.DarkActionBar
- Change activities to SherlockFragmentActivity
- Change fragments to SherlockFragment (and SherlockListFragment)
- Change Menu, MenuItem, MenuInflater & AcitonMode to com.actionbarsherlock types
- Change getActionBar and getMenuInflater calls in activities to getSupportActionBar and getSupportMenuInflater
- Change getActivity to getSherlockActivity where necessary
Bonus:
- Add a ShareActionProvider to each note
At the end of this step you should have cleared all Lint errors :-) Deploy the app to a Froyo phone or emulator to verify.
Step 7: Profit