Android’s PreferenceActivity for all API versions

I have spent the last few days learning about how to use the new Android PreferenceFragment which requires PreferenceActivity to override a new v11 (Honeycomb) method called onBuildHeaders().  Unfortunately, the documentation is not very clear how one would create a single PreferenceActivity that could play well in all versions, utilizing the newest features if you have it and avoiding an app crash on older Android versions. I encountered several solutions to this issue by creating two different activities for the two different mechanisms requiring two entries in your AndroidManifest.xml file.  Having two different PreferenceActivities means if you have library code that extends that class, you now have to duplicate it.  Then, if your app descends your library class, now has to be duplicated yet again.  The end result is … less than ideal.

Thankfully, after spending a great deal of time on the subject, I have come up with a single class solution that will work in all Android versions. A couple of the newer methods need to be found using reflection and based off of them, in addition to using the newly introduced xml file of <preference-headers>, allow for a single class solution.

First, take your old <PreferenceScreen> xml layouts and break them up into several files based on how you would like to see them categorized using the new header format.  Simply breaking them apart so that each PreferenceCategory has its own file is a good start.  For our example here,  we shall assume there are 3 such files, all in the res/xml folder: app_prefs_cat1.xml, app_prefs_cat2.xml, and app_prefs_cat3.xml

Now let us create the descendant PrefsActivity class:

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;

public class PrefsActivity extends PreferenceActivity {
    protected Method mLoadHeaders = null;
    protected Method mHasHeaders = null;

     * Checks to see if using new v11+ way of handling PrefsFragments.
     * @return Returns false pre-v11, else checks to see if using headers.
    public boolean isNewV11Prefs() {
        if (mHasHeaders!=null && mLoadHeaders!=null) {
            try {
                return (Boolean)mHasHeaders.invoke(this);
            } catch (IllegalArgumentException e) {
            } catch (IllegalAccessException e) {
            } catch (InvocationTargetException e) {
        return false;

    public void onCreate(Bundle aSavedState) {
        //onBuildHeaders() will be called during super.onCreate()
        try {
            mLoadHeaders = getClass().getMethod("loadHeadersFromResource", int.class, List.class );
            mHasHeaders = getClass().getMethod("hasHeaders");
        } catch (NoSuchMethodException e) {
        if (!isNewV11Prefs()) {

    public void onBuildHeaders(List<Header> aTarget) {
        try {
            mLoadHeaders.invoke(this,new Object[]{R.xml.pref_headers,aTarget});
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        } catch (InvocationTargetException e) {

    static public class PrefsFragment extends PreferenceFragment {
        public void onCreate(Bundle aSavedState) {
            Context anAct = getActivity().getApplicationContext();
            int thePrefRes = anAct.getResources().getIdentifier(getArguments().getString("pref-resource"),

On older Android versions, the reflected methods will be null and thus avoids calling the newer methods, using the older mechanism of adding the various preference xml files in onCreate(). In order to use the new Honeycomb (v11+) preference mechanism, we need to create one more xml file – the newer <preference-headers> xml file that ties all the category files together. The res/xml resource file “pref_headers.xml”:

<?xml version="1.0" encoding="utf-8"?>
    xmlns:android="" >

<header android:fragment="$PrefsFragment"
    android:title="Category 1 prefs" >
    <extra android:name="pref-resource" android:value="app_prefs_cat1" />

<header android:fragment="$PrefsFragment"
    android:title="Category 2 prefs" >
    <extra android:name="pref-resource" android:value="app_prefs_cat2" />

<header android:fragment="$PrefsFragment"
    android:title="Category 3 prefs" >
    <extra android:name="pref-resource" android:value="app_prefs_cat3" />

    android:title="Blackmoon Info Tech Services"
    android:summary="link to BITS blog">
    <intent android:action="android.intent.action.VIEW" 
            android:data="" />


The first three headers list the three standard category xml files we created, but you are also free to add more items as you see fit, just remember that those will only be visible on devices with Android 3.0 or later.

Now that we have our xml file and single preference activity, we can define it in our AndroidManifest.xml as usual. Note: do not use android:launchMode=”singleTop” for your prefs activity or else it will break phones using 4.0+ by never showing more than just the header list.

    <activity android:name="PrefsActivity" 
        android:enabled="true" >
            <category android:name="android.intent.category.PREFERENCE" />

We can have a menu call our prefs activity with just one line:

    startActivity(new Intent(this, PrefsActivity.class);


Now that you have a descendant class like this one, you can freely use it in all versions of Android and it will automatically use the newer mechanism where appropriate.


35 thoughts on “Android’s PreferenceActivity for all API versions

  1. Dude! Thanks! This is awesome… Just a bit of feedback: for newbies, could you include the package imports to ensure they have imported the right stuff.
    Additionally, if your minSDK<11, Eclipse will still tell you that the addPreferencesFromResources methods is depecrated.
    Is it necessary to break the PreferenceScreen into multiple parts for the Activity's onCreate? I can see why it's important for the Fragment, since we are checking for headers…

    • >…could you include the package imports…
      Since I can’t think of a reason for “why not”, sure. ;) Post updated.

      Eclipse/Lint will warn you about using the deprecated method, but just ignore the warning. We are using the method only when we have to, which is whenever we do not have v11+ style preferences and must use it, which is OK. Do not be frightened about Deprecated code when you have accounted for it, Android won’t remove deprecated methods anytime soon. If it ever did occur, you won’t even need this class anymore as you would be forced to only target newer devices. The Deprecated mechanism is there to warn you that there is a better way to handle something on the latest API version, but once you have accounted for it, you can safely ignore the warning from then on. Removing all calls to deprecated methods would only result in forcing your code to only run on newer devices — thus negating the need to be backward compatible at all.

      The reason you are breaking up the PreferenceScreens has nothing to do with Activities vs Fragments. You are breaking them up so that each preference file can be it’s own category using the new mechanism while still being able to put them all back together as one using the old mechanism — all the while not duplicating PreferenceScreen definitions across multiple files (one for old way, one for new way) which just causes bugs. If you used just a single PreferenceScreen file under the new mechanism you would see just one category listing all your preferences under it. That is fine for apps with only a few preferences, but if you have more than a few, it is visually more appealing if you separated them out into distinctive areas.

  2. I was under the impression that this code should compile with minSDK<11, but "static public class PrefsFragment extends PreferenceFragment" does not compile, because the PreferenceFragment does not exists before API level 11.

    The settings for my project currently are: minSdkVersion="10" targetSdkVersion="16"

    Maybe I am missing something…

    • Considering my projects are minSdkVersion=”3″ and targetSdkVersion=”16″, I can assure you that it does indeed compile and work on API’s lower than 11. Make sure you are using a build target of Android 3.0+ or you will run into that issue. The XML file does not tell the compiler what to use, you need to change that in the project’s properties (Project properties> Android section> Project Build Target).

      • I am having the same problem “Call requires API level 11 (current min is 8): android.preference.PreferenceFragment#”, my Project properties> Android section> Project Build Target are set to API level 16.

      • My IDE: Eclipse Helios Service Release 2
        My AndroidManifest tag: <uses-sdk android:minSdkVersion=”3″ android:targetSdkVersion=”16″ />
        My Project Properties> Android> Project Build Target = Android 4.1, API 16.
        You should see Android 3.0 or better in your project’s Package Explorer window as an included library. If you see an Android version lower than 3.0 here, you will get these “Call requires…” issues.

  3. How do you add a dialogfragment to the preferenceactivity class?Right now i’m using the compatibility package and it’s method expects a FragmentManager object of the v4 type. The getFragmentManager from PreferenceActivity returns a instead one.


    • App preferences on a single screen for pre-Honeycomb devices are typical, but definitely not the only way to do it. Official documentation tries to accomplish creating new apps across older devices, whereas my approach has been to upgrade older apps to function on newer devices. Changing the look on older phones is not always desirable. Neither way is “more correct” than the other and each approach has their pro’s and con’s. Use what works best.

  4. Can you please an idea because I can’t seem to retrieve the value of the specified preference.

    appPrefs = getSharedPreferences(“net.xiomai.LXPreferenceActivity_preferences”, MODE_PRIVATE);

    lxIDNo = appPrefs.getString(“idNoTextPref”,””);

    • There is not enough information to give you any advice. If you are expected the XML defined default value to be there, it will not be returned. You must save a value to it, supply a default in the 2nd parameter to getString() or call the static method PreferenceManager.setDefaultValues() during your Activity’s onCreate().

  5. Pingback: Binary App Dev: Apps | Preference Activity is crashing on Android 2.3

    • The Java class validation that takes place checks for the existence of all properties, consts, and methods referred to in the file regardless if they exist in dead branches or not. Putting if() statements around newly introduced methods will still throw a validation exception in older Android versions.

  6. To go. Do not look just wear Friends regulations put it nicely,Canada Goose Outlet, said Yang Xingmi intend south pacification Dong Chang chaos,Cheap Ray Bans Sale UQCHKM068, just because the money pure gold obstruction,Canada Goose Sale, so give up,Replica Canada Goose,Fashion Sunglasses Online Store HWLWOX6024 IUBY139, and Li Yao have never disagreed on that thing really the case. Yes! My master year after the establishment of the existence of the land,Christian Louboutin Shoes,Ray Ban 2013 Ne

  7. And for too reign in terms of words,Cheap Christian Louboutin, is to extract the full benefits are divided into three points.. He went to the bedside,Canada Goose Jackets, watching with tears Lee Meng said: Li Meng,Canada Goose Sale, Qin teacher’s me and you,Canada Goose Outlet, then you have heard of it if you do not live up to expectations,Cheap Christian Louboutin, then it if I do not speak Mo sea sensibilities me?. Today,Canada Goose Outlet UK, day successor probably did not drive the rest o

  8. Originally they own today will only rise toward supporting role, as well as one of the generals greatly dissatisfied, and now to have this opportunity to fight each other,Canada Goose Sale, naturally it is not easy to let go. Southern Xinjiang Lord laughed: It is so,Cheap Ray Bans Sale MZSIEZ215,Red Bottom Shoes, so we choose to break the tower when the quota,Cheap Ray Bans Sale YEPUSH296,Christian Louboutin Shoes, regardless of the level of my strength,Ray Ban Sunglasses Cheap Sale, just look a

  9. Interestingly, Yaozu revival can do?. Outcomes bath. At that time,Canada Goose Outlet, Ye Xiaofan completely mastered this person is a super assistant. Be able to get the money for himself, Gary and Mellon There Rubio naturally not refuse to see three personal accident and joy of expression to know,Cheap Christian Louboutin, thirty thousand is not a small number,Christian Louboutin Sale, can be worth three level of God Warcraft sperm nucleus,Cheap Canada Goose, especially for such a beast Rubio,

  10. Wong also fear anyone singled out.. Wang 笉 then laughed: uncle 何必谦 speech made by Johnson,Christian Louboutin Outlet, uncle of His Majesty if not open solution,Red High Heels, the hearts will be responsible zhengyang brother poetry disgrace him,Christian Louboutin Shoes, even if not whisk and handsome face, but only to be granted the post of provincial governor also that Ming By then,Canada Goose Outlet, the calibration assistant minister of War,Canada Goose UK, Gener

  11. Then he Zhuantouwangxiang post this fierce,Cheap Ray Bans Sale CBNHRW0875 NMBU255326,Fake Ray Bans, Do you have any master in Japan, Hong Kong also got it, after one hour,Cheap Sunglasses Online Store KTUSHI9517 ADJH229360,Canada Goose UK,Fashion Su, I’m here …… To be honest, I do not lack these resources. As Dayu Er think so, because Liu Hui who are pregnant,Cheap Canada Goose, Tang Feng can not let her suffer any stimulation. The emergence of such a sub-handedly,Fake Canada Goose, the yuan

  12. While on the other side to call in the little devils This word is very unhappy,cheap uggs boots, but Panasonic apricot II did not care, because his eyes nailed on 狄菲 waistline: that body of water as soft,cheap ugg boots, that crooning mildly crisp, That expression of a warm off the hook …… Xu Fu Yuxin hear the words,Canada Goose Outlet, said: It is natural,Canada Goose Outlet, do not say in the cloud continent,Canada Goose UK, the island is in the moon, nor the hospital where a

  13. Pingback: How to: Was PreferenceFragment intentionally excluded from the compatibility package? | SevenNet

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>