Can you imagine an Android application without any configurable options? Actually, only the simplest application can get by without any configuration. Configuration is essential for most of Android applications. But in what way are these applications being configured?
Android provides a standard way to configure an application using SharedPreferences and PreferenceScreen. Check out my hands-on guide to using these things and implementation of custom Preference screen.
The simplest way to provide application’s configuration abilities to the user is to use PreferenceScreen to configure options stored in application’s SharedPreferences. To do this create a PreferenceScreen description file in “res\xml” directory with the following content:
Now create SettingsActivity, which extends PreferenceActivity and override the on Create method in the following way:
And the last necessary thing for now is MyPreferenceFragment class which just provides a link with our preferences XML file:
Now, modify MainActivity to open SettingsActivity in response to menu item click. Launch the application and click on the “Settings” menu item:
You can toggle “Work in background” and change “server address” options. Change some values. Don’t bother about the “Summary” hint (the text below the settings item caption - “test1.server.com” in our case). Currently, it does not reflect actual data.
Now check the “shared preferences” file by executing the following commands:
As you can see, Android automatically saves application settings in SharedPreferences file.
To access shared preferences from the code just read it using the default SharedPreferences class instance:
We see that it is possible to retrieve boolean and string values. But what else can we retrieve? Additionally to the mentioned earlier types, it is possible to retrieve float, int, long, Set and all values at once using Map.
Ok. What about saving SharedPreferences from the code? This is as simple as 1, 2, 3:
We saw that it is possible to store different data types in the SharedPreferences file. But what other controls can we use to represent these values to the user except the mentioned earlier CheckBoxPreference and EditTextPreference?
Here is the list of standard preferences:
We have used CheckBoxPreference, EditTextPreference and PreferenceScreen already. Let`s use the rest of them:
To describe “color_entries” and “color_values” items create “arrays.xml” file in “values” directory with the following content:
Here is the generated preferences file:
And the code to retrieve preferences values:
What if we need to visualize a more complex settings screen? For example, audio recording quality:
This is possible with custom DialogPreference.
To create a custom DialogPreference screen you need to do three things:
- Create your own class which extends DialogPreference;
- Create dialog layout;
- Declare DialogPreference in your preferences file
In own DialogPreference implementation you will need to override the following methods:
- All possible constructors;
- protected void onBindDialogView(View view)
- protected void onDialogClosed(boolean positiveResult)
In constructors, you need to specify whether your DialogPreference should automaticly persist its value by using “setPersistent” method. Don’t set it to true if the screen is complex and contains more than one value. Also, you need to specify layout resource with the “setDialogLayoutResource” method .
In the “onBindDialogView” method, you can load shared preferences and init views.
In the “onDialogClosed” method, you can react on dialog closing and save shared preferences.
Here is my very own basic DialogPreference class:
And here is how to use it in preferences file:
Note that “key” attribute is not used as a shared preferences key because our DialogPreference uses multiple keys. However, the key is defined here to allow accessing this preferences summary in our PreferenceFragment.
Updating preferences Summary
Did you notice that the “summary” sections (text under each option title, “Red” under Color option, for example) are not filled in in compliance with the real settings?
This is because the “summary” does not reflect the actual settings automatically. To update the “summary”, subscribe for shared preferences change and change the summary accordingly. You can do this in your PreferenceFragment onCreate method:
Sometimes it is impossible to listen for configuration changes using this approach. For example, when we are using custom complex preference screen. In this case you will need to subscribe for shared preferences change generally. Do it in your PreferenceFragment onPause and onResume methods:
And in your preferences, change the listener load shared preferences and update the summary:
Are there any other custom Preferences screens available?
Yes. For example Directory chooser.
Import it in to your project and declare in preferences file:
Now, clicking on “Directory” option will open the following dialog
The selected directory path will be saved in the specified sharedpreferences key. Don’t forget to add “WRITE_EXTERNAL_STORAGE” for proper library work.
To put it in a nutshell, those were all the aspects of using SharedPreferences. Hope you found it useful. Source codes of the demo application can be found on Github.