Android Preferences

Sat, 05/15/2010 - 14:28

Preferences are an important part of an Android application. It is important to let the users have the choice to modify and personalize their application depending on their needs.

In the screenshots "custom" is spelled "costum". The typo is fixed in the code examples.

Android preferences can be set in two ways. You can create a preferences.xml file in the res/xml directory, or you can set the preferences from code.
The first example shows a preferences.xml file. Every preference needs to have a android:key value, that we call to get the preference's value. The android:title is the preference's title, and the android:summary is a summary about the preference. The android:defaultValue is the default value of the preference - fx. true or false.
Currently there are 5 different preference views:

  • The CheckBoxPreference is a simple checkbox, that can return true or false.
  • The ListPreference, which shows a radioGroup where only 1 item can be selected a time. The android:entries links to an array in the res/values/arrays, and the android:entryValues is an other array with the items to be returned.
  • The EditTextPreference shows a dialog with an editText view. This returns a String.
  • The RingtonePreference shows a radioGroup that shows the ringtones.
  • The Preference is a custom preference. This works like a Button.
  • The PreferenceScreen is a screen with preferences. When you have a PreferenceScreen inside an other PreferenceScreen, it simply opens a new screen with other preferences.
  • The PreferenceCategory is a category with preferences.

  • Custom preference

    Custom Preference

  • Edit Text Preference

    Edit Text Preference

  • List Preference

    List Preference

  • Ringtone Preference

    Ringtone Preference

  • Preference Screen

    Preference Screen

This is an example on the preferences.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
        <PreferenceCategory
                android:title="First Category">
                <CheckBoxPreference
                        android:title="Checkbox Preference"
                        android:defaultValue="false"
                        android:summary="This preference can be true or false"
                        android:key="checkboxPref" />
                <ListPreference
                        android:title="List Preference"
                        android:summary="This preference allows to select an item in a array"
                        android:key="listPref"
                        android:defaultValue="digiGreen"
                        android:entries="@array/listArray"
                        android:entryValues="@array/listValues" />
        </PreferenceCategory>
        <PreferenceCategory
                android:title="Second Category">
        <EditTextPreference
                android:name="EditText Preference"
                android:summary="This allows you to enter a string"
                android:defaultValue="Nothing"
                android:title="Edit This Text"
                android:key="editTextPref" />
        <RingtonePreference
                android:name="Ringtone Preference"
                android:summary="Select a ringtone"
                android:title="Ringtones"
                android:key="ringtonePref" />
        <PreferenceScreen
                android:key="SecondPrefScreen"
                android:title="Second PreferenceScreen"
                android:summary="This is a second PreferenceScreen">
                <EditTextPreference
                        android:name="An other EditText Preference"
                        android:summary="This is a preference in the second PreferenceScreen"
                        android:title="Edit text"
                        android:key="SecondEditTextPref" />
        </PreferenceScreen>
        <Preference
                android:title="Custom Preference"
                android:summary="This works almost like a button"
                android:key="customPref" />
        </PreferenceCategory>
</PreferenceScreen>

To show the preference screen, we create a class which extends PreferenceActivity. This is an example on the preference class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package org.kaloer.preferenceexample;
 
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.Preference.OnPreferenceClickListener;
import android.widget.Toast;
 
public class Preferences extends PreferenceActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                addPreferencesFromResource(R.xml.preferences);
                // Get the custom preference
                Preference customPref = (Preference) findPreference("customPref");
                customPref
                                .setOnPreferenceClickListener(new OnPreferenceClickListener() {
 
                                        public boolean onPreferenceClick(Preference preference) {
                                                Toast.makeText(getBaseContext(),
                                                                "The custom preference has been clicked",
                                                                Toast.LENGTH_LONG).show();
                                                SharedPreferences customSharedPreference = getSharedPreferences(
                                                                "myCustomSharedPrefs", Activity.MODE_PRIVATE);
                                                SharedPreferences.Editor editor = customSharedPreference
                                                                .edit();
                                                editor.putString("myCustomPref",
                                                                "The preference has been clicked");
                                                editor.commit();
                                                return true;
                                        }
 
                                });
        }
}

We can call this activity when we click a button:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
        @Override
        public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.main);
                Button prefBtn = (Button) findViewById(R.id.prefButton);
                prefBtn.setOnClickListener(new OnClickListener() {
 
                        public void onClick(View v) {
                                Intent settingsActivity = new Intent(getBaseContext(),
                                                Preferences.class);
                                startActivity(settingsActivity);
                        }
                });
        }

To read these preferences from code, we should create a getPrefs() method, which we can call in the onStart() method. When we call it in the onStart() method instead of onCreate(), we can be sure that the preferences load when we have set them and returned to our main activity,
The getPrefs() method could look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
boolean CheckboxPreference;
        String ListPreference;
        String editTextPreference;
        String ringtonePreference;
        String secondEditTextPreference;
        String customPref;
 
        private void getPrefs() {
                // Get the xml/preferences.xml preferences
                SharedPreferences prefs = PreferenceManager
                                .getDefaultSharedPreferences(getBaseContext());
                CheckboxPreference = prefs.getBoolean("checkboxPref", true);
                ListPreference = prefs.getString("listPref", "nr1");
                editTextPreference = prefs.getString("editTextPref",
                                "Nothing has been entered");
                ringtonePreference = prefs.getString("ringtonePref",
                                "DEFAULT_RINGTONE_URI");
                secondEditTextPreference = prefs.getString("SecondEditTextPref",
                                "Nothing has been entered");
                // Get the custom preference
                SharedPreferences mySharedPreferences = getSharedPreferences(
                                "myCustomSharedPrefs", Activity.MODE_PRIVATE);
                customPref = mySharedPreferences.getString("myCusomPref", "");
        }

Remember to add the following tag in your androidmanifest.xml file and add a new string item with the name "set_preferences" with the preference screen's title, for example "Preferences"

1
2
3
4
<activity
        android:name=".Preferences"
        android:label="@string/set_preferences">
</activity>

This is the final result

  • The main activity screen

  • The preference activity

Comments

Anonymous
Tue, 06/15/2010 - 18:46

You spelled "custom" wrong.

Tue, 06/15/2010 - 19:08

Great article!
Fantastic examples!
Thank you so much!

Anonymous
Thu, 06/17/2010 - 13:13

Great article - exactly what I was looking for.

Took me a while to figure out that listArray and listValues (mentioned under the ListPreference in preferences.xml) are actually two arrays that need to be defined in res/values/arrays.xml.

Dude
Tue, 06/22/2010 - 10:42

Could you please add your source code.
I am a newb and am having a hard time understanding the code.

Mads Kalør
Tue, 06/22/2010 - 12:56

Hi,

I'm sorry but I wrote the article for about a year ago, so unfortunately I don't have the source code anymore. But I'll provide one in every article I write in the future. Sorry!

Diego
Tue, 06/22/2010 - 13:49

Very clear, thanks!!

theblang
Wed, 06/23/2010 - 00:51

Thanks Kalor! This helped a lot.

Anonymous
Tue, 06/29/2010 - 07:50

niceee

Manuel
Thu, 07/01/2010 - 14:34

thanks for the tutorial. Please how do you make the preference screen the first screen displayed when onCreate() is called.

Thank you

Mads Kalør
Thu, 07/01/2010 - 14:37

Manuel:

I'm not sure I understand your question. In the preference activity, the preferences are shown by calling
addPreferencesFromResource(R.xml.preferences); in onCreate().

Mads Kalør
Thu, 07/01/2010 - 14:40

If you want the preference screen to be the first activity shown in your application, you will have to add the following to your android manifest file:

1
2
3
4
5
6
7
<activity android:name=".MyPreferenceClass"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
</activity>

NIR
Sat, 07/10/2010 - 04:30

Thanks for a nice tutorial. I hope you can help me expand on this. I would like to add preferences to each item in a ListView. For example, say i had a list view of cars - i would like to be able to define individual preferences for each one of the cars in the list (i.e. make, model, color, etc...)

How can i do this? Everything i find on the web seems to point at a single set of preferences for an app, but i need to have multiple sets.

Thanks again for the tutorial, and any advice you can provide.
//Nick

Tue, 07/20/2010 - 05:45

If you want the preferences to be saved to your preferences file, you have to call:

getPreferenceManager().setSharedPreferencesName(preferences_file_name);

You should do this at the beginning of your PreferenceActivity's onCreate() method, right after you call super.onCreate() and right before you call addPreferencesFromResource()

Nea
Tue, 07/27/2010 - 13:40

Is it possible to set a backgroundimage on a PreferenceScreen?

I have tried the tag android:background="@drawable/some_background" which can be set in for example a LinearLayout XML, but it doesn't work in the PreferenceScreen.

Mads Kalør
Tue, 07/27/2010 - 13:51

The only way to do it (as far as I know) is to do it in code. In your PreferenceActivity you can call getListView() to get the ListView. You can then set the background on this listview by calling setBackgroundResource(int resource).

F.eks. in the onCreate method:
getListView().setBackgroundResource(R.drawable.my_background)

Kyle
Tue, 08/03/2010 - 17:44

I believe the background image can be set on the root PreferenceScreen but it won't work on any nested screens.

If anyone knows a solution to this, I would love to know.

Christian
Wed, 08/04/2010 - 17:12

Do you know if it's possible to customize a preference screen (adding icones before text for example) ?

Mads Kalør
Wed, 08/04/2010 - 18:18

Well, it's not that easy. There is a discussion about it here

Frank
Thu, 08/05/2010 - 22:29

This is fantastic. The only thing that would make it better is if you showed how to define listArray and listValues so your code would compile without errors.

mizkat
Fri, 08/06/2010 - 08:57

anyone please give me a source code about preferences like that..
i'm still confused, and my source code always get errors,,
T_T

Geoff McGrath
Sun, 08/08/2010 - 19:28

To define the listArray and listValues create a new file in your project at this path: /res/values/array.xml

The contents of that file should be:

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

Geoff McGrath
Sun, 08/08/2010 - 19:30

Let's try that again. The file contens should be:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="listArray">
<string-array name="listValues">
</resources>

Christian
Sun, 08/08/2010 - 21:49

Thanks Mads Kalør...

mizkat
Mon, 08/09/2010 - 05:48

thanks geoff, but i still never got it, the code has already right but, when i press the preference button always appear force close on screen,, are them have 2 java file ?

Mads Kalør
Mon, 08/09/2010 - 09:05

In your res/values folder add a file called arrays.xml. Take a look at the documentation.

For example this xml file declares two arrays with 3 objects - one with the visible strings and another with the strings' IDs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="listArray">
   <item>Value 1</item>
   <item>Value 2</item>
   <item>Value 3</item>
</string-array>
 
<string-array name="listValues">
   <item>1</item>
   <item>2</item>
   <item>3</item>
</string-array>
</resources>

mizkat
Tue, 08/10/2010 - 04:36

Oh i'm very thank you to Mads Kaloer and Geoff McGrath, the code has been work, its help me very much, thanks..
:D

Sat, 08/21/2010 - 23:27

Will be definitively using it in my application.
Thanks for this very well written post :)

Lalu
Mon, 08/23/2010 - 01:27

I've been stuck on this for a whole night. The problem is that in the main .java file I have a variable "i" which goes to "i++" every millisecond and I have a Custom Option to reset it to 0 in the preferences .java. Now: every time I enter the preferences screen, i goes to 0 automatically and the related text is reset as well (I am checking if reset is selected /* with an alert - yes/no dialog */ with a boolean). Please, does anyone have any idea of what the problem might be?
P.S.: Thanks Mads, awesome tutorial!!!

Lalu
Mon, 08/23/2010 - 02:20

Solved it. I don't know what was wrong, but I set the boolean to false in onCreate(), before setting it to true.

Wed, 08/25/2010 - 21:07

I was about to build the whole preferences-thing by myself until I found your page, I didn't think it could be that easy. Thanks very much, this really my day!!

Post new comment
The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.