In order to make use of the preferences framework, the first step is to extend the PreferenceActivity class. This is just a convenience class that derives from ListActivity and allows to bootstrap the preferences UI from an XML file. Additionally, it automatically saves to SharedPreferences behind the scenes. Don’t forget that SharedPreferences is the interface responsible for accessing and modifying preference data and that we can manually manipulate it by calling the getSharedPreferences method of an Activity. In order to tie together our PreferenceActivity class and the XML layout file, we use the addPreferencesFromResource method. Thus, our onCreate method is very simple and looks like this:
...
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
...
This assumes that we have already created a file named “preferences.xml” inside the “res/xml” folder. Then, in run-time, the activity will inflate the given XML resource and add the preference hierarchy to the current preference hierarchy. This XML file has a specific format via which we define the types of the preferences. All types derive from the Preference class, which represents the basic preference UI building block and provides the View to be displayed in the activity and the association with a SharedPreferences object to store/retrieve the preference data. Here are some of the most common subclasses that you can directly use:
- CheckBoxPreference: Provides checkbox widget functionality. Will store a Boolean value.
- RingtonePreference: Allows the user to choose a ringtone from those on the device. The chosen ringtone’s URI will be persisted as a string.
- EditTextPreference: Allows for string input. Will store a string into the SharedPreferences.
- ListPreference: Displays a list of entries as a dialog. This preference will store a string into the SharedPreferences.
Also bear in mind that various preferences can be grouped into categories by using the PreferenceCategory class, which groups Preference objects and provides a disabled title above the group.
Let’s examine what our XML declaration file will be consisted of. We are going to have two categories. Under the first one, we will have a CheckBoxPreference, which will enable or disable data updates to a hypothetical application and a ListPreference which through which we will define how often we want updates to happen. As you might have guessed, there is a dependency between the two preferences. This can be achieved by using the android:dependency attribute. Finally, under the second category, we will have a EditTextPreference via which a welcome message will be saved and shown when necessary. This is what the XML file looks like:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory
android:title="First Category"
android:key="first_category">
<CheckBoxPreference
android:key="perform_updates"
android:summary="Enable or disable data updates"
android:title="Enable updates"
android:defaultValue="true"
/>
<ListPreference
android:key="updates_interval"
android:title="Updates interval"
android:summary="Define how often updates will be performed"
android:defaultValue="1000"
android:entries="@array/updateInterval"
android:entryValues="@array/updateIntervalValues"
android:dependency="perform_updates"
/>
</PreferenceCategory>
<PreferenceCategory
android:title="Second Category"
android:key="second_category">
<EditTextPreference
android:key="welcome_message"
android:title="Welcome Message"
android:summary="Define the Welcome message to be shown"
android:dialogTitle="Welcome Message"
android:dialogMessage="Provide a message"
android:defaultValue="Default welcome message" />
</PreferenceCategory>
</PreferenceScreen>
Note that for the ListPreference, an android:entries attribute is defined. We use that to load predefined values which are kept in an external XML file under the name “res/values/arrays.xml”. The “updateInterval” and “updateIntervalValue” entries are used from that file. These are actually key-value pairs, so the actual value stored is the one in the second list. Here is what the file looks like:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="updateInterval">
<item name="1000">Every 1 second</item>
<item name="5000">Every 5 seconds</item>
<item name="30000">Every 30 seconds</item>
<item name="60000">Every 1 minute</item>
<item name="300000">Every 5 minutes</item>
</string-array>
<string-array name="updateIntervalValues">
<item name="1000">1000</item>
<item name="5000">5000</item>
<item name="30000">30000</item>
<item name="60000">60000</item>
<item name="300000">300000</item>
</string-array>
</resources>
As we explained, the persisting part of the equation is handled by the framework. In order to show you how to read the already persisted values, we will create another activity which will be launched from our main one. Let’s first see how the main activity looks like:
package com.javacodegeeks.android.preferences;
import android.content.Intent;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.view.Menu;
import android.view.MenuItem;
public class QuickPrefsActivity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(Menu.NONE, 0, 0, "Show current settings");
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 0:
startActivity(new Intent(this, ShowSettingsActivity.class));
return true;
}
return false;
}
}
Nothing special here. We just provide an options menu with only one MenuItem by using the onCreateOptionsMenu method. When the user selects the specific item, we handle its actions inside the onOptionsItemSelected method and we launch a new activity using the startActivity method. If you want to learn more about option menus, check out my older tutorial named “Using options menus and customized dialogs for user interaction”. More information about starting activities can be found in my tutorial “Launching new activities with intents”.
Let’s now create the “ShowSettingsActivity”. First, we have to declare it in the Android manifest file, so here what our “AndroidManifest.xml” file looks like:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.javacodegeeks.android.preferences"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".QuickPrefsActivity" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".ShowSettingsActivity" />
</application>
<uses-sdk android:minSdkVersion="3" />
</manifest>
Here is the code for the activity itself:
package com.javacodegeeks.android.preferences;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.widget.TextView;
public class ShowSettingsActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show_settings_layout);
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
StringBuilder builder = new StringBuilder();
builder.append("\n" + sharedPrefs.getBoolean("perform_updates", false));
builder.append("\n" + sharedPrefs.getString("updates_interval", "-1"));
builder.append("\n" + sharedPrefs.getString("welcome_message", "NULL"));
TextView settingsTextView = (TextView) findViewById(R.id.settings_text_view);
settingsTextView.setText(builder.toString());
}
}
Inside the activity, we take reference of the SharedPreferences class by using the static method getDefaultSharedPreferences of the PreferenceManager class. Then, depending on the data type of the preference, we use the appropriate getter method, such as getBoolean or getString. Note that the second argument to those is a default value which will be used if a a value has not yet been stored. We use as keys those defined in the original “preferences.xml” file, i.e. “perform_updates”, “updates_interval” and “welcome_message”. The values are concatenated and then presented in a TextView.
Here is also the simple layout for the specific activity:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="@+id/settings_text_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
If we now launch the Eclipse configuration, we will get a preferences screen like the following:
Clicking on the “Updates Interval” will cause a list of options to appear:
Similarly, clicking on the “Welcome Message” preference will cause an edit text to appear:
Now let’s read the already persisted values. Hit the “Menu” button on the emulator so that the options menu appears and choose the “Show current settings” item. This will launch our second activity inside which the values are read and presented as follows:
That’s it guys. A quick guide on how to leverage the preferences framework provided in the SDK to rapidly manipulate user preferences in your application. You can find the Eclipse project created in this tutorial here.
Cheers!
- “Android Full Application Tutorial” series
- Boost your Android XML parsing with XML Pull
- Android Text-To-Speech Application
- Android Reverse Geocoding with Yahoo API – PlaceFinder
- Android Location Based Services Application – GPS location
- Install Android OS on your PC with VirtualBox










