1 page.title=Settings 2 page.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 61 href="{@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 70 example, some apps allow users to specify whether notifications are enabled or specify how often the 71 application syncs data with the cloud.</p> 72 73 <p>If you want to provide settings for your app, you should use 74 Android's {@link android.preference.Preference} APIs to build an interface that's consistent with 75 the user experience in other Android apps (including the system settings). This document describes 76 how 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 81 href="{@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 87 settings. Selecting an item defined by a {@link android.preference.Preference} 88 opens 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 96 built using various subclasses of the {@link android.preference.Preference} class that you 97 declare in an XML file.</p> 98 99 <p>A {@link android.preference.Preference} object is the building block for a single 100 setting. Each {@link android.preference.Preference} appears as an item in a list and provides the 101 appropriate UI for users to modify the setting. For example, a {@link 102 android.preference.CheckBoxPreference} creates a list item that shows a checkbox, and a {@link 103 android.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 106 the system uses to save the setting in a default {@link android.content.SharedPreferences} 107 file for your app's settings. When the user changes a setting, the system updates the corresponding 108 value in the {@link android.content.SharedPreferences} file for you. The only time you should 109 directly interact with the associated {@link android.content.SharedPreferences} file is when you 110 need 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 113 following 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 125 instead 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 131 build 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} 133 that hosts a {@link android.preference.PreferenceFragment} that displays your app settings. 134 However, you can also use {@link android.preference.PreferenceActivity} to create a two-pane layout 135 for 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 139 android.preference.PreferenceFragment} is discussed in the sections about <a 140 href="#Activity">Creating a Preference Activity</a> and <a href="#Fragment">Using 141 Preference 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 147 android.preference.Preference} class. Each subclass includes a set of core properties that allow you 148 to specify things such as a title for the setting and the default value. Each subclass also provides 149 its own specialized properties and user interface. For instance, figure 1 shows a screenshot from 150 the Messaging app's settings. Each list item in the settings screen is backed by a different {@link 151 android.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 158 value 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 162 can 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 166 java.lang.String}.</dd> 167 </dl> 168 169 <p>See the {@link android.preference.Preference} class for a list of all other subclasses and their 170 corresponding properties.</p> 171 172 <p>Of course, the built-in classes don't accommodate every need and your application might require 173 something more specialized. For example, the platform currently does not provide a {@link 174 android.preference.Preference} class for picking a number or a date. So you might need to define 175 your own {@link android.preference.Preference} subclass. For help doing so, see the section about <a 176 href="#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 183 should define your list of settings in XML with a hierarchy of {@link android.preference.Preference} 184 objects. Using an XML file to define your collection of settings is preferred because the file 185 provides an easy-to-read structure that's simple to update. Also, your app's settings are 186 generally 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 189 matches the class name, such as {@code <CheckBoxPreference>}.</p> 190 191 <p>You must save the XML file in the {@code res/xml/} directory. Although you can name the file 192 anything you want, it's traditionally named {@code preferences.xml}. You usually need only one file, 193 because branches in the hierarchy (that open their own list of settings) are declared using nested 194 instances 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 197 settings, 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 <PreferenceScreen>} element. Within this element is where you add each {@link 201 android.preference.Preference}. Each child you add within the 202 {@link android.preference.PreferenceScreen <PreferenceScreen>} element appears as a single 203 item in the list of settings.</p> 204 205 <p>For example:</p> 206 207 <pre> 208 <?xml version="1.0" encoding="utf-8"?> 209 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 210 <CheckBoxPreference 211 android:key="pref_sync" 212 android:title="@string/pref_sync" 213 android:summary="@string/pref_sync_summ" 214 android:defaultValue="true" /> 215 <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 </PreferenceScreen> 224 </pre> 225 226 <p>In this example, there's a {@link android.preference.CheckBoxPreference} and a {@link 227 android.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 232 key (a string) the system uses when saving this setting's value in the {@link 233 android.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 236 preference specifies an {@link android.content.Intent} to invoke (with an <a 237 href="#Intents">{@code <intent>}</a> element) or a {@link android.app.Fragment} to display (with an <a 238 href="{@docRoot}reference/android/preference/Preference.html#attr_android:fragment">{@code 239 android: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 245 android.content.SharedPreferences} file. You should supply a default value for all 246 settings.</dd> 247 </dl> 248 249 <p>For information about all other supported attributes, see the {@link 250 android.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 257 android.preference.PreferenceCategory <PreferenceCategory>} element. <br/><b>2.</b> The title is 258 specified 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 263 define groups of settings or display those groups in a 264 separate 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 270 may have difficulty scanning, comprehending, and processing them. You can remedy this by 271 dividing some or all of the settings into groups, effectively turning one long list into multiple 272 shorter 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 280 deciding which to use and how to divide your settings, you should follow the guidelines in Android 281 Design'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), 287 place each group of {@link android.preference.Preference} objects inside a {@link 288 android.preference.PreferenceCategory}.</p> 289 290 <p>For example:</p> 291 292 <pre> 293 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 294 <PreferenceCategory 295 android:title="@string/pref_sms_storage_title" 296 android:key="pref_key_storage_settings"> 297 <CheckBoxPreference 298 android:key="pref_key_auto_delete" 299 android:summary="@string/pref_summary_auto_delete" 300 android:title="@string/pref_title_auto_delete" 301 android:defaultValue="false"... /> 302 <Preference 303 android:key="pref_key_sms_delete_limit" 304 android:dependency="pref_key_auto_delete" 305 android:summary="@string/pref_summary_delete_limit" 306 android:title="@string/pref_title_sms_delete"... /> 307 <Preference 308 android:key="pref_key_mms_delete_limit" 309 android:dependency="pref_key_auto_delete" 310 android:summary="@string/pref_summary_delete_limit" 311 android:title="@string/pref_title_mms_delete" ... /> 312 </PreferenceCategory> 313 ... 314 </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 321 of {@link android.preference.Preference} objects inside a {@link 322 android.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 <PreferenceScreen>} element 327 creates 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 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 333 <!-- opens a subscreen of settings --> 334 <PreferenceScreen 335 android:key="button_voicemail_category_key" 336 android:title="@string/voicemail" 337 android:persistent="false"> 338 <ListPreference 339 android:key="button_voicemail_provider_key" 340 android:title="@string/voicemail_provider" ... /> 341 <!-- opens another nested subscreen --> 342 <PreferenceScreen 343 android:key="button_voicemail_setting_key" 344 android:title="@string/voicemail_settings" 345 android:persistent="false"> 346 ... 347 </PreferenceScreen> 348 <RingtonePreference 349 android:key="button_voicemail_ringtone_key" 350 android:title="@string/voicemail_ringtone_title" 351 android:ringtoneType="notification" ... /> 352 ... 353 </PreferenceScreen> 354 ... 355 </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 362 settings screen, such as a web browser to view a web page. To invoke an {@link 363 android.content.Intent} when the user selects a preference item, add an {@code <intent>} 364 element as a child of the corresponding {@code <Preference>} 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 <Preference android:title="@string/prefs_web_page" > 370 <intent android:action="android.intent.action.VIEW" 371 android:data="http://www.example.com" /> 372 </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()} 380 method.</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()} 385 method.</dd> 386 <dt>{@code android:targetClass}</dt> 387 <dd>The class part of the component name, as per the {@link android.content.Intent#setComponent 388 setComponent()} method.</dd> 389 <dt>{@code android:targetPackage}</dt> 390 <dd>The package part of the component name, as per the {@link 391 android.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 399 android.preference.PreferenceActivity} class. This is an extension of the traditional {@link 400 android.app.Activity} class that displays a list of settings based on a hierarchy of {@link 401 android.preference.Preference} objects. The {@link android.preference.PreferenceActivity} 402 automatically persists the settings associated with each {@link 403 android.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 406 higher, you should instead use {@link android.preference.PreferenceFragment}. Go to the next 407 section 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 410 android.preference.PreferenceActivity#onCreate onCreate()} callback. Instead, you call {@link 411 android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} to 412 add the preferences you've declared in an XML file to the activity. For example, here's the bare 413 minimum code required for a functional {@link android.preference.PreferenceActivity}:</p> 414 415 <pre> 416 public class SettingsActivity extends PreferenceActivity { 417 @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, 426 the system saves the changes to a default {@link android.content.SharedPreferences} file that your 427 other application components can read when you need to check the user's settings. Many apps, 428 however, require a little more code in order to listen for changes that occur to the preferences. 429 For information about listening to changes in the {@link android.content.SharedPreferences} file, 430 see 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 438 android.preference.PreferenceFragment} to display your list of {@link android.preference.Preference} 439 objects. You can add a {@link android.preference.PreferenceFragment} to any activity—you don't 440 need to use {@link android.preference.PreferenceActivity}.</p> 441 442 <p><a href="{@docRoot}guide/components/fragments.html">Fragments</a> provide a more 443 flexible architecture for your application, compared to using activities alone, no matter what kind 444 of activity you're building. As such, we suggest you use {@link 445 android.preference.PreferenceFragment} to control the display of your settings instead of {@link 446 android.preference.PreferenceActivity} when possible.</p> 447 448 <p>Your implementation of {@link android.preference.PreferenceFragment} can be as simple as 449 defining the {@link android.preference.PreferenceFragment#onCreate onCreate()} method to load a 450 preferences file with {@link android.preference.PreferenceFragment#addPreferencesFromResource 451 addPreferencesFromResource()}. For example:</p> 452 453 <pre> 454 public static class SettingsFragment extends PreferenceFragment { 455 @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> 470 public class SettingsActivity extends Activity { 471 @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 484 a its own {@link android.content.Context} object. If you need a {@link android.content.Context} 485 object, 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 487 the fragment is not yet attached, or was detached during the end of its lifecycle, {@link 488 android.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 494 necessary that you initialize the associated {@link android.content.SharedPreferences} file with 495 default values for each {@link android.preference.Preference} when the user first opens your 496 application.</p> 497 498 <p>The first thing you must do is specify a default value for each {@link 499 android.preference.Preference} 500 object in your XML file using the {@code android:defaultValue} attribute. The value can be any data 501 type that is appropriate for the corresponding {@link android.preference.Preference} object. For 502 example:</p> 503 504 <pre> 505 <!-- default value is a boolean --> 506 <CheckBoxPreference 507 android:defaultValue="true" 508 ... /> 509 510 <!-- default value is a string --> 511 <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 517 activity—and in any other activity through which the user may enter your application for the 518 first time—call {@link android.preference.PreferenceManager#setDefaultValues 519 setDefaultValues()}:</p> 520 521 <pre> 522 PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false); 523 </pre> 524 525 <p>Calling this during {@link android.app.Activity#onCreate onCreate()} ensures that your 526 application is properly initialized with default settings, which your application might need to 527 read in order to determine some behaviors (such as whether to download data while on a 528 cellular 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 536 called in the past (or the {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES} 537 in 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 541 every time your activity starts without overriding the user's saved preferences by resetting them to 542 the defaults. However, if you set it to <code>true</code>, you will override any previous 543 values 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 550 displays only a list of <a href="#Subscreens">subscreens</a> (such as in the system Settings app, 551 as shown in figures 4 and 5). When you're developing such a design for Android 3.0 and higher, you 552 should use the "headers" feature 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 558 android.preference.PreferenceFragment}. That is, each group of settings needs a separate XML 559 file.</li> 560 <li>Create an XML headers file that lists each settings group and declares which fragment 561 contains 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 564 android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} callback to specify the 565 headers file.</li> 566 </ol> 567 568 <p>A great benefit to using this design is that {@link android.preference.PreferenceActivity} 569 automatically 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 572 application to use {@link android.preference.PreferenceFragment} for a two-pane presentation on 573 newer devices while still supporting a traditional multi-screen hierarchy on older 574 devices (see the section about <a href="#BackCompatHeaders">Supporting older versions with 575 preference 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 579 headers 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 <header>} element in 581 the 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 585 item is selected, the associated {@link android.preference.PreferenceFragment} replaces the 586 headers.</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 <header>} 592 element inside a root {@code <preference-headers>} element. For example:</p> 593 594 <pre> 595 <?xml version="1.0" encoding="utf-8"?> 596 <preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> 597 <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 <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 <!-- key/value pairs can be included as arguments for the fragment. --> 606 <extra android:name="someKey" android:value="someHeaderValue" /> 607 </header> 608 </preference-headers> 609 </pre> 610 611 <p>With the {@code android:fragment} attribute, each header declares an instance of {@link 612 android.preference.PreferenceFragment} that should open when the user selects the header.</p> 613 614 <p>The {@code <extras>} element allows you to pass key-value pairs to the fragment in a {@link 615 android.os.Bundle}. The fragment can retrieve the arguments by calling {@link 616 android.app.Fragment#getArguments()}. You might pass arguments to the fragment for a variety of 617 reasons, but one good reason is to reuse the same subclass of {@link 618 android.preference.PreferenceFragment} for each group and use the argument to specify which 619 preferences 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 622 header defines an {@code <extra>} argument with the {@code "settings"} key:</p> 623 624 <pre> 625 public static class SettingsFragment extends PreferenceFragment { 626 @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 645 android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} callback method and call 646 {@link android.preference.PreferenceActivity#loadHeadersFromResource 647 loadHeadersFromResource()}. For example:</p> 648 649 <pre> 650 public class SettingsActivity extends PreferenceActivity { 651 @Override 652 public void onBuildHeaders(List<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 659 android.preference.PreferenceFragment}.</p> 660 661 <p class="note"><strong>Note:</strong> When using preference headers, your subclass of {@link 662 android.preference.PreferenceActivity} doesn't need to implement the {@link 663 android.preference.PreferenceActivity#onCreate onCreate()} method, because the only required 664 task 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 670 provide a two-pane layout when running on Android 3.0 and higher. All you need to do is create an 671 additional preferences XML file that uses basic {@link android.preference.Preference 672 <Preference>} elements that behave like the header items (to be used by the older Android 673 versions).</p> 674 675 <p>Instead of opening a new {@link android.preference.PreferenceScreen}, however, each of the {@link 676 android.preference.Preference <Preference>} elements sends an {@link android.content.Intent} to 677 the {@link android.preference.PreferenceActivity} that specifies which preference XML file to 678 load.</p> 679 680 <p>For example, here's an XML file for preference headers that is used on Android 3.0 681 and higher ({@code res/xml/preference_headers.xml}):</p> 682 683 <pre> 684 <preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> 685 <header 686 android:fragment="com.example.prefs.SettingsFragmentOne" 687 android:title="@string/prefs_category_one" 688 android:summary="@string/prefs_summ_category_one" /> 689 <header 690 android:fragment="com.example.prefs.SettingsFragmentTwo" 691 android:title="@string/prefs_category_two" 692 android:summary="@string/prefs_summ_category_two" /> 693 </preference-headers> 694 </pre> 695 696 <p>And here is a preference file that provides the same headers for versions older than 697 Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):</p> 698 699 <pre> 700 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> 701 <Preference 702 android:title="@string/prefs_category_one" 703 android:summary="@string/prefs_summ_category_one" > 704 <intent 705 android:targetPackage="com.example.prefs" 706 android:targetClass="com.example.prefs.SettingsActivity" 707 android:action="com.example.prefs.PREFS_ONE" /> 708 </Preference> 709 <Preference 710 android:title="@string/prefs_category_two" 711 android:summary="@string/prefs_summ_category_two" > 712 <intent 713 android:targetPackage="com.example.prefs" 714 android:targetClass="com.example.prefs.SettingsActivity" 715 android:action="com.example.prefs.PREFS_TWO" /> 716 </Preference> 717 </PreferenceScreen> 718 </pre> 719 720 <p>Because support for {@code <preference-headers>} was added in Android 3.0, the system calls 721 {@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} in your {@link 722 android.preference.PreferenceActivity} only when running on Android 3.0 or higher. In order to load 723 the "legacy" headers file ({@code preference_headers_legacy.xml}), you must check the Android 724 version and, if the version is older than Android 3.0 ({@link 725 android.os.Build.VERSION_CODES#HONEYCOMB}), call {@link 726 android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} to 727 load the legacy header file. For example:</p> 728 729 <pre> 730 @Override 731 public void onCreate(Bundle savedInstanceState) { 732 super.onCreate(savedInstanceState); 733 ... 734 735 if (Build.VERSION.SDK_INT < 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 @Override 743 public void onBuildHeaders(List<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 749 activity to identify which preference file to load. So retrieve the intent's action and compare it 750 to known action strings that you've used in the preference XML's {@code <intent>} tags:</p> 751 752 <pre> 753 final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE"; 754 ... 755 756 @Override 757 public void onCreate(Bundle savedInstanceState) { 758 super.onCreate(savedInstanceState); 759 760 String action = getIntent().getAction(); 761 if (action != null && action.equals(ACTION_PREFS_ONE)) { 762 addPreferencesFromResource(R.xml.preferences); 763 } 764 ... 765 766 else if (Build.VERSION.SDK_INT < 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 774 android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} will 775 stack all the preferences in a single list, so be sure that it's only called once by chaining the 776 conditions 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 785 within your application by calling the static method {@link 786 android.preference.PreferenceManager#getDefaultSharedPreferences 787 PreferenceManager.getDefaultSharedPreferences()}. This returns the {@link 788 android.content.SharedPreferences} object containing all the key-value pairs that are associated 789 with the {@link android.preference.Preference} objects used in your {@link 790 android.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 793 application:</p> 794 795 <pre> 796 SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); 797 String 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 805 preferences. In order to receive a callback when a change happens to any one of the preferences, 806 implement the {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener 807 SharedPreference.OnSharedPreferenceChangeListener} interface and register the listener for the 808 {@link android.content.SharedPreferences} object by calling {@link 809 android.content.SharedPreferences#registerOnSharedPreferenceChangeListener 810 registerOnSharedPreferenceChangeListener()}.</p> 811 812 <p>The interface has only one callback method, {@link 813 android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged 814 onSharedPreferenceChanged()}, and you might find it easiest to implement the interface as a part of 815 your activity. For example:</p> 816 817 <pre> 818 public 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 835 calls {@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 837 summary to be a description of the user's selection. That is, when the setting is a {@link 838 android.preference.ListPreference} or other multiple choice setting, you should call {@link 839 android.preference.Preference#setSummary setSummary()} when the setting changes to display the 840 current 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 843 href="{@docRoot}design/patterns/settings.html">Settings</a>, we recommend that you update the 844 summary for a {@link android.preference.ListPreference} each time the user changes the preference in 845 order to describe the current setting.</p> 846 847 <p>For proper lifecycle management in the activity, we recommend that you register and unregister 848 your {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} during the {@link 849 android.app.Activity#onResume} and {@link android.app.Activity#onPause} callbacks, respectively:</p> 850 851 <pre> 852 @Override 853 protected void onResume() { 854 super.onResume(); 855 getPreferenceScreen().getSharedPreferences() 856 .registerOnSharedPreferenceChangeListener(this); 857 } 858 859 @Override 860 protected 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 868 android.content.SharedPreferences#registerOnSharedPreferenceChangeListener 869 registerOnSharedPreferenceChangeListener()}, the preference manager does not 870 currently store a strong reference to the listener. You must store a strong 871 reference to the listener, or it will be susceptible to garbage collection. We 872 recommend you keep a reference to the listener in the instance data of an object 873 that 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 876 the listener. As a result, the listener will be subject to garbage collection, 877 and it will fail at some indeterminate time in the future:</p> 878 879 <pre> 880 prefs.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 890 object that will exist as long as the listener is needed:</p> 891 892 <pre> 893 SharedPreferences.OnSharedPreferenceChangeListener listener = 894 new SharedPreferences.OnSharedPreferenceChangeListener() { 895 public void onSharedPreferenceChanged(SharedPreferences prefs, String key) { 896 // listener implementation 897 } 898 }; 899 prefs.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 906 network data their applications are using while in the foreground and background. Users can then 907 disable the use of background data for individual apps. In order to avoid users disabling your app's 908 access to data from the background, you should use the data connection efficiently and allow 909 users 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 912 performs uploads/downloads only when on Wi-Fi, whether your app uses data while roaming, etc. With 913 these controls available to them, users are much less likely to disable your app's access to data 914 when they approach the limits they set in the system Settings, because they can instead precisely 915 control how much data your app uses.</p> 916 917 <p>Once you've added the necessary preferences in your {@link android.preference.PreferenceActivity} 918 to control your app's data habits, you should add an intent filter for {@link 919 android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} in your manifest file. For example:</p> 920 921 <pre> 922 <activity android:name="SettingsActivity" ... > 923 <intent-filter> 924 <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" /> 925 <category android:name="android.intent.category.DEFAULT" /> 926 </intent-filter> 927 </activity> 928 </pre> 929 930 <p>This intent filter indicates to the system that this is the activity that controls your 931 application's data usage. Thus, when the user inspects how much data your app is using from the 932 system'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 934 uses.</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 945 allow you to build a UI for several different types of settings. 946 However, you might discover a setting you need for which there's no built-in solution, such as a 947 number picker or date picker. In such a case, you'll need to create a custom preference by extending 948 the {@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 951 things 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 957 when 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 960 and 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 971 selects the item. However, most custom settings extend {@link android.preference.DialogPreference} to 972 show a dialog, which simplifies the procedure. When you extend {@link 973 android.preference.DialogPreference}, you must call {@link 974 android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()} during in the 975 class constructor to specify the layout for the dialog.</p> 976 977 <p>For example, here's the constructor for a custom {@link 978 android.preference.DialogPreference} that declares the layout and specifies the text for the 979 default positive and negative dialog buttons:</p> 980 981 <pre> 982 public 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 1001 android.preference.Preference} class's {@code persist*()} methods, such as {@link 1002 android.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 1006 data type, so you must use the {@code persist*()} method appropriate for the data type used by your 1007 custom {@link android.preference.Preference}.</p> 1008 1009 <p>When you choose to persist the setting can depend on which {@link 1010 android.preference.Preference} class you extend. If you extend {@link 1011 android.preference.DialogPreference}, then you should persist the value only when the dialog 1012 closes 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 1015 android.preference.DialogPreference#onDialogClosed onDialogClosed()} method. The method includes a 1016 boolean argument that specifies whether the user result is "positive"—if the value is 1017 <code>true</code>, then the user selected the positive button and you should save the new value. For 1018 example:</p> 1019 1020 <pre> 1021 @Override 1022 protected 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 1031 value. Calling {@link android.preference.Preference#persistInt persistInt()} saves the value to 1032 the {@link android.content.SharedPreferences} file (automatically using the key that's 1033 specified 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 1039 calls {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} to notify 1040 you whether the setting has a persisted value. If there is no persisted value, this call provides 1041 you the default value.</p> 1042 1043 <p>The {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} method passes 1044 a boolean, <code>restorePersistedValue</code>, to indicate whether a value has already been persisted 1045 for the setting. If it is <code>true</code>, then you should retrieve the persisted value by calling 1046 one of the {@link 1047 android.preference.Preference} class's {@code getPersisted*()} methods, such as {@link 1048 android.preference.Preference#getPersistedInt getPersistedInt()} for an integer value. You'll 1049 usually want to retrieve the persisted value so you can properly update the UI to reflect the 1050 previously saved value.</p> 1051 1052 <p>If <code>restorePersistedValue</code> is <code>false</code>, then you 1053 should use the default value that is passed in the second argument.</p> 1054 1055 <pre> 1056 @Override 1057 protected 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 1070 default value to use in case there is actually no persisted value or the key does not exist. In 1071 the example above, a local constant is used to specify the default value in case {@link 1072 android.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 1076 its 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 1083 system calls {@link android.preference.Preference#onGetDefaultValue 1084 onGetDefaultValue()} when it instantiates the object in order to retrieve the value. You must 1085 implement this method in order for the system to save the default value in the {@link 1086 android.content.SharedPreferences}. For example:</p> 1087 1088 <pre> 1089 @Override 1090 protected 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 1096 position of the {@code android:defaultValue}, which you must retrieve. The reason you must 1097 implement this method to extract the default value from the attribute is because you must specify 1098 a 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} 1105 subclass is responsible for saving and restoring its state in case the activity or fragment is 1106 restarted (such as when the user rotates the screen). To properly save and 1107 restore the state of your {@link android.preference.Preference} class, you must implement the 1108 lifecycle callback methods {@link android.preference.Preference#onSaveInstanceState 1109 onSaveInstanceState()} and {@link 1110 android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.</p> 1111 1112 <p>The state of your {@link android.preference.Preference} is defined by an object that implements 1113 the {@link android.os.Parcelable} interface. The Android framework provides such an object for you 1114 as a starting point to define your state object: the {@link 1115 android.preference.Preference.BaseSavedState} class.</p> 1116 1117 <p>To define how your {@link android.preference.Preference} class saves its state, you should 1118 extend 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} 1120 object.</p> 1121 1122 <p>For most apps, you can copy the following implementation and simply change the lines that 1123 handle the {@code value} if your {@link android.preference.Preference} subclass saves a data 1124 type other than an integer.</p> 1125 1126 <pre> 1127 private 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 @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<SavedState> CREATOR = 1151 new Parcelable.Creator<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 1165 to your app (usually as a subclass of your {@link android.preference.Preference} subclass), you 1166 then need to implement the {@link android.preference.Preference#onSaveInstanceState 1167 onSaveInstanceState()} and {@link 1168 android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} methods for your 1169 {@link android.preference.Preference} subclass.</p> 1170 1171 <p>For example:</p> 1172 1173 <pre> 1174 @Override 1175 protected 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 @Override 1193 protected 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