August 30, 2014

What's Your Preference: Part One

Beginning with the 0.9 SDK, Android has introduced a framework for presenting a consistent set of preference-setting options for users, so different applications do not have to “reinvent the wheel”. Today, we will take a look at the basics of setting up such a preferences UI, in an except from The Busy Coder’s Guide to Android Development.

The linchpin to the preferences framework is yet another XML data structure. You can describe your application’s preferences in an XML file stored in your project’s res/xml/ directory. Given that, Android can present a pleasant user UI for manipulating those preferences, which are then stored in the SharedPreferences you get back from getDefaultSharedPreferences().

Below, you will find the preference XML for a trivial set of preferences:

[sourcecode language='xml']

xmlns:android="http://schemas.android.com/apk/res/android">
android:key="@string/checkbox"
android:title="Checkbox Preference"
android:summary="Check it on, check it off" />
android:key="@string/ringtone"
android:title="Ringtone Preference"
android:showDefault="true"
android:showSilent="true"
android:summary="Ping a tone, any tone" /> [/sourcecode]

The root of the preference XML is a PreferenceScreen element. We will explain why it is named that in a future post; for now, take it on faith that it is a sensible name.

One of the things you can have inside a PreferenceScreen element, not surprisingly, are preference definitions. These are subclasses of Preference, such as CheckBoxPreference or RingtonePreference, as shown above. As one might expect, these allow you to check a checkbox or choose a ringtone, respectively.

Given that you have set up the preference XML, you can use a nearly-built-in activity for allowing your users to set their preferences. The activity is “nearly-built-in” because you need to subclass it to point it to your preference XML, plus hook it into the rest of your application.

So, for example, here is an activity that displays the UI for the preferences shown above:

[sourcecode language='java']
package com.commonsware.android.prefs;

import android.app.Activity;
import android.os.Bundle;
import android.preference.PreferenceActivity;

public class EditPreferences extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

addPreferencesFromResource(R.xml.preferences);
}
}
[/sourcecode]

As you can see, there is not much to see. All you need to do is call addPreferencesFromResource() and specify the XML resource containing your preferences.

You will also need to add this as an activity to your AndroidManifest.xml file:

[sourcecode language='xml']
package="com.commonsware.android.prefs">

android:name=".SimplePrefsDemo"
android:label="@string/app_name">





android:name=".EditPreferences"
android:label="@string/app_name">



[/sourcecode]

And you will need to arrange to invoke the activity, such as from a menu option:

[sourcecode language='java']
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case EDIT_ID:
startActivity(new Intent(this, EditPreferences.class));
return(true);

case CLOSE_ID:
finish();
return(true);
}

return(super.onOptionsItemSelected(item));
}
[/sourcecode]

However, that is all that is needed, and it really is not that much code outside of the preferences XML. When you get for your effort is an Android-supplied preference UI:

The Preferences activity

The Preferences activity

The checkbox can be directly checked or unchecked. To change the ringtone preference, just click on the entry in the preference list to bring up a selection dialog:

The RingtonePreference selection dialog

The RingtonePreference selection dialog

In our next episode, we will look at adding some structure to the preferences UI, by creating groups of preferences (categories) and additional pages of preferences (screens).