Published: 15 Jul 2011
By: Dino Esposito

In this article, Dino Esposito shows how to build settings dialog boxes using a built-in feature of Android for .NET.

Contents [hide]

The Android for .NET Developers Series

  • Part 1 Starting with this article, I'll discuss what you need to know to approach Android programming without any aid from your .NET expertise.
  • Part 2 In this article, we'll go through an Android application that accepts input from the user and handles user's clicking.
  • Part 3 In this article, you will learn how to build the user interface.
  • Part 4 In this article, I'll be delving deep into menus and dialog boxes in Android for .NET, and discuss a few very common (and frequently used) types of menus and dialogs.
  • Part 5 In this article, Dino Esposito focuses on the options that the Android SDK offers for local storage.
  • Part 6 In this article, Dino Esposito shows how to build settings dialog boxes using a built-in feature of Android for .NET.
  • Part 7 In this article, I'll dissect the code of a realistic application - a waterpolo score manager - to show how to save and resume the status of a game using both the internal storage and SD card.
  • Part 8 In this article, I'll focus on the execution of common tasks from within an Android application. I'll build the skeleton of an application that takes a photo and emails to the specified address. For both tasks I'll use native Android components.
  • Introduction

    All developers agree that nearly any applications should have their own collection of settings to modify the behavior according to business needs and in some cases user preferences. At the same time, all developers agree that writing an additional layer of user interface to enable the input of these settings is one of the most boring tasks, almost as annoying as writing technical documentation. Thanks to templated helpers, in ASP.NET MVC you can go very close to an ideal scenario in which, as a developer, you just write the class that contains your settings and let a system component automatically build an HTML editor around that. In ASP.NET MVC, however, the automatic behavior stops once the form is displayed. Persistence, in other words, is entirely up to you.

    The great news for .NET developers approaching Android programming is that the SDK just provides a set of classes that read layout information from an XML file and build a native user interface automatically. Nicely enough, however, Android classes - specifically the Preferences framework - also manage persistence in a way that is completely transparent to developers. In this article, I'll show how to build settings dialog boxes using this built-in feature.

    Experimenting with Preference Screens

    The first step consists in defining the layout of the settings dialog. You create an XML file with any name and place it under the res/xml folder of your Android project. To start off, let's consider a very simple but still effective layout for a settings dialog that is fairly common in mobile applications - the dialog where the user enters login information to sign in to a given service. To clarify, you see a similar dialog box when you connect to Skype or social network applications on Android and other mobile platforms as well.

    At the very minimum, this login settings dialog will gather three pieces of information: user name and password (credentials) and a flag indicating whether the user wants to stay logged in and possibly for how long. With this scenario in mind, here's a sample XML to describe preferences:

    The PreferenceScreen element represents a page containing some editable settings. You can have multiple screens, you can import a settings screen from another application and you can also create a logical chain of dependencies between screens. Each screen is made of a bunch of preference widgets, namely input elements for data to enter. Table 1 presents the list of available preference widgets.

    Table 1: Preference widgets in Android.

    Widget

    Description

    CheckBoxPreference

    Gets and sets a Boolean value through a check-box user interface.

    EditTextPreference

    Gets and sets a String value through a classic text-box user interface.

    DialogPreference

    Gets and sets custom types through a handmade dialog layout.

    ListPreference

    Gets and sets an array of data through a list user interface.

    Preference

    Base class for all preference widget elements.

    PreferenceCategory

    Container element, it groups child preference widgets in a distinct piece of user interface. The overall behavior is similar to what a fieldset element does in HTML.

    RingtonePreference

    Gets and sets a ringtone. You use this widget when you're choosing a distinct ringtone to be associated with a particular notification.

    You can create your own preference widgets (i.e., a DatePreference) by deriving a new class from Preference. The XML elements in the preference file will define at least four properties: title for the label of the input element, summary for a brief description of the input element, defaultValue for the default value you want to display initially, and finally key to indicate the name of the entry where the entered value will be stored in the preference dictionary. The key attribute is a plain string.

    Now that we have a simple but functional preference screen in place, let's see what it takes to integrate it with a real Android application.

    Integrating the Preference Framework in Applications

    Each preference screen should be wrapped up in a custom activity that inherits from the PreferenceActivity class. This is a necessary step because, as we'll see in a moment, there's a lot of behavior that goes on under the hood. Because there's no magic in software this behavior must be coded somewhere. In this specific case, the invisible location is just the PreferenceActivity class. Here's a sample activity for the login preference screen.

    A preference class is a very simple one that calls addPreferencesFromResources from within its onCreate method. More precisely, you call this method when you have your XML layout defined in the resources of the application. In this case, the parameter you pass just point to the specific resource. In Android, the expression R.xml.Xxx means you want to pick up an element from the application's resource, specifically a resource named Xxx from the xml folder.

    You can also add a preference dialog from an Intent object. In this case, you call the method addPreferencesFromIntent and pass it an Intent object as its sole argument. Here's an example of how you create an Intent out of a preference screen.

    This activity is different from the main activity that governs the main flow of the application. If you want that the preference dialog shows up at startup, you do the following in your primary activity:

    It is necessary that the login preference activity is registered in the application's manifest file.

    Figure 1 shows the output being displayed to the user.

    Figure 1: The login preference activity in action.

    The login preference activity in action.

    Interacting with this dialog box is fairly easy. The user clicks on the button near each widget and an editor is displayed with the current data if any or the default value. See Figure 2.

    Figure 2: Editing data in a preference dialog.

    Editing data in a preference dialog.

    It should be noted that all the preferences you enter through such a dialog are automatically saved to a local file using the SharedPreferences dictionary. Data is saved as the user interacts with the widgets and is transparent to the developer.

    Improving the User Experience

    Settings saved locally make sense only if they can be read back and, more importantly, if they're used to improve the user experience by modifying the user interface. In mobile applications, you always want to minimize typing. For applications that need credentials, a common practice consists in persisting username and password locally with an application specific expiration policy. Our sample application therefore will first read login information from the saved preferences and displays the settings dialog if no such information is found. Here's how to rewrite the onCreate method on the primary activity.

    LoginInfo is a helper class that reads preferences and stores values. To read preferences, you need an instance of the SharedPreferences class. More importantly, you need just the instance shared at application level by all participating activities.

    The static method getDefaultSharedPreferences on the PreferenceManager class returns the SharedPreferences dictionary for the specified context. Because settings are saved by the LoginPreferences activity and retrieved by the primary activity of the application, it is important that you pass a shared context - for example the application context. Here's why this call is absolutely necessary:

    If you pass this instead of getApplicationContext(), then the code compiles and runs, but you just won't be able to read anything back from preferences. It saves correctly in one place, but then reads back from another location. If the login information is missing or invalid, the application shows the settings dialog; otherwise it proceeds and displays the regular interface as in Figure 3.

    Figure 3: The primary interface when login data is available.

    The primary interface when login data is available.

    To display the settings you use the code below. This is the same code that is also bound to the Edit button in Figure 3.

    Changes made to the settings during the application's lifecycle can be notified to the application so that they can be immediately reflected in the user interface. You can register an event listener for the saved event like below. You call this code from onCreate.

    Here's some sample code that is invoked when a change occurs.

    The first argument gets the current status of preferences; the second argument indicates which field has been modified. You'll receive this notification for each individual change. The method Refresh in the code snippet is a placeholder for any UI code that updates the visual elements based on preferences.

    It is worth noting that the preferences dialog doesn't have a Save or OK button. As you can see in Figure 1, it doesn't have any commit/cancel pair of buttons. This is another key pattern of mobile applications - you should try to keep tapping to a bare minimum. In more and more applications any typed data is taken for good and saved or processed as if there was an explicit OK command. Hitting the Back button doesn't cancel anything but simply moves you back to the previous activity - it is the Implicit Save pattern (or Back-and-Save pattern) of mobile applications.

    Summary

    Most of the time programming for Android is boring and .NET developers often find the programming model overzealous. However, I confess that the part of the Android SDK that deals with preferences is really nice and effective. And compared to how picky and slow it could be to develop a custom dialog box, the automatic behavior of the Preferences framework is a big relief for developers.

    The Android for .NET Developers Series

  • Part 1 Starting with this article, I'll discuss what you need to know to approach Android programming without any aid from your .NET expertise.
  • Part 2 In this article, we'll go through an Android application that accepts input from the user and handles user's clicking.
  • Part 3 In this article, you will learn how to build the user interface.
  • Part 4 In this article, I'll be delving deep into menus and dialog boxes in Android for .NET, and discuss a few very common (and frequently used) types of menus and dialogs.
  • Part 5 In this article, Dino Esposito focuses on the options that the Android SDK offers for local storage.
  • Part 6 In this article, Dino Esposito shows how to build settings dialog boxes using a built-in feature of Android for .NET.
  • Part 7 In this article, I'll dissect the code of a realistic application - a waterpolo score manager - to show how to save and resume the status of a game using both the internal storage and SD card.
  • Part 8 In this article, I'll focus on the execution of common tasks from within an Android application. I'll build the skeleton of an application that takes a photo and emails to the specified address. For both tasks I'll use native Android components.
  • <<  Previous Article Continue reading and see our next or previous articles Next Article >>

    About Dino Esposito

    Dino Esposito is one of the world's authorities on Web technology and software architecture. Dino published an array of books, most of which are considered state-of-the-art in their respective areas. His most recent books are “Microsoft ® .NET: Architecting Applications for the Enterprise” and “...

    This author has published 53 articles on DotNetSlackers. View other articles or the complete profile here.

    Other articles in this category


    Developing a Hello World Java Application and Deploying it in Windows Azure - Part I
    This article demonstrates how to install Windows Azure Plugin for Eclipse, create a Hello World appl...
    Android for .NET Developers - Building a Twitter Client
    In this article, I'll discuss the features and capabilities required by an Android application to ta...
    Ref and Out (The Inside Story)
    Knowing the power of ref and out, a developer will certainly make full use of this feature of parame...
    Developing a Hello World Java Application and Deploying it in Windows Azure - Part II
    In this article we will see the steps involved in deploying the WAR created in the first part of thi...
    Android for .NET Developers - Using Web Views
    In this article, I'll show a native app that contains a web-based view. The great news is that HTML ...

    You might also be interested in the following related blog posts


    You should NOT use ASP.NET MVC if. . . read more
    Hey, nice package! read more
    2009 Predictions - ASP.NET, BizTalk and LINQ 2 SQL are dead and so are VB, C# and Azure read more
    Oxite - Oh Dear Lord Why?! read more
    Baby-sitter Framework 2.0: Change tracking in the EF v2, it's still your problem read more
    Best Practices for Wrapping Native Code read more
    I'll get to your application in a minute - First, we need to build the framework read more
    Loving the South African Developer Community read more
    WPF Series: IFrameworkElement - the missing interface read more
    SQL Server Reporting Services Subscriptions with custom security read more
    Top
     
     
     

    Please login to rate or to leave a comment.

    Free Agile Project Management Tool from Telerik
    TeamPulse Community Edition helps your team effectively capture requirements, manage project plans, assign and track work, and most importantly, be continually connected with each other.