settings.jd revision 183bf116978e3c44292c9ead2bceb47e972624a1
1page.title=Settings
2@jd:body
3
4
5<div id="qv-wrapper">
6<div id="qv">
7
8<h2>In this document</h2>
9<ol>
10  <li><a href="#Overview">Overview</a>
11    <ol>
12      <li><a href="#SettingTypes">Preferences</a></li>
13    </ol>
14  </li>
15  <li><a href="#DefiningPrefs">Defining Preferences in XML</a>
16    <ol>
17      <li><a href="#Groups">Creating setting groups</a></li>
18      <li><a href="#Intents">Using intents</a></li>
19    </ol>
20  </li>
21  <li><a href="#Activity">Creating a Preference Activity</a></li>
22  <li><a href="#Fragment">Using Preference Fragments</a></li>
23  <li><a href="#Defaults">Setting Default Values</a></li>
24  <li><a href="#PreferenceHeaders">Using Preference Headers</a>
25    <ol>
26      <li><a href="#CreateHeaders">Creating the headers file</a></li>
27      <li><a href="#DisplayHeaders">Displaying the headers</a></li>
28      <li><a href="#BackCompatHeaders">Supporting older versions with preference headers</a></li>
29    </ol>
30  </li>
31  <li><a href="#ReadingPrefs">Reading Preferences</a>
32    <ol>
33      <li><a href="#Listening">Listening for preference changes</a></li>
34    </ol>
35  </li>
36  <li><a href="#NetworkUsage">Managing Network Usage</a></li>
37  <li><a href="#Custom">Building a Custom Preference</a>
38    <ol>
39      <li><a href="#CustomSelected">Specifying the user interface</a></li>
40      <li><a href="#CustomSave">Saving the setting's value</a></li>
41      <li><a href="#CustomInitialize">Initializing the current value</a></li>
42      <li><a href="#CustomDefault">Providing a default value</a></li>
43      <li><a href="#CustomSaveState">Saving and restoring the Preference's state</a></li>
44    </ol>
45  </li>
46</ol>
47
48<h2>Key classes</h2>
49<ol>
50  <li>{@link android.preference.Preference}</li>
51  <li>{@link android.preference.PreferenceActivity}</li>
52  <li>{@link android.preference.PreferenceFragment}</li>
53</ol>
54
55
56<h2>See also</h2>
57<ol>
58  <li><a
59href="{@docRoot}design/patterns/settings.html">Settings design guide</a></li>
60</ol>
61</div>
62</div>
63
64
65
66
67<p>Applications often include settings that allow users to modify app features and behaviors. For
68example, some apps allow users to specify whether notifications are enabled or specify how often the
69application syncs data with the cloud.</p>
70
71<p>If you want to provide settings for your app, you should use
72Android's {@link android.preference.Preference} APIs to build an interface that's consistent with
73the user experience in other Android apps (including the system settings). This document describes
74how to build your app settings using {@link android.preference.Preference} APIs.</p>
75
76<div class="note design">
77<p><strong>Settings Design</strong></p>
78  <p>For information about how to design your settings, read the <a
79href="{@docRoot}design/patterns/settings.html">Settings</a> design guide.</p>
80</div>
81
82
83<img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" />
84<p class="img-caption"><strong>Figure 1.</strong> Screenshots from the Android Messaging app's
85settings. Selecting an item defined by a {@link android.preference.Preference} 
86opens an interface to change the setting.</p>
87
88
89
90
91<h2 id="Overview">Overview</h2>
92
93<p>Instead of using {@link android.view.View} objects to build the user interface, settings are
94built using various subclasses of the {@link android.preference.Preference} class that you
95declare in an XML file.</p>
96
97<p>A {@link android.preference.Preference} object is the building block for a single
98setting. Each {@link android.preference.Preference} appears as an item in a list and provides the
99appropriate UI for users to modify the setting. For example, a {@link
100android.preference.CheckBoxPreference} creates a list item that shows a checkbox, and a {@link
101android.preference.ListPreference} creates an item that opens a dialog with a list of choices.</p>
102
103<p>Each {@link android.preference.Preference} you add has a corresponding key-value pair that
104the system uses to save the setting in a default {@link android.content.SharedPreferences}
105file for your app's settings. When the user changes a setting, the system updates the corresponding
106value in the {@link android.content.SharedPreferences} file for you. The only time you should
107directly interact with the associated {@link android.content.SharedPreferences} file is when you
108need to read the value in order to determine your app's behavior based on the user's setting.</p>
109
110<p>The value saved in {@link android.content.SharedPreferences} for each setting can be one of the
111following data types:</p>
112
113<ul>
114  <li>Boolean</li>
115  <li>Float</li>
116  <li>Int</li>
117  <li>Long</li>
118  <li>String</li>
119  <li>String {@link java.util.Set}</li>
120</ul>
121
122<p>Because your app's settings UI is built using {@link android.preference.Preference} objects
123instead of
124{@link android.view.View} objects, you need to use a specialized {@link android.app.Activity} or
125{@link android.app.Fragment} subclass to display the list settings:</p>
126
127<ul>
128  <li>If your app supports versions of Android older than 3.0 (API level 10 and lower), you must
129build the activity as an extension of the {@link android.preference.PreferenceActivity} class.</li>
130  <li>On Android 3.0 and later, you should instead use a traditional {@link android.app.Activity}
131that hosts a {@link android.preference.PreferenceFragment} that displays your app settings.
132However, you can also use {@link android.preference.PreferenceActivity} to create a two-pane layout
133for large screens when you have multiple groups of settings.</li>
134</ul>
135
136<p>How to set up your {@link android.preference.PreferenceActivity} and instances of {@link
137android.preference.PreferenceFragment} is discussed in the sections about <a
138href="#Activity">Creating a Preference Activity</a> and <a href="#Fragment">Using
139Preference Fragments</a>.</p>
140
141
142<h3 id="SettingTypes">Preferences</h3>
143
144<p>Every setting for your app is represented by a specific subclass of the {@link
145android.preference.Preference} class. Each subclass includes a set of core properties that allow you
146to specify things such as a title for the setting and the default value. Each subclass also provides
147its own specialized properties and user interface. For instance, figure 1 shows a screenshot from
148the Messaging app's settings. Each list item in the settings screen is backed by a different {@link
149android.preference.Preference} object.</p>
150
151<p>A few of the most common preferences are:</p>
152
153<dl>
154  <dt>{@link android.preference.CheckBoxPreference}</dt>
155  <dd>Shows an item with a checkbox for a setting that is either enabled or disabled. The saved
156value is a boolean (<code>true</code> if it's checked).</dd>
157
158  <dt>{@link android.preference.ListPreference}</dt>
159  <dd>Opens a dialog with a list of radio buttons. The saved value
160can be any one of the supported value types (listed above).</dd>
161
162  <dt>{@link android.preference.EditTextPreference}</dt>
163  <dd>Opens a dialog with an {@link android.widget.EditText} widget. The saved value is a {@link
164java.lang.String}.</dd>
165</dl>
166
167<p>See the {@link android.preference.Preference} class for a list of all other subclasses and their
168corresponding properties.</p>
169
170<p>Of course, the built-in classes don't accommodate every need and your application might require
171something more specialized. For example, the platform currently does not provide a {@link
172android.preference.Preference} class for picking a number or a date. So you might need to define
173your own {@link android.preference.Preference} subclass. For help doing so, see the section about <a
174href="#Custom">Building a Custom Preference</a>.</p>
175
176
177
178<h2 id="DefiningPrefs">Defining Preferences in XML</h2>
179
180<p>Although you can instantiate new {@link android.preference.Preference} objects at runtime, you
181should define your list of settings in XML with a hierarchy of {@link android.preference.Preference}
182objects. Using an XML file to define your collection of settings is preferred because the file
183provides an easy-to-read structure that's simple to update. Also, your app's settings are
184generally pre-determined, although you can still modify the collection at runtime.</p>
185
186<p>Each {@link android.preference.Preference} subclass can be declared with an XML element that
187matches the class name, such as {@code &lt;CheckBoxPreference>}.</p>
188
189<p>You must save the XML file in the {@code res/xml/} directory. Although you can name the file
190anything you want, it's traditionally named {@code preferences.xml}. You usually need only one file,
191because branches in the hierarchy (that open their own list of settings) are declared using nested
192instances of {@link android.preference.PreferenceScreen}.</p>
193
194<p class="note"><strong>Note:</strong> If you want to create a multi-pane layout for your
195settings, then you need separate XML files for each fragment.</p>
196
197<p>The root node for the XML file must be a {@link android.preference.PreferenceScreen
198&lt;PreferenceScreen&gt;} element. Within this element is where you add each {@link
199android.preference.Preference}. Each child you add within the
200{@link android.preference.PreferenceScreen &lt;PreferenceScreen&gt;} element appears as a single
201item in the list of settings.</p>
202
203<p>For example:</p>
204
205<pre>
206&lt;?xml version="1.0" encoding="utf-8"?>
207&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
208    &lt;CheckBoxPreference
209        android:key="pref_sync"
210        android:title="@string/pref_sync"
211        android:summary="@string/pref_sync_summ"
212        android:defaultValue="true" />
213    &lt;ListPreference
214        android:dependency="pref_sync"
215        android:key="pref_syncConnectionType"
216        android:title="@string/pref_syncConnectionType"
217        android:dialogTitle="@string/pref_syncConnectionType"
218        android:entries="@array/pref_syncConnectionTypes_entries"
219        android:entryValues="@array/pref_syncConnectionTypes_values"
220        android:defaultValue="@string/pref_syncConnectionTypes_default" />
221&lt;/PreferenceScreen>
222</pre>
223
224<p>In this example, there's a {@link android.preference.CheckBoxPreference} and a {@link
225android.preference.ListPreference}. Both items include the following three attributes:</p>
226
227<dl>
228  <dt>{@code android:key}</dt>
229  <dd>This attribute is required for preferences that persist a data value. It specifies the unique
230key (a string) the system uses when saving this setting's value in the {@link
231android.content.SharedPreferences}. 
232  <p>The only instances in which this attribute is <em>not required</em> is when the preference is a
233{@link android.preference.PreferenceCategory} or {@link android.preference.PreferenceScreen}, or the
234preference specifies an {@link android.content.Intent} to invoke (with an <a
235href="#Intents">{@code &lt;intent&gt;}</a> element) or a {@link android.app.Fragment} to display (with an <a
236href="{@docRoot}reference/android/preference/Preference.html#attr_android:fragment">{@code
237android:fragment}</a> attribute).</p>
238  </dd>
239  <dt>{@code android:title}</dt>
240  <dd>This provides a user-visible name for the setting.</dd>
241  <dt>{@code android:defaultValue}</dt>
242  <dd>This specifies the initial value that the system should set in the {@link
243android.content.SharedPreferences} file. You should supply a default value for all
244settings.</dd>
245</dl>
246
247<p>For information about all other supported attributes, see the {@link
248android.preference.Preference} (and respective subclass) documentation.</p>
249
250
251<div class="figure" style="width:300px">
252  <img src="{@docRoot}images/ui/settings/settings-titles.png" alt="" />
253  <p class="img-caption"><strong>Figure 2.</strong> Setting categories
254    with titles. <br/><b>1.</b> The category is specified by the {@link
255android.preference.PreferenceCategory &lt;PreferenceCategory>} element. <br/><b>2.</b> The title is
256specified with the {@code android:title} attribute.</p>
257</div>
258
259
260<p>When your list of settings exceeds about 10 items, you might want to add titles to
261define groups of settings or display those groups in a
262separate screen. These options are described in the following sections.</p>
263
264
265<h3 id="Groups">Creating setting groups</h3>
266
267<p>If you present a list of 10 or more settings, users
268may have difficulty scanning, comprehending, and processing them. You can remedy this by
269dividing some or all of the settings into groups, effectively turning one long list into multiple
270shorter lists. A group of related settings can be presented in one of two ways:</p>
271
272<ul>
273  <li><a href="#Titles">Using titles</a></li>
274  <li><a href="#Subscreens">Using subscreens</a></li>
275</ul>
276
277<p>You can use one or both of these grouping techniques to organize your app's settings. When
278deciding which to use and how to divide your settings, you should follow the guidelines in Android
279Design's <a href="{@docRoot}design/patterns/settings.html">Settings</a> guide.</p>
280
281
282<h4 id="Titles">Using titles</h4>
283
284<p>If you want to provide dividers with headings between groups of settings (as shown in figure 2),
285place each group of {@link android.preference.Preference} objects inside a {@link
286android.preference.PreferenceCategory}.</p>
287
288<p>For example:</p>
289
290<pre>
291&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
292    &lt;PreferenceCategory 
293        android:title="&#64;string/pref_sms_storage_title"
294        android:key="pref_key_storage_settings">
295        &lt;CheckBoxPreference
296            android:key="pref_key_auto_delete"
297            android:summary="&#64;string/pref_summary_auto_delete"
298            android:title="&#64;string/pref_title_auto_delete"
299            android:defaultValue="false"... />
300        &lt;Preference 
301            android:key="pref_key_sms_delete_limit"
302            android:dependency="pref_key_auto_delete"
303            android:summary="&#64;string/pref_summary_delete_limit"
304            android:title="&#64;string/pref_title_sms_delete"... />
305        &lt;Preference 
306            android:key="pref_key_mms_delete_limit"
307            android:dependency="pref_key_auto_delete"
308            android:summary="&#64;string/pref_summary_delete_limit"
309            android:title="&#64;string/pref_title_mms_delete" ... />
310    &lt;/PreferenceCategory>
311    ...
312&lt;/PreferenceScreen>
313</pre>
314
315
316<h4 id="Subscreens">Using subscreens</h4>
317
318<p>If you want to place groups of settings into a subscreen (as shown in figure 3), place the group
319of {@link android.preference.Preference} objects inside a {@link
320android.preference.PreferenceScreen}.</p>
321
322<img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" />
323<p class="img-caption"><strong>Figure 3.</strong> Setting subscreens. The {@code
324&lt;PreferenceScreen>} element
325creates an item that, when selected, opens a separate list to display the nested settings.</p>
326
327<p>For example:</p>
328
329<pre>
330&lt;PreferenceScreen  xmlns:android="http://schemas.android.com/apk/res/android">
331    &lt;!-- opens a subscreen of settings -->
332    &lt;PreferenceScreen
333        android:key="button_voicemail_category_key"
334        android:title="&#64;string/voicemail"
335        android:persistent="false">
336        &lt;ListPreference
337            android:key="button_voicemail_provider_key"
338            android:title="&#64;string/voicemail_provider" ... />
339        &lt;!-- opens another nested subscreen -->
340        &lt;PreferenceScreen
341            android:key="button_voicemail_setting_key"
342            android:title="&#64;string/voicemail_settings"
343            android:persistent="false">
344            ...
345        &lt;/PreferenceScreen>
346        &lt;RingtonePreference
347            android:key="button_voicemail_ringtone_key"
348            android:title="&#64;string/voicemail_ringtone_title"
349            android:ringtoneType="notification" ... />
350        ...
351    &lt;/PreferenceScreen>
352    ...
353&lt;/PreferenceScreen>
354</pre>
355
356
357<h3 id="Intents">Using intents</h3>
358
359<p>In some cases, you might want a preference item to open a different activity instead of a
360settings screen, such as a web browser to view a web page. To invoke an {@link
361android.content.Intent} when the user selects a preference item, add an {@code &lt;intent&gt;}
362element as a child of the corresponding {@code &lt;Preference&gt;} element.</p>
363
364<p>For example, here's how you can use a preference item to open a web page:</p>
365
366<pre>
367&lt;Preference android:title="@string/prefs_web_page" >
368    &lt;intent android:action="android.intent.action.VIEW"
369            android:data="http://www.example.com" />
370&lt;/Preference>
371</pre>
372
373<p>You can create both implicit and explicit intents using the following attributes:</p>
374
375<dl>
376  <dt>{@code android:action}</dt>
377    <dd>The action to assign, as per the {@link android.content.Intent#setAction setAction()}
378method.</dd>
379  <dt>{@code android:data}</dt>
380    <dd>The data to assign, as per the {@link android.content.Intent#setData setData()} method.</dd>
381  <dt>{@code android:mimeType}</dt>
382    <dd>The MIME type to assign, as per the {@link android.content.Intent#setType setType()}
383method.</dd>
384  <dt>{@code android:targetClass}</dt>
385    <dd>The class part of the component name, as per the {@link android.content.Intent#setComponent
386setComponent()} method.</dd>
387  <dt>{@code android:targetPackage}</dt>
388    <dd>The package part of the component name, as per the {@link
389android.content.Intent#setComponent setComponent()} method.</dd>
390</dl>
391
392
393
394<h2 id="Activity">Creating a Preference Activity</h2>
395
396<p>To display your settings in an activity, extend the {@link
397android.preference.PreferenceActivity} class. This is an extension of the traditional {@link
398android.app.Activity} class that displays a list of settings based on a hierarchy of {@link
399android.preference.Preference} objects. The {@link android.preference.PreferenceActivity}
400automatically persists the settings associated with each {@link
401android.preference.Preference} when the user makes a change.</p>
402
403<p class="note"><strong>Note:</strong> If you're developing your application for Android 3.0 and
404higher, you should instead use {@link android.preference.PreferenceFragment}. Go to the next
405section about <a href="#Fragment">Using Preference Fragments</a>.</p>
406
407<p>The most important thing to remember is that you do not load a layout of views during the {@link
408android.preference.PreferenceActivity#onCreate onCreate()} callback. Instead, you call {@link
409android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} to
410add the preferences you've declared in an XML file to the activity. For example, here's the bare
411minimum code required for a functional {@link android.preference.PreferenceActivity}:</p>
412
413<pre>
414public class SettingsActivity extends PreferenceActivity {
415    &#64;Override
416    public void onCreate(Bundle savedInstanceState) {
417        super.onCreate(savedInstanceState);
418        addPreferencesFromResource(R.xml.preferences);
419    }
420}
421</pre>
422
423<p>This is actually enough code for some apps, because as soon as the user modifies a preference,
424the system saves the changes to a default {@link android.content.SharedPreferences} file that your
425other application components can read when you need to check the user's settings. Many apps,
426however, require a little more code in order to listen for changes that occur to the preferences.
427For information about listening to changes in the {@link android.content.SharedPreferences} file,
428see the section about <a href="#ReadingPrefs">Reading Preferences</a>.</p>
429
430
431
432
433<h2 id="Fragment">Using Preference Fragments</h2>
434
435<p>If you're developing for Android 3.0 (API level 11) and higher, you should use a {@link
436android.preference.PreferenceFragment} to display your list of {@link android.preference.Preference}
437objects. You can add a {@link android.preference.PreferenceFragment} to any activity&mdash;you don't
438need to use {@link android.preference.PreferenceActivity}.</p>
439
440<p><a href="{@docRoot}guide/components/fragments.html">Fragments</a> provide a more
441flexible architecture for your application, compared to using activities alone, no matter what kind
442of activity you're building. As such, we suggest you use {@link
443android.preference.PreferenceFragment} to control the display of your settings instead of {@link
444android.preference.PreferenceActivity} when possible.</p>
445
446<p>Your implementation of {@link android.preference.PreferenceFragment} can be as simple as
447defining the {@link android.preference.PreferenceFragment#onCreate onCreate()} method to load a
448preferences file with {@link android.preference.PreferenceFragment#addPreferencesFromResource
449addPreferencesFromResource()}. For example:</p>
450
451<pre>
452public static class SettingsFragment extends PreferenceFragment {
453    &#64;Override
454    public void onCreate(Bundle savedInstanceState) {
455        super.onCreate(savedInstanceState);
456
457        // Load the preferences from an XML resource
458        addPreferencesFromResource(R.xml.preferences);
459    }
460    ...
461}
462</pre>
463
464<p>You can then add this fragment to an {@link android.app.Activity} just as you would for any other
465{@link android.app.Fragment}. For example:</p>
466
467<pre>
468public class SettingsActivity extends Activity {
469    &#64;Override
470    protected void onCreate(Bundle savedInstanceState) {
471        super.onCreate(savedInstanceState);
472
473        // Display the fragment as the main content.
474        getFragmentManager().beginTransaction()
475                .replace(android.R.id.content, new SettingsFragment())
476                .commit();
477    }
478}
479</pre>
480
481<p class="note"><strong>Note:</strong> A {@link android.preference.PreferenceFragment} doesn't have
482a its own {@link android.content.Context} object. If you need a {@link android.content.Context}
483object, you can call {@link android.app.Fragment#getActivity()}. However, be careful to call
484{@link android.app.Fragment#getActivity()} only when the fragment is attached to an activity. When
485the fragment is not yet attached, or was detached during the end of its lifecycle, {@link
486android.app.Fragment#getActivity()} will return null.</p>
487
488
489<h2 id="Defaults">Setting Default Values</h2>
490
491<p>The preferences you create probably define some important behaviors for your application, so it's
492necessary that you initialize the associated {@link android.content.SharedPreferences} file with
493default values for each {@link android.preference.Preference} when the user first opens your
494application.</p>
495
496<p>The first thing you must do is specify a default value for each {@link
497android.preference.Preference}
498object in your XML file using the {@code android:defaultValue} attribute. The value can be any data
499type that is appropriate for the corresponding {@link android.preference.Preference} object. For
500example:</p>
501
502<pre>
503&lt;!-- default value is a boolean -->
504&lt;CheckBoxPreference
505    android:defaultValue="true"
506    ... />
507
508&lt;!-- default value is a string -->
509&lt;ListPreference
510    android:defaultValue="@string/pref_syncConnectionTypes_default"
511    ... />
512</pre>
513
514<p>Then, from the {@link android.app.Activity#onCreate onCreate()} method in your application's main
515activity&mdash;and in any other activity through which the user may enter your application for the
516first time&mdash;call {@link android.preference.PreferenceManager#setDefaultValues
517setDefaultValues()}:</p>
518
519<pre>
520PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false);
521</pre>
522
523<p>Calling this during {@link android.app.Activity#onCreate onCreate()} ensures that your
524application is properly initialized with default settings, which your application might need to
525read in order to determine some behaviors (such as whether to download data while on a
526cellular network).</p>
527
528<p>This method takes three arguments:</p>
529<ul>
530  <li>Your application {@link android.content.Context}.</li>
531  <li>The resource ID for the preference XML file for which you want to set the default values.</li>
532  <li>A boolean indicating whether the default values should be set more than once.
533<p>When <code>false</code>, the system sets the default values only if this method has never been
534called in the past (or the {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES}
535in the default value shared preferences file is false).</p></li>
536</ul>
537
538<p>As long as you set the third argument to <code>false</code>, you can safely call this method
539every time your activity starts without overriding the user's saved preferences by resetting them to
540the defaults. However, if you set it to <code>true</code>, you will override any previous
541values with the defaults.</p>
542
543
544
545<h2 id="PreferenceHeaders">Using Preference Headers</h2>
546
547<p>In rare cases, you might want to design your settings such that the first screen
548displays only a list of <a href="#Subscreens">subscreens</a> (such as in the system Settings app,
549as shown in figures 4 and 5). When you're developing such a design for Android 3.0 and higher, you
550should use a new "headers" feature in Android 3.0, instead of building subscreens with nested
551{@link android.preference.PreferenceScreen} elements.</p>
552
553<p>To build your settings with headers, you need to:</p>
554<ol>
555  <li>Separate each group of settings into separate instances of {@link
556android.preference.PreferenceFragment}. That is, each group of settings needs a separate XML
557file.</li>
558  <li>Create an XML headers file that lists each settings group and declares which fragment
559contains the corresponding list of settings.</li>
560  <li>Extend the {@link android.preference.PreferenceActivity} class to host your settings.</li>
561  <li>Implement the {@link
562android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} callback to specify the
563headers file.</li>
564</ol>
565
566<p>A great benefit to using this design is that {@link android.preference.PreferenceActivity}
567automatically presents the two-pane layout shown in figure 4 when running on large screens.</p>
568
569<p>Even if your application supports versions of Android older than 3.0, you can build your
570application to use {@link android.preference.PreferenceFragment} for a two-pane presentation on
571newer devices while still supporting a traditional multi-screen hierarchy on older
572devices (see the section about <a href="#BackCompatHeaders">Supporting older versions with
573preference headers</a>).</p>
574
575<img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" />
576<p class="img-caption"><strong>Figure 4.</strong> Two-pane layout with headers. <br/><b>1.</b> The
577headers are defined with an XML headers file. <br/><b>2.</b> Each group of settings is defined by a
578{@link android.preference.PreferenceFragment} that's specified by a {@code &lt;header>} element in
579the headers file.</p>
580
581<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" />
582<p class="img-caption"><strong>Figure 5.</strong> A handset device with setting headers. When an
583item is selected, the associated {@link android.preference.PreferenceFragment} replaces the
584headers.</p>
585
586
587<h3 id="CreateHeaders" style="clear:left">Creating the headers file</h3>
588
589<p>Each group of settings in your list of headers is specified by a single {@code &lt;header>}
590element inside a root {@code &lt;preference-headers>} element. For example:</p>
591
592<pre>
593&lt;?xml version="1.0" encoding="utf-8"?>
594&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
595    &lt;header 
596        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne"
597        android:title="@string/prefs_category_one"
598        android:summary="@string/prefs_summ_category_one" />
599    &lt;header 
600        android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo"
601        android:title="@string/prefs_category_two"
602        android:summary="@string/prefs_summ_category_two" >
603        &lt;!-- key/value pairs can be included as arguments for the fragment. -->
604        &lt;extra android:name="someKey" android:value="someHeaderValue" />
605    &lt;/header>
606&lt;/preference-headers>
607</pre>
608
609<p>With the {@code android:fragment} attribute, each header declares an instance of {@link
610android.preference.PreferenceFragment} that should open when the user selects the header.</p>
611
612<p>The {@code &lt;extras>} element allows you to pass key-value pairs to the fragment in a {@link
613android.os.Bundle}. The fragment can retrieve the arguments by calling {@link
614android.app.Fragment#getArguments()}. You might pass arguments to the fragment for a variety of
615reasons, but one good reason is to reuse the same subclass of {@link
616android.preference.PreferenceFragment} for each group and use the argument to specify which
617preferences XML file the fragment should load.</p>
618
619<p>For example, here's a fragment that can be reused for multiple settings groups, when each
620header defines an {@code &lt;extra>} argument with the {@code "settings"} key:</p>
621
622<pre>
623public static class SettingsFragment extends PreferenceFragment {
624    &#64;Override
625    public void onCreate(Bundle savedInstanceState) {
626        super.onCreate(savedInstanceState);
627
628        String settings = getArguments().getString("settings");
629        if ("notifications".equals(settings)) {
630            addPreferencesFromResource(R.xml.settings_wifi);
631        } else if ("sync".equals(settings)) {
632            addPreferencesFromResource(R.xml.settings_sync);
633        }
634    }
635}
636</pre>
637
638
639
640<h3 id="DisplayHeaders">Displaying the headers</h3>
641
642<p>To display the preference headers, you must implement the {@link
643android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} callback method and call
644{@link android.preference.PreferenceActivity#loadHeadersFromResource
645loadHeadersFromResource()}. For example:</p>
646
647<pre>
648public class SettingsActivity extends PreferenceActivity {
649    &#64;Override
650    public void onBuildHeaders(List&lt;Header> target) {
651        loadHeadersFromResource(R.xml.preference_headers, target);
652    }
653}
654</pre>
655
656<p>When the user selects an item from the list of headers, the system opens the associated {@link
657android.preference.PreferenceFragment}.</p>
658
659<p class="note"><strong>Note:</strong> When using preference headers, your subclass of {@link
660android.preference.PreferenceActivity} doesn't need to implement the {@link
661android.preference.PreferenceActivity#onCreate onCreate()} method, because the only required
662task for the activity is to load the headers.</p>
663
664
665<h3 id="BackCompatHeaders">Supporting older versions with preference headers</h3>
666
667<p>If your application supports versions of Android older than 3.0, you can still use headers to
668provide a two-pane layout when running on Android 3.0 and higher. All you need to do is create an
669additional preferences XML file that uses basic {@link android.preference.Preference
670&lt;Preference>} elements that behave like the header items (to be used by the older Android
671versions).</p>
672
673<p>Instead of opening a new {@link android.preference.PreferenceScreen}, however, each of the {@link
674android.preference.Preference &lt;Preference>} elements sends an {@link android.content.Intent} to
675the {@link android.preference.PreferenceActivity} that specifies which preference XML file to
676load.</p>
677
678<p>For example, here's an XML file for preference headers that is used on Android 3.0
679and higher ({@code res/xml/preference_headers.xml}):</p> 
680
681<pre>
682&lt;preference-headers xmlns:android="http://schemas.android.com/apk/res/android">
683    &lt;header 
684        android:fragment="com.example.prefs.SettingsFragmentOne"
685        android:title="@string/prefs_category_one"
686        android:summary="@string/prefs_summ_category_one" />
687    &lt;header 
688        android:fragment="com.example.prefs.SettingsFragmentTwo"
689        android:title="@string/prefs_category_two"
690        android:summary="@string/prefs_summ_category_two" />
691&lt;/preference-headers>
692</pre>
693
694<p>And here is a preference file that provides the same headers for versions older than
695Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):</p>
696
697<pre>
698&lt;PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
699    &lt;Preference 
700        android:title="@string/prefs_category_one"
701        android:summary="@string/prefs_summ_category_one"  >
702        &lt;intent 
703            android:targetPackage="com.example.prefs"
704            android:targetClass="com.example.prefs.SettingsActivity"
705            android:action="com.example.prefs.PREFS_ONE" />
706    &lt;/Preference>
707    &lt;Preference 
708        android:title="@string/prefs_category_two"
709        android:summary="@string/prefs_summ_category_two" >
710        &lt;intent 
711            android:targetPackage="com.example.prefs"
712            android:targetClass="com.example.prefs.SettingsActivity"
713            android:action="com.example.prefs.PREFS_TWO" />
714    &lt;/Preference>
715&lt;/PreferenceScreen>
716</pre>
717
718<p>Because support for {@code &lt;preference-headers>} was added in Android 3.0, the system calls
719{@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} in your {@link
720android.preference.PreferenceActivity} only when running on Androd 3.0 or higher. In order to load
721the "legacy" headers file ({@code preference_headers_legacy.xml}), you must check the Android
722version and, if the version is older than Android 3.0 ({@link
723android.os.Build.VERSION_CODES#HONEYCOMB}), call {@link
724android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} to
725load the legacy header file. For example:</p>
726
727<pre>
728&#64;Override
729public void onCreate(Bundle savedInstanceState) {
730    super.onCreate(savedInstanceState);
731    ...
732
733    if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
734        // Load the legacy preferences headers
735        addPreferencesFromResource(R.xml.preference_headers_legacy);
736    }
737}
738
739// Called only on Honeycomb and later
740&#64;Override
741public void onBuildHeaders(List&lt;Header> target) {
742   loadHeadersFromResource(R.xml.preference_headers, target);
743}
744</pre>
745
746<p>The only thing left to do is handle the {@link android.content.Intent} that's passed into the
747activity to identify which preference file to load. So retrieve the intent's action and compare it
748to known action strings that you've used in the preference XML's {@code &lt;intent>} tags:</p>
749
750<pre>
751final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE";
752...
753
754&#64;Override
755public void onCreate(Bundle savedInstanceState) {
756    super.onCreate(savedInstanceState);
757
758    String action = getIntent().getAction();
759    if (action != null &amp;&amp; action.equals(ACTION_PREFS_ONE)) {
760        addPreferencesFromResource(R.xml.preferences);
761    }
762    ...
763
764    else if (Build.VERSION.SDK_INT &lt; Build.VERSION_CODES.HONEYCOMB) {
765        // Load the legacy preferences headers
766        addPreferencesFromResource(R.xml.preference_headers_legacy);
767    }
768}
769</pre>
770
771<p>Beware that consecutive calls to {@link
772android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} will
773stack all the preferences in a single list, so be sure that it's only called once by chaining the
774conditions with else-if statements.</p>
775
776
777
778
779
780<h2 id="ReadingPrefs">Reading Preferences</h2>
781
782<p>By default, all your app's preferences are saved to a file that's accessible from anywhere
783within your application by calling the static method {@link
784android.preference.PreferenceManager#getDefaultSharedPreferences
785PreferenceManager.getDefaultSharedPreferences()}. This returns the {@link
786android.content.SharedPreferences} object containing all the key-value pairs that are associated
787with the {@link android.preference.Preference} objects used in your {@link
788android.preference.PreferenceActivity}.</p>
789
790<p>For example, here's how you can read one of the preference values from any other activity in your
791application:</p>
792
793<pre>
794SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
795String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, "");
796</pre>
797
798
799
800<h3 id="Listening">Listening for preference changes</h3>
801
802<p>There are several reasons you might want to be notified as soon as the use changes one of the
803preferences. In order to receive a callback when a change happens to any one of the preferences,
804implement the {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener
805SharedPreference.OnSharedPreferenceChangeListener} interface and register the listener for the
806{@link android.content.SharedPreferences} object by calling {@link
807android.content.SharedPreferences#registerOnSharedPreferenceChangeListener
808registerOnSharedPreferenceChangeListener()}.</p>
809
810<p>The interface has only one callback method, {@link
811android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged
812onSharedPreferenceChanged()}, and you might find it easiest to implement the interface as a part of
813your activity. For example:</p>
814
815<pre>
816public class SettingsActivity extends PreferenceActivity
817                              implements OnSharedPreferenceChangeListener {
818    public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType";
819    ...
820
821    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
822        if (key.equals(KEY_PREF_SYNC_CONN)) {
823            Preference connectionPref = findPreference(key);
824            // Set summary to be the user-description for the selected value
825            connectionPref.setSummary(sharedPreferences.getString(key, ""));
826        }
827    }
828}
829</pre>
830
831<p>In this example, the method checks whether the changed setting is for a known preference key. It
832calls {@link android.preference.PreferenceActivity#findPreference findPreference()} to get the
833{@link android.preference.Preference} object that was changed so it can modify the item's
834summary to be a description of the user's selection. That is, when the setting is a {@link
835android.preference.ListPreference} or other multiple choice setting, you should call {@link
836android.preference.Preference#setSummary setSummary()} when the setting changes to display the
837current status (such as the Sleep setting shown in figure 5).</p>
838
839<p class="note"><strong>Note:</strong> As described in the Android Design document about <a
840href="{@docRoot}design/patterns/settings.html">Settings</a>, we recommend that you update the
841summary for a {@link android.preference.ListPreference} each time the user changes the preference in
842order to describe the current setting.</p>
843
844<p>For proper lifecycle management in the activity, we recommend that you register and unregister
845your {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} during the {@link
846android.app.Activity#onResume} and {@link android.app.Activity#onPause} callbacks, respectively:</p>
847
848<pre>
849&#64;Override
850protected void onResume() {
851    super.onResume();
852    getPreferenceScreen().getSharedPreferences()
853            .registerOnSharedPreferenceChangeListener(this);
854}
855
856&#64;Override
857protected void onPause() {
858    super.onPause();
859    getPreferenceScreen().getSharedPreferences()
860            .unregisterOnSharedPreferenceChangeListener(this);
861}
862</pre>
863
864
865
866<h2 id="NetworkUsage">Managing Network Usage</h2>
867
868
869<p>Beginning with Android 4.0, the system's Settings application allows users to see how much
870network data their applications are using while in the foreground and background. Users can then
871disable the use of background data for individual apps. In order to avoid users disabling your app's
872access to data from the background, you should use the data connection efficiently and allow
873users to refine your app's data usage through your application settings.<p>
874
875<p>For example, you might allow the user to control how often your app syncs data, whether your app
876performs uploads/downloads only when on Wi-Fi, whether your app uses data while roaming, etc. With
877these controls available to them, users are much less likely to disable your app's access to data
878when they approach the limits they set in the system Settings, because they can instead precisely
879control how much data your app uses.</p>
880
881<p>Once you've added the necessary preferences in your {@link android.preference.PreferenceActivity}
882to control your app's data habits, you should add an intent filter for {@link
883android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} in your manifest file. For example:</p>
884
885<pre>
886&lt;activity android:name="SettingsActivity" ... >
887    &lt;intent-filter>
888       &lt;action android:name="android.intent.action.MANAGE_NETWORK_USAGE" />
889       &lt;category android:name="android.intent.category.DEFAULT" />
890    &lt;/intent-filter>
891&lt;/activity>
892</pre>
893
894<p>This intent filter indicates to the system that this is the activity that controls your
895application's data usage. Thus, when the user inspects how much data your app is using from the
896system's Settings app, a <em>View application settings</em> button is available that launches your
897{@link android.preference.PreferenceActivity} so the user can refine how much data your app
898uses.</p>
899
900
901
902
903
904
905
906<h2 id="Custom">Building a Custom Preference</h2>
907
908<p>The Android framework includes a variety of {@link android.preference.Preference} subclasses that
909allow you to build a UI for several different types of settings.
910However, you might discover a setting you need for which there’s no built-in solution, such as a
911number picker or date picker. In such a case, you’ll need to create a custom preference by extending
912the {@link android.preference.Preference} class or one of the other subclasses.</p>
913
914<p>When you extend the {@link android.preference.Preference} class, there are a few important
915things you need to do:</p>
916
917<ul>
918  <li>Specify the user interface that appears when the user selects the settings.</li>
919  <li>Save the setting's value when appropriate.</li>
920  <li>Initialize the {@link android.preference.Preference} with the current (or default) value
921when it comes into view.</li>
922  <li>Provide the default value when requested by the system.</li>
923  <li>If the {@link android.preference.Preference} provides its own UI (such as a dialog), save
924and restore the state to handle lifecycle changes (such as when the user rotates the screen).</li>
925</ul>
926
927<p>The following sections describe how to accomplish each of these tasks.</p>
928
929
930
931<h3 id="CustomSelected">Specifying the user interface</h3>
932
933  <p>If you directly extend the {@link android.preference.Preference} class, you need to implement
934{@link android.preference.Preference#onClick()} to define the action that occurs when the user
935selects the item. However, most custom settings extend {@link android.preference.DialogPreference} to
936show a dialog, which simplifies the procedure. When you extend {@link
937android.preference.DialogPreference}, you must call {@link
938android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()} during in the
939class constructor to specify the layout for the dialog.</p>
940
941  <p>For example, here's the constructor for a custom {@link
942android.preference.DialogPreference} that declares the layout and specifies the text for the
943default positive and negative dialog buttons:</p>
944
945<pre>
946public class NumberPickerPreference extends DialogPreference {
947    public NumberPickerPreference(Context context, AttributeSet attrs) {
948        super(context, attrs);
949        
950        setDialogLayoutResource(R.layout.numberpicker_dialog);
951        setPositiveButtonText(android.R.string.ok);
952        setNegativeButtonText(android.R.string.cancel);
953        
954        setDialogIcon(null);
955    }
956    ...
957}
958</pre>
959
960
961
962<h3 id="CustomSave">Saving the setting's value</h3>
963
964<p>You can save a value for the setting at any time by calling one of the {@link
965android.preference.Preference} class's {@code persist*()} methods, such as {@link
966android.preference.Preference#persistInt persistInt()} if the setting's value is an integer or
967{@link android.preference.Preference#persistBoolean persistBoolean()} to save a boolean.</p>
968
969<p class="note"><strong>Note:</strong> Each {@link android.preference.Preference} can save only one
970data type, so you must use the {@code persist*()} method appropriate for the data type used by your
971custom {@link android.preference.Preference}.</p>
972
973<p>When you choose to persist the setting can depend on which {@link
974android.preference.Preference} class you extend. If you extend {@link
975android.preference.DialogPreference}, then you should persist the value only when the dialog
976closes due to a positive result (the user selects the "OK" button).</p>
977
978<p>When a {@link android.preference.DialogPreference} closes, the system calls the {@link
979android.preference.DialogPreference#onDialogClosed onDialogClosed()} method. The method includes a
980boolean argument that specifies whether the user result is "positive"&mdash;if the value is
981<code>true</code>, then the user selected the positive button and you should save the new value. For
982example:</p>
983
984<pre>
985&#64;Override
986protected void onDialogClosed(boolean positiveResult) {
987    // When the user selects "OK", persist the new value
988    if (positiveResult) {
989        persistInt(mNewValue);
990    }
991}
992</pre>
993
994<p>In this example, <code>mNewValue</code> is a class member that holds the setting's current
995value. Calling {@link android.preference.Preference#persistInt persistInt()} saves the value to
996the {@link android.content.SharedPreferences} file (automatically using the key that's
997specified in the XML file for this {@link android.preference.Preference}).</p>
998
999
1000<h3 id="CustomInitialize">Initializing the current value</h3>
1001
1002<p>When the system adds your {@link android.preference.Preference} to the screen, it
1003calls {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} to notify
1004you whether the setting has a persisted value. If there is no persisted value, this call provides
1005you the default value.</p>
1006
1007<p>The {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} method passes
1008a boolean, <code>restorePersistedValue</code>, to indicate whether a value has already been persisted
1009for the setting. If it is <code>true</code>, then you should retrieve the persisted value by calling
1010one of the {@link
1011android.preference.Preference} class's {@code getPersisted*()} methods, such as {@link
1012android.preference.Preference#getPersistedInt getPersistedInt()} for an integer value. You'll
1013usually want to retrieve the persisted value so you can properly update the UI to reflect the
1014previously saved value.</p>
1015
1016<p>If <code>restorePersistedValue</code> is <code>false</code>, then you
1017should use the default value that is passed in the second argument.</p>
1018
1019<pre>
1020&#64;Override
1021protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
1022    if (restorePersistedValue) {
1023        // Restore existing state
1024        mCurrentValue = this.getPersistedInt(DEFAULT_VALUE);
1025    } else {
1026        // Set default state from the XML attribute
1027        mCurrentValue = (Integer) defaultValue;
1028        persistInt(mCurrentValue);
1029    }
1030}
1031</pre>
1032
1033<p>Each {@code getPersisted*()} method takes an argument that specifies the
1034default value to use in case there is actually no persisted value or the key does not exist. In
1035the example above, a local constant is used to specify the default value in case {@link
1036android.preference.Preference#getPersistedInt getPersistedInt()} can't return a persisted value.</p>
1037
1038<p class="caution"><strong>Caution:</strong> You <strong>cannot</strong> use the
1039<code>defaultValue</code> as the default value in the {@code getPersisted*()} method, because
1040its value is always null when <code>restorePersistedValue</code> is <code>true</code>.</p>
1041
1042
1043<h3 id="CustomDefault">Providing a default value</h3>
1044
1045<p>If the instance of your {@link android.preference.Preference} class specifies a default value
1046(with the {@code android:defaultValue} attribute), then the
1047system calls {@link android.preference.Preference#onGetDefaultValue
1048onGetDefaultValue()} when it instantiates the object in order to retrieve the value. You must
1049implement this method in order for the system to save the default value in the {@link
1050android.content.SharedPreferences}. For example:</p>
1051
1052<pre>
1053&#64;Override
1054protected Object onGetDefaultValue(TypedArray a, int index) {
1055    return a.getInteger(index, DEFAULT_VALUE);
1056}
1057</pre>
1058
1059<p>The method arguments provide everything you need: the array of attributes and the index
1060position of the {@code android:defaultValue}, which you must retrieve. The reason you must
1061implement this method to extract the default value from the attribute is because you must specify
1062a local default value for the attribute in case the value is undefined.</p>
1063
1064
1065
1066<h3 id="CustomSaveState">Saving and restoring the Preference's state</h3>
1067
1068<p>Just like a {@link android.view.View} in a layout, your {@link android.preference.Preference}
1069subclass is responsible for saving and restoring its state in case the activity or fragment is
1070restarted (such as when the user rotates the screen). To properly save and
1071restore the state of your {@link android.preference.Preference} class, you must implement the
1072lifecycle callback methods {@link android.preference.Preference#onSaveInstanceState
1073onSaveInstanceState()} and {@link
1074android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.</p>
1075
1076<p>The state of your {@link android.preference.Preference} is defined by an object that implements
1077the {@link android.os.Parcelable} interface. The Android framework provides such an object for you
1078as a starting point to define your state object: the {@link
1079android.preference.Preference.BaseSavedState} class.</p>
1080
1081<p>To define how your {@link android.preference.Preference} class saves its state, you should
1082extend the {@link android.preference.Preference.BaseSavedState} class. You need to override just
1083 a few methods and define the {@link android.preference.Preference.BaseSavedState#CREATOR}
1084object.</p>
1085
1086<p>For most apps, you can copy the following implementation and simply change the lines that
1087handle the {@code value} if your {@link android.preference.Preference} subclass saves a data
1088type other than an integer.</p>
1089
1090<pre>
1091private static class SavedState extends BaseSavedState {
1092    // Member that holds the setting's value
1093    // Change this data type to match the type saved by your Preference
1094    int value;
1095
1096    public SavedState(Parcelable superState) {
1097        super(superState);
1098    }
1099
1100    public SavedState(Parcel source) {
1101        super(source);
1102        // Get the current preference's value
1103        value = source.readInt();  // Change this to read the appropriate data type
1104    }
1105
1106    &#64;Override
1107    public void writeToParcel(Parcel dest, int flags) {
1108        super.writeToParcel(dest, flags);
1109        // Write the preference's value
1110        dest.writeInt(value);  // Change this to write the appropriate data type
1111    }
1112
1113    // Standard creator object using an instance of this class
1114    public static final Parcelable.Creator&lt;SavedState> CREATOR =
1115            new Parcelable.Creator&lt;SavedState>() {
1116
1117        public SavedState createFromParcel(Parcel in) {
1118            return new SavedState(in);
1119        }
1120
1121        public SavedState[] newArray(int size) {
1122            return new SavedState[size];
1123        }
1124    };
1125}
1126</pre>
1127
1128<p>With the above implementation of {@link android.preference.Preference.BaseSavedState} added
1129to your app (usually as a subclass of your {@link android.preference.Preference} subclass), you
1130then need to implement the {@link android.preference.Preference#onSaveInstanceState
1131onSaveInstanceState()} and {@link
1132android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} methods for your
1133{@link android.preference.Preference} subclass.</p>
1134
1135<p>For example:</p>
1136
1137<pre>
1138&#64;Override
1139protected Parcelable onSaveInstanceState() {
1140    final Parcelable superState = super.onSaveInstanceState();
1141    // Check whether this Preference is persistent (continually saved)
1142    if (isPersistent()) {
1143        // No need to save instance state since it's persistent, use superclass state
1144        return superState;
1145    }
1146
1147    // Create instance of custom BaseSavedState
1148    final SavedState myState = new SavedState(superState);
1149    // Set the state's value with the class member that holds current setting value
1150    myState.value = mNewValue;
1151    return myState;
1152}
1153
1154&#64;Override
1155protected void onRestoreInstanceState(Parcelable state) {
1156    // Check whether we saved the state in onSaveInstanceState
1157    if (state == null || !state.getClass().equals(SavedState.class)) {
1158        // Didn't save the state, so call superclass
1159        super.onRestoreInstanceState(state);
1160        return;
1161    }
1162
1163    // Cast state to custom BaseSavedState and pass to superclass
1164    SavedState myState = (SavedState) state;
1165    super.onRestoreInstanceState(myState.getSuperState());
1166    
1167    // Set this Preference's widget to reflect the restored state
1168    mNumberPicker.setValue(myState.value);
1169}
1170</pre>
1171
1172