Android User Interface Design: Building Application Preference Screens

Android User Interface Design: Building Application Preference Screens

Tutorial Details
  • Technology: Android SDK
  • Difficulty: Beginner/Intermediate
  • Estimated Completion Time: 45-60 Minutes
This entry is part 11 of 21 in the series Android User Interface Design

Many applications can benefit from Shared Preferences – the Android platform’s answer to the persistent storage of application settings. There are many ways to create user interfaces for collecting and displaying persistent settings for users. The easiest way is to use the PreferencesActivity, which provides a consistent look-and-feel with the rest of the platform, including the device system preferences. Learn how to use PreferencesActivity in this tutorial.

Our simple Mobiletuts tutorial feed reader application, which doesn’t have an official name yet (we’ve been referring to it as TutList), needs better user control over the background updating process. Therefore, we’ll add a single preference to help control the background updating.

This tutorial builds upon previous tutorials, including Android Essentials: Application Preferences and the continued series on our TutList activity with the most recent tutorial, Android Fundamentals: Scheduling Recurring Tasks. If you have trouble keeping up, feel free to post questions in the comment section — many folks read and respond, including ourselves. Also, don’t forget about the Android SDK reference.
The final sample code that accompanies this tutorial is available for download as open-source from the Google code hosting.

Step 0: Getting Started

This tutorial assumes you will start where the previous tutorial in the series, Android Fundamentals: Scheduling Recurring Tasks, left off. You can download that code and work from there or you can download the code for this tutorial and follow along. Either way, get ready by downloading one or the other project and importing it into Eclipse.

Step 1: Adding a Shared Preferences Helper

Shared preferences are often used throughout an application. The definitions of the names of the individual settings and the name of the preferences group must be stored for use throughout an application. There are several ways to solve this problem. The solution we’ll use involves a helper class for consistent access to specific settings values, with the preferences keys stored in as resources strings for access from code and other resource files.

Let’s start with the helper class code:

public class TutListSharedPrefs {
    public final static String PREFS_NAME = "tutlist_prefs";
    public static boolean getBackgroundUpdateFlag(Context context) {
        SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
        return prefs.getBoolean(
                context.getString(R.string.pref_key_flag_background_update),
                false);
    }
    public static void setBackgroundUpdateFlag(Context context, boolean newValue) {
        SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, 0);
        Editor prefsEditor = prefs.edit();
        prefsEditor.putBoolean(
                context.getString(R.string.pref_key_flag_background_update),
                newValue);
        prefsEditor.commit();
    }
}

In this class, we’ve defined a public constant to identify the name of the preferences group or set, called PREFS_NAME. We’ve also used a resource string, called pref_key_flag_background_update, to specify the specific preference name definition. You should add a string to your resources so this identifier is defined. We set its value to “background_update_flag” but what matters is that the value used is the same everywhere.

Although we’ve added a setBackgroundUpdateFlag() method for completeness, we will not be using this method. Read on to see why.

Finally, we added this Java class to the com.mamlambo.tutorial.tutlist.data package as that seems most relevant.

Step 2: Adding a Preferences Screen Activity

The Android SDK includes a consistent means of presenting settings to users: the PreferenceActivity. In conjunction with a preference resource file, this specialized Activity class makes it very easy for developers to configure and display most types of application settings in a consistent fashion. The consistency with other application and system preference screens also makes these screens familiar and easy for users, too.

To add a PreferenceActivity to the “TutList” application, start by adding a new activity call TutListPreferencesActivity and have it extend PreferenceActivity (we added it to the main package). Since we’re not using the default preference name, we need to set the preference name this PreferenceActivity will use. In addition, we need to tell it which preference resource file to use. This will tell it how to display the preferences, as well as which ones this screen displays and modifies.

Within the onCreate() method of this activity, use the setSharedPreferencesName() method with the preference group constant defined in the preferences helper class we defined in the previous step. Then make a call to the addPreferencesFromResource() method. We’ll define this resource in the next step.

Right now, this entire class looks like this:

public class TutListPreferencesActivity extends PreferenceActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getPreferenceManager().setSharedPreferencesName(
                TutListSharedPrefs.PREFS_NAME);
        addPreferencesFromResource(R.xml.prefs);
    }
}

We’ll enhance this class throughout the tutorial. But first, let’s create the referenced XML resource called prefs.

Step 3: Defining a Preferences Screen Resource

Add a new XML file called prefs.xml to the application resources. You can use the new Android XML file wizard and fill out the fields as shown in the following image. This will also create the XML file in the correct location, the /res/xml directory.

A preferences activity resource file consists of a <PreferencesScreen> tag with one or more <PreferenceCategory> tags for organizing settings and various type-specific attributes. For our simple preference needs, we can use the <CheckBoxPreference>, which loads and stores a Boolean value. Other possible types include EditTextPreference and ListPreference selections, for collecting strings and a choice from amongst a list of items, respectively.

Here’s the entire contents preference screen resource file, prefs.xml:

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:title="Background Updating">
        <CheckBoxPreference
            android:summary="@string/pref_summary_background_update_flag"
            android:title="@string/pref_title_background_update_flag"
            android:key="@string/pref_key_flag_background_update" />
    </PreferenceCategory>
</PreferenceScreen>

This demonstrates one of best reasons to store the key strings as a resource: they can be used directly in the XML file as well as loaded into Java.

Step 4: Launching the Preferences Screen

Next, we’ll add a menu item on the list fragment to launch the preferences screen. While doing this, we’ll also update the refresh menu item to no longer start the scheduled update.

To do this, first edit the /res/menu/options_menu.xml resource file to add a new menu item:

<item
    android:id="@+id/settings_option_item"
    android:icon="@drawable/ic_menu_preferences"
    android:title="@string/settings"></item>

You’ll also need to add the corresponding resource string for the item title (@string/settings) and add an appropriate icon (@drawable/ic_menu_preferences). We used the standard preferences icon from the Android SDK, which will be familiar to users.

Next, edit the onCreateOptionsMenu() method to provide the correct Intent for the new menu item:

Intent prefsIntent = new Intent(getActivity().getApplicationContext(),
        TutListPreferencesActivity.class);
MenuItem preferences = menu.findItem(R.id.settings_option_item);
preferences.setIntent(prefsIntent);

Now, update the onOptionsItemSelected() method. Since there is more than one menu item, it now makes sense to use a switch statement. Within the switch statement, we can use the constant identifiers assigned for each menu item to differentiate the user selections.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case R.id.refresh_option_item:
        getActivity().startService(item.getIntent());
        break;
    case R.id.settings_option_item:
        getActivity().startActivity(item.getIntent());
        break;
    }
    return true;
}

Finally, don’t forget to add the new activity to the Android manifest file:

<activity
    android:name=".TutListPreferencesActivity" />

You can now run the application and see the new menu item.

The preferences activity can be launched and store and retrieve the background update preference. It should look like the following:

It looks great, but it doesn’t do anything real yet. Although the flag is updated within the preferences, there isn’t yet a place where the value is checked to see if the background updating should start or not..

Step 5: Starting and Stopping the Alarm

In the last step, calls to the setRecurringAlarm() helper method were removed. In fact, this method won’t be needed in the TutListFragment class any longer. Instead, move it to the TutListPreferencesActivity class. Then add a second helper, called cancelRecurringAlarm():

private void cancelRecurringAlarm(Context context) {
    Intent downloader = new Intent(context, AlarmReceiver.class);
    PendingIntent recurringDownload = PendingIntent.getBroadcast(context,
            0, downloader, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarms.cancel(recurringDownload);
}

Finally, override the onPause() method of the TutListPreferencesActivity class to set or cancel the recurring alarm as appropriate. Within this method, you can check the value of preferences — updated values using the helper method getBackgroundUpdateFlag() and call the appropriate method:

@Override
protected void onPause() {
    super.onPause();
    Context context = getApplicationContext();
    if (TutListSharedPrefs.getBackgroundUpdateFlag(getApplicationContext())) {
        setRecurringAlarm(context);
    } else {
        cancelRecurringAlarm(context);
    }
}

Now, whenever the settings are checked, the alarm is updated based on the current value. With a default value of “off”, the user must go in to the settings to enable background downloading.

About PreferenceFragment

You may have wondered why we didn’t use the new PreferenceFragment class. The reason is simple: it is not yet supported in the compatibility library. Since we want to keep the TutList application compatible with more than just Android 3.0 devices, we can’t yet use it. Hopefully the compatibility library will continue to be enhanced.

Conclusion

In this tutorial, you have learned how to use the PreferencesScreen resource file with a PreferencesActivity to quickly and easily create a functional activity that for managing application preference data. In addition, you provided the user with a method to control the background updating of the TutList application.
As always, we look forward to your feedback.

About the Authors

Mobile developers Lauren Darcey and Shane Conder have coauthored several books on Android development: an in-depth programming book entitled Android Wireless Application Development and Sams Teach Yourself Android Application Development in 24 Hours. When not writing, they spend their time developing mobile software at their company and providing consulting services. They can be reached at via email to androidwirelessdev+mt@gmail.com, via their blog at androidbook.blogspot.com, and on Twitter @androidwireless.

Need More Help Writing Android Apps? Check out our Latest Books and Resources!

Buy Android Wireless Application Development, 2nd Edition  Buy Sam's Teach Yourself Android Application Development in 24 Hours  Mamlambo code at Code Canyon

Series Navigation«Android User Interface Design: Working With FragmentsAndroid User Interface Design: Basic Text Controls»

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Droid

    This is exactly what I’m looking for :-) What about tutorial for simple android RSS reader? :-)

    • http://androidbook.blogspot.com/ Shane Conder & Lauren Darcey
      Author

      Hi Droid,

      This app is basically a simple RSS reader. It has a hard-coded feed, and will ultimately rely on some specifics to the mobiletuts feed, but the basics are the same. :)

  • david

    Nice tutorial, ive been watching this site for a while now waiting for some more in depth tutorials on android interface development.

    By any chance do you have experience with developing custom interfaces using open gl? Ive been looking at some ipad interfaces like ones used by the flipbook application.

    I would love to be able to develop these interfaces but i need to learn how to use opengl.

    If you have the experience to be able to do a tutorial on how to create those sorts of custom interfaces i would love to see them and it would really benefit the android dev community to beautify their apps.

    Thanks again for the great tut.

  • http://en.davidmorales.me David

    Nice tut!

    One little thing to fix: in step 4 “@drawable/ic_menu_preferences” should be “@android:drawable/ic_menu_preferences”

    • http://androidbook.blogspot.com/ Shane Conder & Lauren Darcey
      Author

      Thanks for the feedback, David.

      Actually, we included the resource directly in the project. (In Step 4, “We used the standard preferences icon…” basically means we borrowed the actual graphic file, not just referenced the built-in one.) This allows the resource to be reliable (always the same) and ultimately something that can be changed to better theme it to the app (if needed).

  • Dliswa

    Sorry to say my problem is different
    but i need some help

    Thanks in advance

    I am aware of Creating a new values directory for the language with the suffix of the language code. For german: values-de or french: values-fr then copy our string.xml into that and translate each entry. And this works based on the Phone Localization settings

    I wanted to know if we can bypass the phone setting and and make the user select his required language inside the app?

    My requirement is, i want to give a language selection option inside my app, and make the user select the language he wants for the app.. how to dynamically switch between the string.xml (for different languages) ???

    thanks in advance

    • http://androidbook.blogspot.com/ Shane Conder & Lauren Darcey
      Author

      I’m not immediately aware of a way to do this, but the way I would do it is create an intent that launches directly to the language settings screen. (The activity is com.android.settings.LanguageSettings — from there, the back key will bring people back to your app — just as if that activity had been part of your app.)

  • billyjoe

    what are the imports used in preference?

  • Flemming

    does anyone know how to set the default value of “off” to “on”, so the user can avoid go in to the settings to enable background downloading.

    • http://www.facebook.com/Liggli Dennis Fluttershy

      android:defaultValue=”true”

  • jv0521

    First of all, thank you for the great guides, they provide much help as I’m new to Android development. Unfortunately I am stuck at this section. I followed the instructions (even compared the codes from the source), but when I run the application (either on my phone or a virtual device), it does not react to pressing the menu button, nothing pops up.. Here is my onCreateOptionsMenu() function, hope you can help me in identifying the problem. :) Thanks in advance!

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.options_menu, menu);
    Intent prefsIntent = new Intent(getActivity().getApplicationContext(),
    TutListPreferencesActivity.class);
    MenuItem preferences = menu.findItem(R.id.settings_option_item);
    preferences.setIntent(prefsIntent);
    }

    • Timothy Caraballo

      An old post, but in case someone else is wondering, you have to call

      setHasOptionsMenu(true);

      for Fragments to use menus. You can call this from your fragment’s onCreate method.

  • Abdul Basith

    Very useful for beginners

  • http://www.facebook.com/Liggli Dennis Fluttershy

    But remember:
    “Don’t start a label with an instructional verb like ‘Set’, ‘Change’, ‘Edit’, ‘Modify’, ‘Manage’, ‘Use’, ‘Select’, or ‘Choose’. Users already understand that they can do these things to settings.”
    …read more about Settings here:
    http://developer.android.com/design/patterns/settings.html

  • http://www.mobileappsdevelopmentteam.com/ Madt Team

    These steps are full of information. This information helps UI designers who want to design screen as per the requirement.