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