diff options
Diffstat (limited to 'docs/html/guide/topics')
25 files changed, 1276 insertions, 135 deletions
diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd index 602b6e8..598b08a 100644 --- a/docs/html/guide/topics/data/backup.jd +++ b/docs/html/guide/topics/data/backup.jd @@ -187,10 +187,7 @@ href="#RestoreVersion">Checking the Restore Data Version</a> for more informatio available only on devices running API Level 8 (Android 2.2) or greater, so you should also set your <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code android:minSdkVersion}</a> -attribute to "8". However, if you implement proper <a -href="{@docRoot}resources/articles/backward-compatibility.html">backward compatibility</a> in -your application, you can support this feature for devices running API Level 8 or greater, while -remaining compatible with older devices.</p> +attribute to "8".</p> diff --git a/docs/html/guide/topics/data/install-location.jd b/docs/html/guide/topics/data/install-location.jd index 19c4b39..5abdced 100644 --- a/docs/html/guide/topics/data/install-location.jd +++ b/docs/html/guide/topics/data/install-location.jd @@ -111,10 +111,7 @@ storage.</p> <p class="caution"><strong>Caution:</strong> Although XML markup such as this will be ignored by older platforms, you must be careful not to use programming APIs introduced in API Level 8 while your {@code minSdkVersion} is less than "8", unless you perform the work necessary to -provide backward compatibility in your code. For information about building -backward compatibility in your application code, see the <a -href="{@docRoot}resources/articles/backward-compatibility.html">Backward Compatibility</a> -article.</p> +provide backward compatibility in your code.</p> @@ -141,17 +138,13 @@ system again. At which time, you can restart your Service.</dd> <dd>Your alarms registered with {@link android.app.AlarmManager} will be cancelled. You must manually re-register any alarms when external storage is remounted.</dd> <dt>Input Method Engines</dt> - <dd>Your <a href="{@docRoot}resources/articles/on-screen-inputs.html">IME</a> will be + <dd>Your <a href="{@docRoot}guide/topics/text/creating-input-method.html">IME</a> will be replaced by the default IME. When external storage is remounted, the user can open system settings to enable your IME again.</dd> <dt>Live Wallpapers</dt> - <dd>Your running <a href="{@docRoot}resources/articles/live-wallpapers.html">Live Wallpaper</a> + <dd>Your running <a href="http://android-developers.blogspot.com/2010/02/live-wallpapers.html">Live Wallpaper</a> will be replaced by the default Live Wallpaper. When external storage is remounted, the user can select your Live Wallpaper again.</dd> - <dt>Live Folders</dt> - <dd>Your <a href="{@docRoot}resources/articles/live-folders.html">Live Folder</a> will be -removed from the home screen. When external storage is remounted, the user can add your Live Folder -to the home screen again.</dd> <dt>App Widgets</dt> <dd>Your <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widget</a> will be removed from the home screen. When external storage is remounted, your App Widget will <em>not</em> be @@ -174,7 +167,7 @@ external storage, it can never receive this broadcast.</dd> <dt>Copy Protection</dt> <dd>Your application cannot be installed to a device's SD card if it uses Google Play's Copy Protection feature. However, if you use Google Play's - <a href="{@docRoot}guide/google/play/licensing.html">Application Licensing</a> instead, your + <a href="{@docRoot}guide/google/play/licensing/index.html">Application Licensing</a> instead, your application <em>can</em> be installed to internal or external storage, including SD cards.</dd> </dl> diff --git a/docs/html/guide/topics/graphics/opengl.jd b/docs/html/guide/topics/graphics/opengl.jd index a9fedb7..6114a4a 100644 --- a/docs/html/guide/topics/graphics/opengl.jd +++ b/docs/html/guide/topics/graphics/opengl.jd @@ -84,11 +84,8 @@ understanding how to implement these classes in an activity should be your first this class by creating an instance of {@link android.opengl.GLSurfaceView} and adding your {@link android.opengl.GLSurfaceView.Renderer Renderer} to it. However, if you want to capture touch screen events, you should extend the {@link android.opengl.GLSurfaceView} class to - implement the touch listeners, as shown in OpenGL Tutorials for - <a href="{@docRoot}resources/tutorials/opengl/opengl-es10.html#touch">ES 1.0</a>, - <a href="{@docRoot}resources/tutorials/opengl/opengl-es20.html#touch">ES 2.0</a> and the <a -href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchRotateActivity.html" ->TouchRotateActivity</a> sample.</dd> + implement the touch listeners, as shown in OpenGL training lesson, + <a href="{@docRoot}training/graphics/opengl/touch.html">Responding to Touch Events</a>.</dd> <dt><strong>{@link android.opengl.GLSurfaceView.Renderer}</strong></dt> <dd>This interface defines the methods required for drawing graphics in an OpenGL {@link @@ -164,9 +161,8 @@ interface to OpenGL ES 2.0 and is available starting with Android 2.2 (API Level </li> </ul> -<p>If you'd like to start building an app with OpenGL right away, have a look at the tutorials for -<a href="{@docRoot}resources/tutorials/opengl/opengl-es10.html">OpenGL ES 1.0</a> or -<a href="{@docRoot}resources/tutorials/opengl/opengl-es20.html">OpenGL ES 2.0</a>! +<p>If you'd like to start building an app with OpenGL right away, follow the +<a href="{@docRoot}training/graphics/opengl/index.html">Displaying Graphics with OpenGL ES</a> class. </p> <h2 id="manifest">Declaring OpenGL Requirements</h2> @@ -277,10 +273,6 @@ which simulates a camera position. </li> </ol> -<p>For a complete example of how to apply projection and camera views with OpenGL ES 1.0, see the <a -href="{@docRoot}resources/tutorials/opengl/opengl-es10.html#projection-and-views">OpenGL ES 1.0 -tutorial</a>.</p> - <h3 id="proj-es2">Projection and camera view in OpenGL ES 2.0</h3> <p>In the ES 2.0 API, you apply projection and camera view by first adding a matrix member to @@ -382,8 +374,7 @@ objects to be rendered by OpenGL. </li> </ol> <p>For a complete example of how to apply projection and camera view with OpenGL ES 2.0, see the <a -href="{@docRoot}resources/tutorials/opengl/opengl-es20.html#projection-and-views">OpenGL ES 2.0 -tutorial</a>.</p> +href="{@docRoot}training/graphics/opengl/index.html">Displaying Graphics with OpenGL ES</a> class.</p> <h2 id="faces-winding">Shape Faces and Winding</h2> diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd index a3d4a95..4807a5e 100644 --- a/docs/html/guide/topics/manifest/manifest-element.jd +++ b/docs/html/guide/topics/manifest/manifest-element.jd @@ -152,7 +152,7 @@ either internal or external storage through the system settings.</td> <p class="caution"><strong>Caution:</strong> If your application uses Google Play's Copy Protection feature, it cannot be installed to a device's SD card. However, if you use Google - Play's <a href="{@docRoot}guide/google/play/licensing.html">Application Licensing</a> instead, + Play's <a href="{@docRoot}guide/google/play/licensing/index.html">Application Licensing</a> instead, your application <em>can</em> be installed to internal or external storage, including SD cards.</p> <p class="note"><strong>Note:</strong> By default, your application will be installed on the @@ -175,7 +175,7 @@ multiple SD cards can be used with the same device.</li> storage. However, the system will not allow the user to move the application to external storage if this attribute is set to {@code internalOnly}, which is the default setting.</p> -<p>Read <a href="{@docRoot}guide/appendix/install-location.html">App Install Location</a> for +<p>Read <a href="{@docRoot}guide/topics/data/install-location.html">App Install Location</a> for more information about using this attribute (including how to maintain backward compatibility).</p> <p>Introduced in: API Level 8.</p> diff --git a/docs/html/guide/topics/media/camera.jd b/docs/html/guide/topics/media/camera.jd index a63270a..3fe23f8 100644 --- a/docs/html/guide/topics/media/camera.jd +++ b/docs/html/guide/topics/media/camera.jd @@ -617,7 +617,7 @@ public class CameraActivity extends Activity { // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); - FrameLayout preview = (FrameLayout) findViewById(id.camera_preview); + FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview); preview.addView(mPreview); } } diff --git a/docs/html/guide/topics/providers/content-provider-basics.jd b/docs/html/guide/topics/providers/content-provider-basics.jd index 7999033..8c47ad7 100644 --- a/docs/html/guide/topics/providers/content-provider-basics.jd +++ b/docs/html/guide/topics/providers/content-provider-basics.jd @@ -1030,12 +1030,12 @@ mRowsDeleted = getContentResolver().delete( A provider defines URI permissions for content URIs in its manifest, using the <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#gprmsn"> android:grantUriPermission</a></code> - attribute of the - {@code <a href="guide/topics/manifest/provider-element.html"><provider></a>} + attribute of the <a href="{@docRoot}guide/topics/manifest/provider-element.html"> + {@code <provider>}</a> element, as well as the - {@code <a href="guide/topics/manifest/grant-uri-permission-element.html"> - <grant-uri-permission></a>} child element of the - {@code <a href="guide/topics/manifest/provider-element.html"><provider></a>} + <a href="{@docRoot}guide/topics/manifest/grant-uri-permission-element.html">{@code + <grant-uri-permission>}</a> child element of the + <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code <provider>}</a> element. The URI permissions mechanism is explained in more detail in the <a href="{@docRoot}guide/topics/security/security.html">Security and Permissions</a> guide, in the section "URI Permissions". diff --git a/docs/html/guide/topics/renderscript/index.jd b/docs/html/guide/topics/renderscript/index.jd index b6758bc..4c22e72 100644 --- a/docs/html/guide/topics/renderscript/index.jd +++ b/docs/html/guide/topics/renderscript/index.jd @@ -1,8 +1,10 @@ page.title=Computation +page.landing=true +page.landing.intro=Renderscript provides a platform-independent computation engine that operates at the native level. Use it to accelerate your apps that require extensive computational horsepower. +page.landing.image= + @jd:body -<p>Renderscript provides a platform-independent computation engine that operates at the native level. - Use it to accelerate your apps that require extensive computational horsepower.</p> <div class="landing-docs"> <div> diff --git a/docs/html/guide/topics/resources/accessing-resources.jd b/docs/html/guide/topics/resources/accessing-resources.jd index 03bb939..0673b6f 100644 --- a/docs/html/guide/topics/resources/accessing-resources.jd +++ b/docs/html/guide/topics/resources/accessing-resources.jd @@ -336,6 +336,6 @@ android.widget.ArrayAdapter}<String>(this, <strong>android.R.layout.simple <p>In this example, {@link android.R.layout#simple_list_item_1} is a layout resource defined by the platform for items in a {@link android.widget.ListView}. You can use this instead of creating -your own layout for list items. (For more about using {@link android.widget.ListView}, see the -<a href="{@docRoot}resources/tutorials/views/hello-listview.html">List View Tutorial</a>.)</p> +your own layout for list items. For more information, see the +<a href="{@docRoot}guide/topics/ui/layout/listview.html">List View</a> developer guide.</p> diff --git a/docs/html/guide/topics/resources/layout-resource.jd b/docs/html/guide/topics/resources/layout-resource.jd index 5643075..cd88ae9 100644 --- a/docs/html/guide/topics/resources/layout-resource.jd +++ b/docs/html/guide/topics/resources/layout-resource.jd @@ -161,17 +161,16 @@ included layout. Only effective if <code>android:layout_height</code> is also de supported by the root element in the included layout and they will override those defined in the root element.</p> - <p class="caution"><strong>Caution:</strong> If you want to override the layout dimensions, -you must override both <code>android:layout_height</code> and -<code>android:layout_width</code>—you cannot override only the height or only the width. -If you override only one, it will not take effect. (Other layout properties, such as weight, -are still inherited from the source layout.)</p> + <p class="caution"><strong>Caution:</strong> If you want to override layout attributes using + the <code><include></code> tag, you must override both + <code>android:layout_height</code> and <code>android:layout_width</code> in order for + other layout attributes to take effect.</p> <p>Another way to include a layout is to use {@link android.view.ViewStub}. It is a lightweight View that consumes no layout space until you explicitly inflate it, at which point, it includes a layout file defined by its {@code android:layout} attribute. For more information about using {@link -android.view.ViewStub}, read <a href="{@docRoot}resources/articles/layout-tricks-stubs.html">Layout -Tricks: ViewStubs</a>.</p> +android.view.ViewStub}, read <a href="{@docRoot}training/improving-layouts/loading-ondemand.html">Loading + Views On Demand</a>.</p> </dd> <dt id="merge-element"><code><merge></code></dt> @@ -182,8 +181,7 @@ that already contains the appropriate parent View to contain the children of the in another layout file using <a href="#include-element"><code><include></code></a> and this layout doesn't require a different {@link android.view.ViewGroup} container. For more information about merging layouts, read <a -href="{@docRoot}resources/articles/layout-tricks-merge.html">Layout -Tricks: Merging</a>.</dd> +href="{@docRoot}training/improving-layouts/reusing-layouts.html">Re-using Layouts with <include/></a>.</dd> </dl> diff --git a/docs/html/guide/topics/resources/runtime-changes.jd b/docs/html/guide/topics/resources/runtime-changes.jd index f5475b4..5f39aa5 100644 --- a/docs/html/guide/topics/resources/runtime-changes.jd +++ b/docs/html/guide/topics/resources/runtime-changes.jd @@ -16,8 +16,8 @@ parent.link=index.html <ol> <li><a href="providing-resources.html">Providing Resources</a></li> <li><a href="accessing-resources.html">Accessing Resources</a></li> - <li><a href="{@docRoot}resources/articles/faster-screen-orientation-change.html">Faster Screen -Orientation Change</a></li> + <li><a href="http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html">Faster + Screen Orientation Change</a></li> </ol> </div> </div> diff --git a/docs/html/guide/topics/search/index.jd b/docs/html/guide/topics/search/index.jd index 2ee624b..680c607 100644 --- a/docs/html/guide/topics/search/index.jd +++ b/docs/html/guide/topics/search/index.jd @@ -54,9 +54,9 @@ search your data. To perform a search, you need to use APIs appropriate for your if your data is stored in an SQLite database, you should use the {@link android.database.sqlite} APIs to perform searches. <br/><br/> -Also, there is no guarantee that every device provides a dedicated SEARCH button to invoke the +Also, there is no guarantee that a device provides a dedicated SEARCH button that invokes the search interface in your application. When using the search dialog or a custom interface, you -must always provide a search button in your UI that activates the search interface. For more +must provide a search button in your UI that activates the search interface. For more information, see <a href="search-dialog.html#InvokingTheSearchDialog">Invoking the search dialog</a>.</p> diff --git a/docs/html/guide/topics/search/search-dialog.jd b/docs/html/guide/topics/search/search-dialog.jd index 49451ac..b9a26d6 100644 --- a/docs/html/guide/topics/search/search-dialog.jd +++ b/docs/html/guide/topics/search/search-dialog.jd @@ -6,14 +6,6 @@ parent.link=index.html <div id="qv-wrapper"> <div id="qv"> - <h2>Quickview</h2> - <ul> - <li>The Android system sends search queries from the search dialog or widget to an activity you -specify to perform searches and present results</li> - <li>You can put the search widget in the Action Bar, as an "action view," for quick -access</li> - </ul> - <h2>In this document</h2> <ol> @@ -61,14 +53,8 @@ Dictionary</a></li> <h2>Downloads</h2> <ol> -<li><a href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a></li> -</ol> - -<h2>See also</h2> -<ol> -<li><a href="adding-recent-query-suggestions.html">Adding Recent Query Suggestions</a></li> -<li><a href="adding-custom-suggestions.html">Adding Custom Suggestions</a></li> -<li><a href="searchable-config.html">Searchable Configuration</a></li> +<li><a href="{@docRoot}design/downloads/index.html#action-bar-icon-pack">Action Bar +Icon Pack</a></li> </ol> </div> @@ -142,12 +128,14 @@ data, and displays the search results.</p></li> <li>A search interface, provided by either: <ul> <li>The search dialog - <p>By default, the search dialog is hidden, but appears at the top of the screen when the -user presses the device SEARCH button (when available) or another button in your user interface.</p> + <p>By default, the search dialog is hidden, but appears at the top of the screen when + you call {@link android.app.Activity#onSearchRequested()} (when the user presses your + Search button).</p> </li> <li>Or, a {@link android.widget.SearchView} widget <p>Using the search widget allows you to put the search box anywhere in your activity. -Instead of putting it in your activity layout, however, it's usually more convenient for users as an +Instead of putting it in your activity layout, you should usually use +{@link android.widget.SearchView} as an <a href="{@docRoot}guide/topics/ui/actionbar.html#ActionView">action view in the Action Bar</a>.</p> </li> </ul> @@ -415,10 +403,9 @@ searchable activity that performs the search. However, if you are developing your application for devices running Android 3.0, you should consider using the search widget instead (see the side box).</p> -<p>The search dialog is always hidden by default, until the user activates it. If the user's device -includes a SEARCH button, pressing it will activate the search dialog by default. Your application -can also activate the search dialog on demand by calling {@link -android.app.Activity#onSearchRequested onSearchRequested()}. However, neither of these work +<p>The search dialog is always hidden by default, until the user activates it. Your application +can activate the search dialog by calling {@link +android.app.Activity#onSearchRequested onSearchRequested()}. However, this method doesn't work until you enable the search dialog for the activity.</p> <p>To enable the search dialog, you must indicate to the system which searchable activity should @@ -469,8 +456,8 @@ search dialog:</p> href="{@docRoot}guide/topics/manifest/meta-data-element.html">{@code <meta-data>}</a> element to declare which searchable activity to use for searches, the activity has enabled the search dialog. -While the user is in this activity, the device SEARCH button (if available) and the {@link -android.app.Activity#onSearchRequested onSearchRequested()} method will activate the search dialog. +While the user is in this activity, the {@link +android.app.Activity#onSearchRequested onSearchRequested()} method activates the search dialog. When the user executes the search, the system starts {@code SearchableActivity} and delivers it the {@link android.content.Intent#ACTION_SEARCH} intent.</p> @@ -495,21 +482,22 @@ searches.</p> <h3 id="InvokingTheSearchDialog">Invoking the search dialog</h3> -<p>As mentioned above, the device SEARCH button will open the search dialog as long as the current -activity has declared in the manifest the searchable activity to use.</p> - -<p>However, some devices do not include a dedicated SEARCH button, so you should not assume that -it's always available. When using the search dialog, you must <strong>always provide another search -button in your UI</strong> that activates the search dialog by calling {@link -android.app.Activity#onSearchRequested()}.</p> - -<p>For instance, you should either provide a menu item in your <a -href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or a button in your -activity layout that -activates search by calling {@link android.app.Activity#onSearchRequested()}. The <a -href="{@docRoot}shareables/search_icons.zip">search_icons.zip</a> file includes icons for -medium and high density screens, which you can use for your search menu item or button (low-density -screens scale-down the hdpi image by one half). </p> +<p>Although some devices provide a dedicated Search button, the behavior of the button may vary +between devices and many devices do not provide a Search button at all. So when using the search +dialog, you <strong>must provide a search button in your UI</strong> that activates the search +dialog by calling {@link android.app.Activity#onSearchRequested()}.</p> + +<p>For instance, you should add a Search button in your <a +href="{@docRoot}guide/topics/ui/menus.html#options-menu">Options Menu</a> or UI +layout that calls {@link android.app.Activity#onSearchRequested()}. For consistency with +the Android system and other apps, you should label your button with the Android Search icon that's +available from the <a href="{@docRoot}design/downloads/index.html#action-bar-icon-pack">Action Bar +Icon Pack</a>.</p> + +<p class="note"><strong>Note:</strong> If your app uses the <a +href="{@docRoot}guide/topics/ui/actionbar.html">action bar</a>, then you should not use +the search dialog for your search interface. Instead, use the <a href="#UsingSearchWidget">search +widget</a> as a collapsible view in the action bar.</p> <p>You can also enable "type-to-search" functionality, which activates the search dialog when the user starts typing on the keyboard—the keystrokes are inserted into the search dialog. You can diff --git a/docs/html/guide/topics/security/security.jd b/docs/html/guide/topics/security/security.jd index eeaac44..9cdccae 100644 --- a/docs/html/guide/topics/security/security.jd +++ b/docs/html/guide/topics/security/security.jd @@ -135,8 +135,7 @@ dynamic permission grants on a case-by-case basis.</p> <p>To provide additional protection for sensitive data, some applications choose to encrypt local files using a key that is not accessible to the -application. (For example, a key can be placed in a <code><a -href={@docRoot}reference/java/security/KeyStore.html">KeyStore</a></code> and +application. (For example, a key can be placed in a {@link java.security.KeyStore} and protected with a user password that is not stored on the device). While this does not protect data from a root compromise that can monitor the user inputting the password, it can provide protection for a lost device without <a @@ -717,8 +716,7 @@ href="{@docRoot}reference/android/accounts/AccountManager.html"> AccountManager</a></code> using <code><a href="{@docRoot}reference/android/content/pm/PackageManager.html#checkSignatures(java.lang.String,%20java.lang.String)">checkSignature()</a></code>. Alternatively, if only one application will use the credential, you might use a -<code><a -href={@docRoot}reference/java/security/KeyStore.html">KeyStore</a></code> for +{@link java.security.KeyStore} for storage.</p> <a name="Crypto"></a> @@ -752,8 +750,7 @@ href="{@docRoot}reference/javax/crypto/KeyGenerator.html"> number generator significantly weakens the strength of the algorithm, and may allow offline attacks.</p> -<p>If you need to store a key for repeated use, use a mechanism like <code><a -href="{@docRoot}reference/java/security/KeyStore.html">KeyStore</a></code> that +<p>If you need to store a key for repeated use, use a mechanism like {@link java.security.KeyStore} that provides a mechanism for long term storage and retrieval of cryptographic keys.</p> diff --git a/docs/html/guide/topics/sensors/index.jd b/docs/html/guide/topics/sensors/index.jd index a045899..726476a 100644 --- a/docs/html/guide/topics/sensors/index.jd +++ b/docs/html/guide/topics/sensors/index.jd @@ -18,7 +18,7 @@ the default position, the screens are wider than they are tall. This introduces issues that we’ve noticed causing problems in some apps.</p> </a> - <a href="android-developers.blogspot.com/2011/06/deep-dive-into-location.html"> + <a href="http://android-developers.blogspot.com/2011/06/deep-dive-into-location.html"> <h4>A Deep Dive Into Location</h4> <p>I’ve written an open-source reference app that incorporates all of the tips, tricks, and cheats I know to reduce the time between opening an app and seeing an up-to-date list of nearby diff --git a/docs/html/guide/topics/sensors/sensors_overview.jd b/docs/html/guide/topics/sensors/sensors_overview.jd index e38a843..a162ccf 100644 --- a/docs/html/guide/topics/sensors/sensors_overview.jd +++ b/docs/html/guide/topics/sensors/sensors_overview.jd @@ -662,7 +662,7 @@ whether there's a pressure sensor on a device:</p> <h4>Using Google Play filters to target specific sensor configurations</h4> <p>If you are publishing your application on Google Play you can use the - <a href="{@docRoot}guide//topics/manifest/uses-feature-element.html"><code><uses-feature> + <a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"><code><uses-feature> </code></a> element in your manifest file to filter your application from devices that do not have the appropriate sensor configuration for your application. The <code><uses-feature></code> element has several hardware descriptors that let you filter diff --git a/docs/html/guide/topics/text/creating-input-method.jd b/docs/html/guide/topics/text/creating-input-method.jd index e49610f..7086824 100644 --- a/docs/html/guide/topics/text/creating-input-method.jd +++ b/docs/html/guide/topics/text/creating-input-method.jd @@ -1,6 +1,5 @@ page.title=Creating an Input Method parent.title=Articles -parent.link=../browser.html?tag=article @jd:body <div id="qv-wrapper"> @@ -162,8 +161,8 @@ parent.link=../browser.html?tag=article In this example, {@code MyKeyboardView} is an instance of a custom implementation of {@link android.inputmethodservice.KeyboardView} that renders a {@link android.inputmethodservice.Keyboard}. If you’re building a traditional QWERTY keyboard, - see the <a href=”{@docRoot}resources/samples/SoftKeyboard/index.html”>Soft Keyboard</a> sample - app for an example of how to extend the {@link android.inputmethodservice.KeyboardView} class. + see the Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample + app</a> for an example of how to extend the {@link android.inputmethodservice.KeyboardView} class. </p> <h3 id="CandidateView">Candidates view</h3> <p> @@ -175,7 +174,8 @@ parent.link=../browser.html?tag=article default behavior, so you don’t have to implement this if you don’t provide suggestions).</p> <p> For an example implementation that provides user suggestions, see the - <a href=”{@docRoot}resources/samples/SoftKeyboard/index.html”>Soft Keyboard</a> sample app. + Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample + app</a>. </p> <h3 id="DesignConsiderations">UI design considerations</h3> <p> @@ -388,8 +388,8 @@ The input type bit pattern can have one of several values, including: To intercept hardware keys, override {@link android.inputmethodservice.InputMethodService#onKeyDown(int, KeyEvent) onKeyDown()} and {@link android.inputmethodservice.InputMethodService#onKeyUp(int, KeyEvent) onKeyUp()}. - See the <a href=”{@docRoot}resources/samples/SoftKeyboard/index.html”>Soft Keyboard</a> sample - app for an example. + See the Soft Keyboard <a href="{@docRoot}tools/samples/index.html">sample + app</a> for an example. </p> <p> Remember to call the <code>super()</code> method for keys you don't want to handle yourself. diff --git a/docs/html/guide/topics/text/spell-checker-framework.jd b/docs/html/guide/topics/text/spell-checker-framework.jd index 1c2e211..7f7a0b8 100644 --- a/docs/html/guide/topics/text/spell-checker-framework.jd +++ b/docs/html/guide/topics/text/spell-checker-framework.jd @@ -1,6 +1,5 @@ page.title=Spelling Checker Framework parent.title=Articles -parent.link=../browser.html?tag=article @jd:body <div id="qv-wrapper"> <div id="qv"> diff --git a/docs/html/guide/topics/ui/accessibility/services.jd b/docs/html/guide/topics/ui/accessibility/services.jd index 0c1d065..7d36181 100644 --- a/docs/html/guide/topics/ui/accessibility/services.jd +++ b/docs/html/guide/topics/ui/accessibility/services.jd @@ -10,7 +10,7 @@ parent.link=index.html <ol> <li><a href="#manifest">Manifest Declarations and Permissions</a> <ol> - <li><a href="service-declaration">Accessibility service declaration</a></li> + <li><a href="#service-declaration">Accessibility service declaration</a></li> <li><a href="#service-config">Accessibility service configuration</a></li> </ol> </li> diff --git a/docs/html/guide/topics/ui/controls/checkbox.jd b/docs/html/guide/topics/ui/controls/checkbox.jd index 35b8f56..ea70980 100644 --- a/docs/html/guide/topics/ui/controls/checkbox.jd +++ b/docs/html/guide/topics/ui/controls/checkbox.jd @@ -65,7 +65,7 @@ click event for both checkboxes:</p> <pre> public void onCheckboxClicked(View view) { // Is the view now checked? - boolean checked = (CheckBox) view).isChecked(); + boolean checked = ((CheckBox) view).isChecked(); // Check which checkbox was clicked switch(view.getId()) { diff --git a/docs/html/guide/topics/ui/controls/radiobutton.jd b/docs/html/guide/topics/ui/controls/radiobutton.jd index f6f6d49..c96e576 100644 --- a/docs/html/guide/topics/ui/controls/radiobutton.jd +++ b/docs/html/guide/topics/ui/controls/radiobutton.jd @@ -72,7 +72,7 @@ click event for both radio buttons:</p> <pre> public void onRadioButtonClicked(View view) { // Is the button now checked? - boolean checked = (RadioButton) view).isChecked(); + boolean checked = ((RadioButton) view).isChecked(); // Check which radio button was clicked switch(view.getId()) { diff --git a/docs/html/guide/topics/ui/declaring-layout.jd b/docs/html/guide/topics/ui/declaring-layout.jd index 3c9faa8..e229f23 100644 --- a/docs/html/guide/topics/ui/declaring-layout.jd +++ b/docs/html/guide/topics/ui/declaring-layout.jd @@ -32,12 +32,17 @@ parent.link=index.html <li>{@link android.view.ViewGroup}</li> <li>{@link android.view.ViewGroup.LayoutParams}</li> </ol> -</div> + + <h2>See also</h2> + <ol> + <li><a href="{@docRoot}training/basics/firstapp/building-ui.html">Building a Simple User +Interface</a></li> </div> </div> -<p>Your layout is the architecture for the user interface in an Activity. -It defines the layout structure and holds all the elements that appear to the user. -You can declare your layout in two ways:</p> +<p>A layout defines the visual structure for a user interface, such as the UI for an <a +href="{@docRoot}guide/components/activities.html">activity</a> or <a +href="{@docRoot}guide/topics/appwidgets/index.html">app widget</a>. +You can declare a layout in two ways:</p> <ul> <li><strong>Declare UI elements in XML</strong>. Android provides a straightforward XML vocabulary that corresponds to the View classes and subclasses, such as those for widgets and layouts.</li> @@ -77,16 +82,6 @@ Layout Objects</a>. There are also a collection of tutorials on building various <h2 id="write">Write the XML</h2> -<div class="sidebox-wrapper"> -<div class="sidebox"> -<p>For your convenience, the API reference documentation for UI related classes -lists the available XML attributes that correspond to the class methods, including inherited -attributes.</p> -<p>To learn more about the available XML elements and attributes, as well as the format of the XML file, see <a -href="{@docRoot}guide/topics/resources/available-resources.html#layoutresources">Layout Resources</a>.</p> -</div> -</div> - <p>Using Android's XML vocabulary, you can quickly design UI layouts and the screen elements they contain, in the same way you create web pages in HTML — with a series of nested elements. </p> <p>Each layout file must contain exactly one root element, which must be a View or ViewGroup object. Once you've defined the root element, you can add additional layout objects or widgets as child elements to gradually build a View hierarchy that defines your layout. For example, here's an XML layout that uses a vertical {@link android.widget.LinearLayout} @@ -111,7 +106,8 @@ to hold a {@link android.widget.TextView} and a {@link android.widget.Button}:</ <p>After you've declared your layout in XML, save the file with the <code>.xml</code> extension, in your Android project's <code>res/layout/</code> directory, so it will properly compile. </p> -<p>We'll discuss each of the attributes shown here a little later.</p> +<p>More information about the syntax for a layout XML file is available in the <a +href="{@docRoot}guide/topics/resources/layout-resource.html">Layout Resources</a> document.</p> <h2 id="load">Load the XML Resource</h2> @@ -406,13 +402,13 @@ into a view that can be added into the {@link android.widget.AdapterView} layout <div class="layout first"> <h4><a href="layout/listview.html">List View</a></h4> - <a href="layout/list.html"><img src="{@docRoot}images/ui/listview-small.png" alt="" /></a> + <a href="layout/listview.html"><img src="{@docRoot}images/ui/listview-small.png" alt="" /></a> <p>Displays a scrolling single column list.</p> </div> <div class="layout"> <h4><a href="layout/gridview.html">Grid View</a></h4> - <a href="layout/grid.html"><img src="{@docRoot}images/ui/gridview-small.png" alt="" /></a> + <a href="layout/gridview.html"><img src="{@docRoot}images/ui/gridview-small.png" alt="" /></a> <p>Displays a scrolling grid of columns and rows.</p> </div> diff --git a/docs/html/guide/topics/ui/layout/gridview.jd b/docs/html/guide/topics/ui/layout/gridview.jd index 284a25a..67bdd0f 100644 --- a/docs/html/guide/topics/ui/layout/gridview.jd +++ b/docs/html/guide/topics/ui/layout/gridview.jd @@ -1,4 +1,4 @@ -page.title=Grid +page.title=Grid View parent.title=Layouts parent.link=layout-objects.html @jd:body @@ -22,10 +22,15 @@ two-dimensional, scrollable grid. The grid items are automatically inserted to the layout using a {@link android.widget.ListAdapter}.</p> +<p>For an introduction to how you can dynamically insert views using an adapter, read +<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Building Layouts with + an Adapter</a>.</p> + <img src="{@docRoot}images/ui/gridview.png" alt="" /> <h2 id="example">Example</h2> + <p>In this tutorial, you'll create a grid of image thumbnails. When an item is selected, a toast message will display the position of the image.</p> diff --git a/docs/html/guide/topics/ui/layout/listview.jd b/docs/html/guide/topics/ui/layout/listview.jd index 26a7597..fee5292 100644 --- a/docs/html/guide/topics/ui/layout/listview.jd +++ b/docs/html/guide/topics/ui/layout/listview.jd @@ -28,6 +28,10 @@ scrollable items. The list items are automatically inserted to the list using an android.widget.Adapter} that pulls content from a source such as an array or database query and converts each item result into a view that's placed into the list.</p> +<p>For an introduction to how you can dynamically insert views using an adapter, read +<a href="{@docRoot}guide/topics/ui/declaring-layout.html#AdapterViews">Building Layouts with + an Adapter</a>.</p> + <img src="{@docRoot}images/ui/listview.png" alt="" /> <h2 id="Loader">Using a Loader</h2> @@ -147,5 +151,5 @@ href="{@docRoot}guide/topics/providers/contacts-provider.html">Contacts Provider</a>, if you want to try this code, your app must request the {@link android.Manifest.permission#READ_CONTACTS} permission in the manifest file:<br/> -<code><uses-permission android:name="android.permission.READ_CONTACTS" /></p> +<code><uses-permission android:name="android.permission.READ_CONTACTS" /></code></p> diff --git a/docs/html/guide/topics/ui/layout/relative.jd b/docs/html/guide/topics/ui/layout/relative.jd index ee6cf02..47f9417 100644 --- a/docs/html/guide/topics/ui/layout/relative.jd +++ b/docs/html/guide/topics/ui/layout/relative.jd @@ -44,19 +44,19 @@ android.widget.RelativeLayout.LayoutParams}.</p> include:</p> <dl> <dt><a -href="{docRoot}reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_alignParentTop" +href="{@docRoot}reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_alignParentTop" >{@code android:layout_alignParentTop}</a></dt> <dd>If {@code "true"}, makes the top edge of this view match the top edge of the parent. </dd> <dt><a -href="{docRoot}reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_centerVertical" +href="{@docRoot}reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_centerVertical" >{@code android:layout_centerVertical}</a></dt> <dd>If {@code "true"}, centers this child vertically within its parent.</dd> <dt><a -href="{docRoot}reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_below" +href="{@docRoot}reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_below" >{@code android:layout_below}</a></dt> <dd>Positions the top edge of this view below the view specified with a resource ID.</dd> <dt><a -href="{docRoot}reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_toRightOf" +href="{@docRoot}reference/android/widget/RelativeLayout.LayoutParams.html#attr_android:layout_toRightOf" >{@code android:layout_toRightOf}</a></dt> <dd>Positions the left edge of this view to the right of the view specified with a resource ID.</dd> </dl> diff --git a/docs/html/guide/topics/ui/settings.jd b/docs/html/guide/topics/ui/settings.jd new file mode 100644 index 0000000..33e164b --- /dev/null +++ b/docs/html/guide/topics/ui/settings.jd @@ -0,0 +1,1171 @@ +page.title=Settings +@jd:body + + +<div id="qv-wrapper"> +<div id="qv"> + +<h2>In this document</h2> +<ol> + <li><a href="#Overview">Overview</a> + <ol> + <li><a href="#SettingTypes">Preferences</a></li> + </ol> + </li> + <li><a href="#DefiningPrefs">Defining Preferences in XML</a> + <ol> + <li><a href="#Groups">Creating setting groups</a></li> + <li><a href="#Intents">Using intents</a></li> + </ol> + </li> + <li><a href="#Activity">Creating a Preference Activity</a></li> + <li><a href="#Fragment">Using Preference Fragments</a></li> + <li><a href="#Defaults">Setting Default Values</a></li> + <li><a href="#PreferenceHeaders">Using Preference Headers</a> + <ol> + <li><a href="#CreateHeaders">Creating the headers file</a></li> + <li><a href="#DisplayHeaders">Displaying the headers</a></li> + <li><a href="#BackCompatHeaders">Supporting older versions with preference headers</a></li> + </ol> + </li> + <li><a href="#ReadingPrefs">Reading Preferences</a> + <ol> + <li><a href="#Listening">Listening for preference changes</a></li> + </ol> + </li> + <li><a href="#NetworkUsage">Managing Network Usage</a></li> + <li><a href="#Custom">Building a Custom Preference</a> + <ol> + <li><a href="#CustomSelected">Specifying the user interface</a></li> + <li><a href="#CustomSave">Saving the setting's value</a></li> + <li><a href="#CustomInitialize">Initializing the current value</a></li> + <li><a href="#CustomDefault">Providing a default value</a></li> + <li><a href="#CustomSaveState">Saving and restoring the Preference's state</a></li> + </ol> + </li> +</ol> + +<h2>Key classes</h2> +<ol> + <li>{@link android.preference.Preference}</li> + <li>{@link android.preference.PreferenceActivity}</li> + <li>{@link android.preference.PreferenceFragment}</li> +</ol> + + +<h2>See also</h2> +<ol> + <li><a +href="{@docRoot}design/patterns/settings.html">Settings design guide</a></li> +</ol> +</div> +</div> + + + + +<p>Applications often include settings that allow users to modify app features and behaviors. For +example, some apps allow users to specify whether notifications are enabled or specify how often the +application syncs data with the cloud.</p> + +<p>If you want to provide settings for your app, you should use +Android's {@link android.preference.Preference} APIs to build an interface that's consistent with +the user experience in other Android apps (including the system settings). This document describes +how to build your app settings using {@link android.preference.Preference} APIs.</p> + +<div class="note design"> +<p><strong>Settings Design</strong></p> + <p>For information about how to design your settings, read the <a +href="{@docRoot}design/patterns/settings.html">Settings</a> design guide.</p> +</div> + + +<img src="{@docRoot}images/ui/settings/settings.png" alt="" width="435" /> +<p class="img-caption"><strong>Figure 1.</strong> Screenshots from the Android Messaging app's +settings. Selecting an item defined by a {@link android.preference.Preference} +opens an interface to change the setting.</p> + + + + +<h2 id="Overview">Overview</h2> + +<p>Instead of using {@link android.view.View} objects to build the user interface, settings are +built using various subclasses of the {@link android.preference.Preference} class that you +declare in an XML file.</p> + +<p>A {@link android.preference.Preference} object is the building block for a single +setting. Each {@link android.preference.Preference} appears as an item in a list and provides the +appropriate UI for users to modify the setting. For example, a {@link +android.preference.CheckBoxPreference} creates a list item that shows a checkbox, and a {@link +android.preference.ListPreference} creates an item that opens a dialog with a list of choices.</p> + +<p>Each {@link android.preference.Preference} you add has a corresponding key-value pair that +the system uses to save the setting in a default {@link android.content.SharedPreferences} +file for your app's settings. When the user changes a setting, the system updates the corresponding +value in the {@link android.content.SharedPreferences} file for you. The only time you should +directly interact with the associated {@link android.content.SharedPreferences} file is when you +need to read the value in order to determine your app's behavior based on the user's setting.</p> + +<p>The value saved in {@link android.content.SharedPreferences} for each setting can be one of the +following data types:</p> + +<ul> + <li>Boolean</li> + <li>Float</li> + <li>Int</li> + <li>Long</li> + <li>String</li> + <li>String {@link java.util.Set}</li> +</ul> + +<p>Because your app's settings UI is built using {@link android.preference.Preference} objects +instead of +{@link android.view.View} objects, you need to use a specialized {@link android.app.Activity} or +{@link android.app.Fragment} subclass to display the list settings:</p> + +<ul> + <li>If your app supports versions of Android older than 3.0 (API level 10 and lower), you must +build the activity as an extension of the {@link android.preference.PreferenceActivity} class.</li> + <li>On Android 3.0 and later, you should instead use a traditional {@link android.app.Activity} +that hosts a {@link android.preference.PreferenceFragment} that displays your app settings. +However, you can also use {@link android.preference.PreferenceActivity} to create a two-pane layout +for large screens when you have multiple groups of settings.</li> +</ul> + +<p>How to set up your {@link android.preference.PreferenceActivity} and instances of {@link +android.preference.PreferenceFragment} is discussed in the sections about <a +href="#Activity">Creating a Preference Activity</a> and <a href="#Fragment">Using +Preference Fragments</a>.</p> + + +<h3 id="SettingTypes">Preferences</h3> + +<p>Every setting for your app is represented by a specific subclass of the {@link +android.preference.Preference} class. Each subclass includes a set of core properties that allow you +to specify things such as a title for the setting and the default value. Each subclass also provides +its own specialized properties and user interface. For instance, figure 1 shows a screenshot from +the Messaging app's settings. Each list item in the settings screen is backed by a different {@link +android.preference.Preference} object.</p> + +<p>A few of the most common preferences are:</p> + +<dl> + <dt>{@link android.preference.CheckBoxPreference}</dt> + <dd>Shows an item with a checkbox for a setting that is either enabled or disabled. The saved +value is a boolean (<code>true</code> if it's checked).</dd> + + <dt>{@link android.preference.ListPreference}</dt> + <dd>Opens a dialog with a list of radio buttons. The saved value +can be any one of the supported value types (listed above).</dd> + + <dt>{@link android.preference.EditTextPreference}</dt> + <dd>Opens a dialog with an {@link android.widget.EditText} widget. The saved value is a {@link +java.lang.String}.</dd> +</dl> + +<p>See the {@link android.preference.Preference} class for a list of all other subclasses and their +corresponding properties.</p> + +<p>Of course, the built-in classes don't accommodate every need and your application might require +something more specialized. For example, the platform currently does not provide a {@link +android.preference.Preference} class for picking a number or a date. So you might need to define +your own {@link android.preference.Preference} subclass. For help doing so, see the section about <a +href="#Custom">Building a Custom Preference</a>.</p> + + + +<h2 id="DefiningPrefs">Defining Preferences in XML</h2> + +<p>Although you can instantiate new {@link android.preference.Preference} objects at runtime, you +should define your list of settings in XML with a hierarchy of {@link android.preference.Preference} +objects. Using an XML file to define your collection of settings is preferred because the file +provides an easy-to-read structure that's simple to update. Also, your app's settings are +generally pre-determined, although you can still modify the collection at runtime.</p> + +<p>Each {@link android.preference.Preference} subclass can be declared with an XML element that +matches the class name, such as {@code <CheckBoxPreference>}.</p> + +<p>You must save the XML file in the {@code res/xml/} directory. Although you can name the file +anything you want, it's traditionally named {@code preferences.xml}. You usually need only one file, +because branches in the hierarchy (that open their own list of settings) are declared using nested +instances of {@link android.preference.PreferenceScreen}.</p> + +<p class="note"><strong>Note:</strong> If you want to create a multi-pane layout for your +settings, then you need separate XML files for each fragment.</p> + +<p>The root node for the XML file must be a {@link android.preference.PreferenceScreen +<PreferenceScreen>} element. Within this element is where you add each {@link +android.preference.Preference}. Each child you add within the +{@link android.preference.PreferenceScreen <PreferenceScreen>} element appears as a single +item in the list of settings.</p> + +<p>For example:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <CheckBoxPreference + android:key="pref_sync" + android:title="@string/pref_sync" + android:summary="@string/pref_sync_summ" + android:defaultValue="true" /> + <ListPreference + android:dependency="pref_sync" + android:key="pref_syncConnectionType" + android:title="@string/pref_syncConnectionType" + android:dialogTitle="@string/pref_syncConnectionType" + android:entries="@array/pref_syncConnectionTypes_entries" + android:entryValues="@array/pref_syncConnectionTypes_values" + android:defaultValue="@string/pref_syncConnectionTypes_default" /> +</PreferenceScreen> +</pre> + +<p>In this example, there's a {@link android.preference.CheckBoxPreference} and a {@link +android.preference.ListPreference}. Both items include the following three attributes:</p> + +<dl> + <dt>{@code android:key}</dt> + <dd>This attribute is required for preferences that persist a data value. It specifies the unique +key (a string) the system uses when saving this setting's value in the {@link +android.content.SharedPreferences}. + <p>The only instances in which this attribute is <em>not required</em> is when the preference is a +{@link android.preference.PreferenceCategory} or {@link android.preference.PreferenceScreen}, or the +preference specifies an {@link android.content.Intent} to invoke (with an <a +href="#Intents">{@code <intent>}</a> element) or a {@link android.app.Fragment} to display (with an <a +href="{@docRoot}reference/android/preference/Preference.html#attr_android:fragment">{@code +android:fragment}</a> attribute).</p> + </dd> + <dt>{@code android:title}</dt> + <dd>This provides a user-visible name for the setting.</dd> + <dt>{@code android:defaultValue}</dt> + <dd>This specifies the initial value that the system should set in the {@link +android.content.SharedPreferences} file. You should supply a default value for all +settings.</dd> +</dl> + +<p>For information about all other supported attributes, see the {@link +android.preference.Preference} (and respective subclass) documentation.</p> + + +<div class="figure" style="width:300px"> + <img src="{@docRoot}images/ui/settings/settings-titles.png" alt="" /> + <p class="img-caption"><strong>Figure 2.</strong> Setting categories + with titles. <br/><b>1.</b> The category is specified by the {@link +android.preference.PreferenceCategory <PreferenceCategory>} element. <br/><b>2.</b> The title is +specified with the {@code android:title} attribute.</p> +</div> + + +<p>When your list of settings exceeds about 10 items, you might want to add titles to +define groups of settings or display those groups in a +separate screen. These options are described in the following sections.</p> + + +<h3 id="Groups">Creating setting groups</h3> + +<p>If you present a list of 10 or more settings, users +may have difficulty scanning, comprehending, and processing them. You can remedy this by +dividing some or all of the settings into groups, effectively turning one long list into multiple +shorter lists. A group of related settings can be presented in one of two ways:</p> + +<ul> + <li><a href="#Titles">Using titles</a></li> + <li><a href="#Subscreens">Using subscreens</a></li> +</ul> + +<p>You can use one or both of these grouping techniques to organize your app's settings. When +deciding which to use and how to divide your settings, you should follow the guidelines in Android +Design's <a href="{@docRoot}design/patterns/settings.html">Settings</a> guide.</p> + + +<h4 id="Titles">Using titles</h4> + +<p>If you want to provide dividers with headings between groups of settings (as shown in figure 2), +place each group of {@link android.preference.Preference} objects inside a {@link +android.preference.PreferenceCategory}.</p> + +<p>For example:</p> + +<pre> +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <PreferenceCategory + android:title="@string/pref_sms_storage_title" + android:key="pref_key_storage_settings"> + <CheckBoxPreference + android:key="pref_key_auto_delete" + android:summary="@string/pref_summary_auto_delete" + android:title="@string/pref_title_auto_delete" + android:defaultValue="false"... /> + <Preference + android:key="pref_key_sms_delete_limit" + android:dependency="pref_key_auto_delete" + android:summary="@string/pref_summary_delete_limit" + android:title="@string/pref_title_sms_delete"... /> + <Preference + android:key="pref_key_mms_delete_limit" + android:dependency="pref_key_auto_delete" + android:summary="@string/pref_summary_delete_limit" + android:title="@string/pref_title_mms_delete" ... /> + </PreferenceCategory> + ... +</PreferenceScreen> +</pre> + + +<h4 id="Subscreens">Using subscreens</h4> + +<p>If you want to place groups of settings into a subscreen (as shown in figure 3), place the group +of {@link android.preference.Preference} objects inside a {@link +android.preference.PreferenceScreen}.</p> + +<img src="{@docRoot}images/ui/settings/settings-subscreen.png" alt="" /> +<p class="img-caption"><strong>Figure 3.</strong> Setting subscreens. The {@code +<PreferenceScreen>} element +creates an item that, when selected, opens a separate list to display the nested settings.</p> + +<p>For example:</p> + +<pre> +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- opens a subscreen of settings --> + <PreferenceScreen + android:key="button_voicemail_category_key" + android:title="@string/voicemail" + android:persistent="false"> + <ListPreference + android:key="button_voicemail_provider_key" + android:title="@string/voicemail_provider" ... /> + <!-- opens another nested subscreen --> + <PreferenceScreen + android:key="button_voicemail_setting_key" + android:title="@string/voicemail_settings" + android:persistent="false"> + ... + </PreferenceScreen> + <RingtonePreference + android:key="button_voicemail_ringtone_key" + android:title="@string/voicemail_ringtone_title" + android:ringtoneType="notification" ... /> + ... + </PreferenceScreen> + ... +</PreferenceScreen> +</pre> + + +<h3 id="Intents">Using intents</h3> + +<p>In some cases, you might want a preference item to open a different activity instead of a +settings screen, such as a web browser to view a web page. To invoke an {@link +android.content.Intent} when the user selects a preference item, add an {@code <intent>} +element as a child of the corresponding {@code <Preference>} element.</p> + +<p>For example, here's how you can use a preference item to open a web page:</p> + +<pre> +<Preference android:title="@string/prefs_web_page" > + <intent android:action="android.intent.action.VIEW" + android:data="http://www.example.com" /> +</Preference> +</pre> + +<p>You can create both implicit and explicit intents using the following attributes:</p> + +<dl> + <dt>{@code android:action}</dt> + <dd>The action to assign, as per the {@link android.content.Intent#setAction setAction()} +method.</dd> + <dt>{@code android:data}</dt> + <dd>The data to assign, as per the {@link android.content.Intent#setData setData()} method.</dd> + <dt>{@code android:mimeType}</dt> + <dd>The MIME type to assign, as per the {@link android.content.Intent#setType setType()} +method.</dd> + <dt>{@code android:targetClass}</dt> + <dd>The class part of the component name, as per the {@link android.content.Intent#setComponent +setComponent()} method.</dd> + <dt>{@code android:targetPackage}</dt> + <dd>The package part of the component name, as per the {@link +android.content.Intent#setComponent setComponent()} method.</dd> +</dl> + + + +<h2 id="Activity">Creating a Preference Activity</h2> + +<p>To display your settings in an activity, extend the {@link +android.preference.PreferenceActivity} class. This is an extension of the traditional {@link +android.app.Activity} class that displays a list of settings based on a hierarchy of {@link +android.preference.Preference} objects. The {@link android.preference.PreferenceActivity} +automatically persists the settings associated with each {@link +android.preference.Preference} when the user makes a change.</p> + +<p class="note"><strong>Note:</strong> If you're developing your application for Android 3.0 and +higher, you should instead use {@link android.preference.PreferenceFragment}. Go to the next +section about <a href="#Fragment">Using Preference Fragments</a>.</p> + +<p>The most important thing to remember is that you do not load a layout of views during the {@link +android.preference.PreferenceActivity#onCreate onCreate()} callback. Instead, you call {@link +android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} to +add the preferences you've declared in an XML file to the activity. For example, here's the bare +minimum code required for a functional {@link android.preference.PreferenceActivity}:</p> + +<pre> +public class SettingsActivity extends PreferenceActivity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + addPreferencesFromResource(R.xml.preferences); + } +} +</pre> + +<p>This is actually enough code for some apps, because as soon as the user modifies a preference, +the system saves the changes to a default {@link android.content.SharedPreferences} file that your +other application components can read when you need to check the user's settings. Many apps, +however, require a little more code in order to listen for changes that occur to the preferences. +For information about listening to changes in the {@link android.content.SharedPreferences} file, +see the section about <a href="#ReadingPrefs">Reading Preferences</a>.</p> + + + + +<h2 id="Fragment">Using Preference Fragments</h2> + +<p>If you're developing for Android 3.0 (API level 11) and higher, you should use a {@link +android.preference.PreferenceFragment} to display your list of {@link android.preference.Preference} +objects. You can add a {@link android.preference.PreferenceFragment} to any activity—you don't +need to use {@link android.preference.PreferenceActivity}.</p> + +<p><a href="{@docRoot}guide/components/fragments.html">Fragments</a> provide a more +flexible architecture for your application, compared to using activities alone, no matter what kind +of activity you're building. As such, we suggest you use {@link +android.preference.PreferenceFragment} to control the display of your settings instead of {@link +android.preference.PreferenceActivity} when possible.</p> + +<p>Your implementation of {@link android.preference.PreferenceFragment} can be as simple as +defining the {@link android.preference.PreferenceFragment#onCreate onCreate()} method to load a +preferences file with {@link android.preference.PreferenceFragment#addPreferencesFromResource +addPreferencesFromResource()}. For example:</p> + +<pre> +public static class SettingsFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Load the preferences from an XML resource + addPreferencesFromResource(R.xml.preferences); + } + ... +} +</pre> + +<p>You can then add this fragment to an {@link android.app.Activity} just as you would for any other +{@link android.app.Fragment}. For example:</p> + +<pre> +public class SettingsActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Display the fragment as the main content. + getFragmentManager().beginTransaction() + .replace(android.R.id.content, new SettingsFragment()) + .commit(); + } +} +</pre> + +<p class="note"><strong>Note:</strong> A {@link android.preference.PreferenceFragment} doesn't have +a its own {@link android.content.Context} object. If you need a {@link android.content.Context} +object, you can call {@link android.app.Fragment#getActivity()}. However, be careful to call +{@link android.app.Fragment#getActivity()} only when the fragment is attached to an activity. When +the fragment is not yet attached, or was detached during the end of its lifecycle, {@link +android.app.Fragment#getActivity()} will return null.</p> + + +<h2 id="Defaults">Setting Default Values</h2> + +<p>The preferences you create probably define some important behaviors for your application, so it's +necessary that you initialize the associated {@link android.content.SharedPreferences} file with +default values for each {@link android.preference.Preference} when the user first opens your +application.</p> + +<p>The first thing you must do is specify a default value for each {@link +android.preference.Preference} +object in your XML file using the {@code android:defaultValue} attribute. The value can be any data +type that is appropriate for the corresponding {@link android.preference.Preference} object. For +example:</p> + +<pre> +<!-- default value is a boolean --> +<CheckBoxPreference + android:defaultValue="true" + ... /> + +<!-- default value is a string --> +<ListPreference + android:defaultValue="@string/pref_syncConnectionTypes_default" + ... /> +</pre> + +<p>Then, from the {@link android.app.Activity#onCreate onCreate()} method in your application's main +activity—and in any other activity through which the user may enter your application for the +first time—call {@link android.preference.PreferenceManager#setDefaultValues +setDefaultValues()}:</p> + +<pre> +PreferenceManager.setDefaultValues(this, R.xml.advanced_preferences, false); +</pre> + +<p>Calling this during {@link android.app.Activity#onCreate onCreate()} ensures that your +application is properly initialized with default settings, which your application might need to +read in order to determine some behaviors (such as whether to download data while on a +cellular network).</p> + +<p>This method takes three arguments:</p> +<ul> + <li>Your application {@link android.content.Context}.</li> + <li>The resource ID for the preference XML file for which you want to set the default values.</li> + <li>A boolean indicating whether the default values should be set more than once. +<p>When <code>false</code>, the system sets the default values only if this method has never been +called in the past (or the {@link android.preference.PreferenceManager#KEY_HAS_SET_DEFAULT_VALUES} +in the default value shared preferences file is false).</p></li> +</ul> + +<p>As long as you set the third argument to <code>false</code>, you can safely call this method +every time your activity starts without overriding the user's saved preferences by resetting them to +the defaults. However, if you set it to <code>true</code>, you will override any previous +values with the defaults.</p> + + + +<h2 id="PreferenceHeaders">Using Preference Headers</h2> + +<p>In rare cases, you might want to design your settings such that the first screen +displays only a list of <a href="#Subscreens">subscreens</a> (such as in the system Settings app, +as shown in figures 4 and 5). When you're developing such a design for Android 3.0 and higher, you +should use a new "headers" feature in Android 3.0, instead of building subscreens with nested +{@link android.preference.PreferenceScreen} elements.</p> + +<p>To build your settings with headers, you need to:</p> +<ol> + <li>Separate each group of settings into separate instances of {@link +android.preference.PreferenceFragment}. That is, each group of settings needs a separate XML +file.</li> + <li>Create an XML headers file that lists each settings group and declares which fragment +contains the corresponding list of settings.</li> + <li>Extend the {@link android.preference.PreferenceActivity} class to host your settings.</li> + <li>Implement the {@link +android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} callback to specify the +headers file.</li> +</ol> + +<p>A great benefit to using this design is that {@link android.preference.PreferenceActivity} +automatically presents the two-pane layout shown in figure 4 when running on large screens.</p> + +<p>Even if your application supports versions of Android older than 3.0, you can build your +application to use {@link android.preference.PreferenceFragment} for a two-pane presentation on +newer devices while still supporting a traditional multi-screen hierarchy on older +devices (see the section about <a href="#BackCompatHeaders">Supporting older versions with +preference headers</a>).</p> + +<img src="{@docRoot}images/ui/settings/settings-headers-tablet.png" alt="" /> +<p class="img-caption"><strong>Figure 4.</strong> Two-pane layout with headers. <br/><b>1.</b> The +headers are defined with an XML headers file. <br/><b>2.</b> Each group of settings is defined by a +{@link android.preference.PreferenceFragment} that's specified by a {@code <header>} element in +the headers file.</p> + +<img src="{@docRoot}images/ui/settings/settings-headers-handset.png" alt="" /> +<p class="img-caption"><strong>Figure 5.</strong> A handset device with setting headers. When an +item is selected, the associated {@link android.preference.PreferenceFragment} replaces the +headers.</p> + + +<h3 id="CreateHeaders" style="clear:left">Creating the headers file</h3> + +<p>Each group of settings in your list of headers is specified by a single {@code <header>} +element inside a root {@code <preference-headers>} element. For example:</p> + +<pre> +<?xml version="1.0" encoding="utf-8"?> +<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> + <header + android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentOne" + android:title="@string/prefs_category_one" + android:summary="@string/prefs_summ_category_one" /> + <header + android:fragment="com.example.prefs.SettingsActivity$SettingsFragmentTwo" + android:title="@string/prefs_category_two" + android:summary="@string/prefs_summ_category_two" > + <!-- key/value pairs can be included as arguments for the fragment. --> + <extra android:name="someKey" android:value="someHeaderValue" /> + </header> +</preference-headers> +</pre> + +<p>With the {@code android:fragment} attribute, each header declares an instance of {@link +android.preference.PreferenceFragment} that should open when the user selects the header.</p> + +<p>The {@code <extras>} element allows you to pass key-value pairs to the fragment in a {@link +android.os.Bundle}. The fragment can retrieve the arguments by calling {@link +android.app.Fragment#getArguments()}. You might pass arguments to the fragment for a variety of +reasons, but one good reason is to reuse the same subclass of {@link +android.preference.PreferenceFragment} for each group and use the argument to specify which +preferences XML file the fragment should load.</p> + +<p>For example, here's a fragment that can be reused for multiple settings groups, when each +header defines an {@code <extra>} argument with the {@code "settings"} key:</p> + +<pre> +public static class SettingsFragment extends PreferenceFragment { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String settings = getArguments().getString("settings"); + if ("notifications".equals(settings)) { + addPreferencesFromResource(R.xml.settings_wifi); + } else if ("sync".equals(settings)) { + addPreferencesFromResource(R.xml.settings_sync); + } + } +} +</pre> + + + +<h3 id="DisplayHeaders">Displaying the headers</h3> + +<p>To display the preference headers, you must implement the {@link +android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} callback method and call +{@link android.preference.PreferenceActivity#loadHeadersFromResource +loadHeadersFromResource()}. For example:</p> + +<pre> +public class SettingsActivity extends PreferenceActivity { + @Override + public void onBuildHeaders(List<Header> target) { + loadHeadersFromResource(R.xml.preference_headers, target); + } +} +</pre> + +<p>When the user selects an item from the list of headers, the system opens the associated {@link +android.preference.PreferenceFragment}.</p> + +<p class="note"><strong>Note:</strong> When using preference headers, your subclass of {@link +android.preference.PreferenceActivity} doesn't need to implement the {@link +android.preference.PreferenceActivity#onCreate onCreate()} method, because the only required +task for the activity is to load the headers.</p> + + +<h3 id="BackCompatHeaders">Supporting older versions with preference headers</h3> + +<p>If your application supports versions of Android older than 3.0, you can still use headers to +provide a two-pane layout when running on Android 3.0 and higher. All you need to do is create an +additional preferences XML file that uses basic {@link android.preference.Preference +<Preference>} elements that behave like the header items (to be used by the older Android +versions).</p> + +<p>Instead of opening a new {@link android.preference.PreferenceScreen}, however, each of the {@link +android.preference.Preference <Preference>} elements sends an {@link android.content.Intent} to +the {@link android.preference.PreferenceActivity} that specifies which preference XML file to +load.</p> + +<p>For example, here's an XML file for preference headers that is used on Android 3.0 +and higher ({@code res/xml/preference_headers.xml}):</p> + +<pre> +<preference-headers xmlns:android="http://schemas.android.com/apk/res/android"> + <header + android:fragment="com.example.prefs.SettingsFragmentOne" + android:title="@string/prefs_category_one" + android:summary="@string/prefs_summ_category_one" /> + <header + android:fragment="com.example.prefs.SettingsFragmentTwo" + android:title="@string/prefs_category_two" + android:summary="@string/prefs_summ_category_two" /> +</preference-headers> +</pre> + +<p>And here is a preference file that provides the same headers for versions older than +Android 3.0 ({@code res/xml/preference_headers_legacy.xml}):</p> + +<pre> +<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> + <Preference + android:title="@string/prefs_category_one" + android:summary="@string/prefs_summ_category_one" > + <intent + android:targetPackage="com.example.prefs" + android:targetClass="com.example.prefs.SettingsActivity" + android:action="com.example.prefs.PREFS_ONE" /> + </Preference> + <Preference + android:title="@string/prefs_category_two" + android:summary="@string/prefs_summ_category_two" > + <intent + android:targetPackage="com.example.prefs" + android:targetClass="com.example.prefs.SettingsActivity" + android:action="com.example.prefs.PREFS_TWO" /> + </Preference> +</PreferenceScreen> +</pre> + +<p>Because support for {@code <preference-headers>} was added in Android 3.0, the system calls +{@link android.preference.PreferenceActivity#onBuildHeaders onBuildHeaders()} in your {@link +android.preference.PreferenceActivity} only when running on Androd 3.0 or higher. In order to load +the "legacy" headers file ({@code preference_headers_legacy.xml}), you must check the Android +version and, if the version is older than Android 3.0 ({@link +android.os.Build.VERSION_CODES#HONEYCOMB}), call {@link +android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} to +load the legacy header file. For example:</p> + +<pre> +@Override +public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + ... + + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + // Load the legacy preferences headers + addPreferencesFromResource(R.xml.preference_headers_legacy); + } +} + +// Called only on Honeycomb and later +@Override +public void onBuildHeaders(List<Header> target) { + loadHeadersFromResource(R.xml.preference_headers, target); +} +</pre> + +<p>The only thing left to do is handle the {@link android.content.Intent} that's passed into the +activity to identify which preference file to load. So retrieve the intent's action and compare it +to known action strings that you've used in the preference XML's {@code <intent>} tags:</p> + +<pre> +final static String ACTION_PREFS_ONE = "com.example.prefs.PREFS_ONE"; +... + +@Override +public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + String action = getIntent().getAction(); + if (action != null && action.equals(ACTION_PREFS_ONE)) { + addPreferencesFromResource(R.xml.preferences); + } + ... + + else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) { + // Load the legacy preferences headers + addPreferencesFromResource(R.xml.preference_headers_legacy); + } +} +</pre> + +<p>Beware that consecutive calls to {@link +android.preference.PreferenceActivity#addPreferencesFromResource addPreferencesFromResource()} will +stack all the preferences in a single list, so be sure that it's only called once by chaining the +conditions with else-if statements.</p> + + + + + +<h2 id="ReadingPrefs">Reading Preferences</h2> + +<p>By default, all your app's preferences are saved to a file that's accessible from anywhere +within your application by calling the static method {@link +android.preference.PreferenceManager#getDefaultSharedPreferences +PreferenceManager.getDefaultSharedPreferences()}. This returns the {@link +android.content.SharedPreferences} object containing all the key-value pairs that are associated +with the {@link android.preference.Preference} objects used in your {@link +android.preference.PreferenceActivity}.</p> + +<p>For example, here's how you can read one of the preference values from any other activity in your +application:</p> + +<pre> +SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this); +String syncConnPref = sharedPref.getString(SettingsActivity.KEY_PREF_SYNC_CONN, ""); +</pre> + + + +<h3 id="Listening">Listening for preference changes</h3> + +<p>There are several reasons you might want to be notified as soon as the use changes one of the +preferences. In order to receive a callback when a change happens to any one of the preferences, +implement the {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener +SharedPreference.OnSharedPreferenceChangeListener} interface and register the listener for the +{@link android.content.SharedPreferences} object by calling {@link +android.content.SharedPreferences#registerOnSharedPreferenceChangeListener +registerOnSharedPreferenceChangeListener()}.</p> + +<p>The interface has only one callback method, {@link +android.content.SharedPreferences.OnSharedPreferenceChangeListener#onSharedPreferenceChanged +onSharedPreferenceChanged()}, and you might find it easiest to implement the interface as a part of +your activity. For example:</p> + +<pre> +public class SettingsActivity extends PreferenceActivity + implements OnSharedPreferenceChangeListener { + public static final String KEY_PREF_SYNC_CONN = "pref_syncConnectionType"; + ... + + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals(KEY_PREF_SYNC_CONN)) { + Preference connectionPref = findPreference(key); + // Set summary to be the user-description for the selected value + connectionPref.setSummary(sharedPreferences.getString(key, "")); + } + } +} +</pre> + +<p>In this example, the method checks whether the changed setting is for a known preference key. It +calls {@link android.preference.PreferenceActivity#findPreference findPreference()} to get the +{@link android.preference.Preference} object that was changed so it can modify the item's +summary to be a description of the user's selection. That is, when the setting is a {@link +android.preference.ListPreference} or other multiple choice setting, you should call {@link +android.preference.Preference#setSummary setSummary()} when the setting changes to display the +current status (such as the Sleep setting shown in figure 5).</p> + +<p class="note"><strong>Note:</strong> As described in the Android Design document about <a +href="{@docRoot}design/patterns/settings.html">Settings</a>, we recommend that you update the +summary for a {@link android.preference.ListPreference} each time the user changes the preference in +order to describe the current setting.</p> + +<p>For proper lifecycle management in the activity, we recommend that you register and unregister +your {@link android.content.SharedPreferences.OnSharedPreferenceChangeListener} during the {@link +android.app.Activity#onResume} and {@link android.app.Activity#onPause} callbacks, respectively:</p> + +<pre> +@Override +protected void onResume() { + super.onResume(); + getPreferenceScreen().getSharedPreferences() + .registerOnSharedPreferenceChangeListener(this); +} + +@Override +protected void onPause() { + super.onPause(); + getPreferenceScreen().getSharedPreferences() + .unregisterOnSharedPreferenceChangeListener(this); +} +</pre> + + + +<h2 id="NetworkUsage">Managing Network Usage</h2> + + +<p>Beginning with Android 4.0, the system's Settings application allows users to see how much +network data their applications are using while in the foreground and background. Users can then +disable the use of background data for individual apps. In order to avoid users disabling your app's +access to data from the background, you should use the data connection efficiently and allow +users to refine your app's data usage through your application settings.<p> + +<p>For example, you might allow the user to control how often your app syncs data, whether your app +performs uploads/downloads only when on Wi-Fi, whether your app uses data while roaming, etc. With +these controls available to them, users are much less likely to disable your app's access to data +when they approach the limits they set in the system Settings, because they can instead precisely +control how much data your app uses.</p> + +<p>Once you've added the necessary preferences in your {@link android.preference.PreferenceActivity} +to control your app's data habits, you should add an intent filter for {@link +android.content.Intent#ACTION_MANAGE_NETWORK_USAGE} in your manifest file. For example:</p> + +<pre> +<activity android:name="SettingsActivity" ... > + <intent-filter> + <action android:name="android.intent.action.MANAGE_NETWORK_USAGE" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> +</activity> +</pre> + +<p>This intent filter indicates to the system that this is the activity that controls your +application's data usage. Thus, when the user inspects how much data your app is using from the +system's Settings app, a <em>View application settings</em> button is available that launches your +{@link android.preference.PreferenceActivity} so the user can refine how much data your app +uses.</p> + + + + + + + +<h2 id="Custom">Building a Custom Preference</h2> + +<p>The Android framework includes a variety of {@link android.preference.Preference} subclasses that +allow you to build a UI for several different types of settings. +However, you might discover a setting you need for which there’s no built-in solution, such as a +number picker or date picker. In such a case, you’ll need to create a custom preference by extending +the {@link android.preference.Preference} class or one of the other subclasses.</p> + +<p>When you extend the {@link android.preference.Preference} class, there are a few important +things you need to do:</p> + +<ul> + <li>Specify the user interface that appears when the user selects the settings.</li> + <li>Save the setting's value when appropriate.</li> + <li>Initialize the {@link android.preference.Preference} with the current (or default) value +when it comes into view.</li> + <li>Provide the default value when requested by the system.</li> + <li>If the {@link android.preference.Preference} provides its own UI (such as a dialog), save +and restore the state to handle lifecycle changes (such as when the user rotates the screen).</li> +</ul> + +<p>The following sections describe how to accomplish each of these tasks.</p> + + + +<h3 id="CustomSelected">Specifying the user interface</h3> + + <p>If you directly extend the {@link android.preference.Preference} class, you need to implement +{@link android.preference.Preference#onClick()} to define the action that occurs when the user +selects the item. However, most custom settings extend {@link android.preference.DialogPreference} to +show a dialog, which simplifies the procedure. When you extend {@link +android.preference.DialogPreference}, you must call {@link +android.preference.DialogPreference#setDialogLayoutResource setDialogLayoutResourcs()} during in the +class constructor to specify the layout for the dialog.</p> + + <p>For example, here's the constructor for a custom {@link +android.preference.DialogPreference} that declares the layout and specifies the text for the +default positive and negative dialog buttons:</p> + +<pre> +public class NumberPickerPreference extends DialogPreference { + public NumberPickerPreference(Context context, AttributeSet attrs) { + super(context, attrs); + + setDialogLayoutResource(R.layout.numberpicker_dialog); + setPositiveButtonText(android.R.string.ok); + setNegativeButtonText(android.R.string.cancel); + + setDialogIcon(null); + } + ... +} +</pre> + + + +<h3 id="CustomSave">Saving the setting's value</h3> + +<p>You can save a value for the setting at any time by calling one of the {@link +android.preference.Preference} class's {@code persist*()} methods, such as {@link +android.preference.Preference#persistInt persistInt()} if the setting's value is an integer or +{@link android.preference.Preference#persistBoolean persistBoolean()} to save a boolean.</p> + +<p class="note"><strong>Note:</strong> Each {@link android.preference.Preference} can save only one +data type, so you must use the {@code persist*()} method appropriate for the data type used by your +custom {@link android.preference.Preference}.</p> + +<p>When you choose to persist the setting can depend on which {@link +android.preference.Preference} class you extend. If you extend {@link +android.preference.DialogPreference}, then you should persist the value only when the dialog +closes due to a positive result (the user selects the "OK" button).</p> + +<p>When a {@link android.preference.DialogPreference} closes, the system calls the {@link +android.preference.DialogPreference#onDialogClosed onDialogClosed()} method. The method includes a +boolean argument that specifies whether the user result is "positive"—if the value is +<code>true</code>, then the user selected the positive button and you should save the new value. For +example:</p> + +<pre> +@Override +protected void onDialogClosed(boolean positiveResult) { + // When the user selects "OK", persist the new value + if (positiveResult) { + persistInt(mNewValue); + } +} +</pre> + +<p>In this example, <code>mNewValue</code> is a class member that holds the setting's current +value. Calling {@link android.preference.Preference#persistInt persistInt()} saves the value to +the {@link android.content.SharedPreferences} file (automatically using the key that's +specified in the XML file for this {@link android.preference.Preference}).</p> + + +<h3 id="CustomInitialize">Initializing the current value</h3> + +<p>When the system adds your {@link android.preference.Preference} to the screen, it +calls {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} to notify +you whether the setting has a persisted value. If there is no persisted value, this call provides +you the default value.</p> + +<p>The {@link android.preference.Preference#onSetInitialValue onSetInitialValue()} method passes +a boolean, <code>restorePersistedValue</code>, to indicate whether a value has already been persisted +for the setting. If it is <code>true</code>, then you should retrieve the persisted value by calling +one of the {@link +android.preference.Preference} class's {@code getPersisted*()} methods, such as {@link +android.preference.Preference#getPersistedInt getPersistedInt()} for an integer value. You'll +usually want to retrieve the persisted value so you can properly update the UI to reflect the +previously saved value.</p> + +<p>If <code>restorePersistedValue</code> is <code>false</code>, then you +should use the default value that is passed in the second argument.</p> + +<pre> +@Override +protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { + if (restorePersistedValue) { + // Restore existing state + mCurrentValue = this.getPersistedInt(DEFAULT_VALUE); + } else { + // Set default state from the XML attribute + mCurrentValue = (Integer) defaultValue; + persistInt(mCurrentValue); + } +} +</pre> + +<p>Each {@code getPersisted*()} method takes an argument that specifies the +default value to use in case there is actually no persisted value or the key does not exist. In +the example above, a local constant is used to specify the default value in case {@link +android.preference.Preference#getPersistedInt getPersistedInt()} can't return a persisted value.</p> + +<p class="caution"><strong>Caution:</strong> You <strong>cannot</strong> use the +<code>defaultValue</code> as the default value in the {@code getPersisted*()} method, because +its value is always null when <code>restorePersistedValue</code> is <code>true</code>.</p> + + +<h3 id="CustomDefault">Providing a default value</h3> + +<p>If the instance of your {@link android.preference.Preference} class specifies a default value +(with the {@code android:defaultValue} attribute), then the +system calls {@link android.preference.Preference#onGetDefaultValue +onGetDefaultValue()} when it instantiates the object in order to retrieve the value. You must +implement this method in order for the system to save the default value in the {@link +android.content.SharedPreferences}. For example:</p> + +<pre> +@Override +protected Object onGetDefaultValue(TypedArray a, int index) { + return a.getInteger(index, DEFAULT_VALUE); +} +</pre> + +<p>The method arguments provide everything you need: the array of attributes and the index +position of the {@code android:defaultValue}, which you must retrieve. The reason you must +implement this method to extract the default value from the attribute is because you must specify +a local default value for the attribute in case the value is undefined.</p> + + + +<h3 id="CustomSaveState">Saving and restoring the Preference's state</h3> + +<p>Just like a {@link android.view.View} in a layout, your {@link android.preference.Preference} +subclass is responsible for saving and restoring its state in case the activity or fragment is +restarted (such as when the user rotates the screen). To properly save and +restore the state of your {@link android.preference.Preference} class, you must implement the +lifecycle callback methods {@link android.preference.Preference#onSaveInstanceState +onSaveInstanceState()} and {@link +android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()}.</p> + +<p>The state of your {@link android.preference.Preference} is defined by an object that implements +the {@link android.os.Parcelable} interface. The Android framework provides such an object for you +as a starting point to define your state object: the {@link +android.preference.Preference.BaseSavedState} class.</p> + +<p>To define how your {@link android.preference.Preference} class saves its state, you should +extend the {@link android.preference.Preference.BaseSavedState} class. You need to override just + a few methods and define the {@link android.preference.Preference.BaseSavedState#CREATOR} +object.</p> + +<p>For most apps, you can copy the following implementation and simply change the lines that +handle the {@code value} if your {@link android.preference.Preference} subclass saves a data +type other than an integer.</p> + +<pre> +private static class SavedState extends BaseSavedState { + // Member that holds the setting's value + // Change this data type to match the type saved by your Preference + int value; + + public SavedState(Parcelable superState) { + super(superState); + } + + public SavedState(Parcel source) { + super(source); + // Get the current preference's value + value = source.readInt(); // Change this to read the appropriate data type + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + super.writeToParcel(dest, flags); + // Write the preference's value + dest.writeInt(value); // Change this to write the appropriate data type + } + + // Standard creator object using an instance of this class + public static final Parcelable.Creator<SavedState> CREATOR = + new Parcelable.Creator<SavedState>() { + + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; +} +</pre> + +<p>With the above implementation of {@link android.preference.Preference.BaseSavedState} added +to your app (usually as a subclass of your {@link android.preference.Preference} subclass), you +then need to implement the {@link android.preference.Preference#onSaveInstanceState +onSaveInstanceState()} and {@link +android.preference.Preference#onRestoreInstanceState onRestoreInstanceState()} methods for your +{@link android.preference.Preference} subclass.</p> + +<p>For example:</p> + +<pre> +@Override +protected Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + // Check whether this Preference is persistent (continually saved) + if (isPersistent()) { + // No need to save instance state since it's persistent, use superclass state + return superState; + } + + // Create instance of custom BaseSavedState + final SavedState myState = new SavedState(superState); + // Set the state's value with the class member that holds current setting value + myState.value = mNewValue; + return myState; +} + +@Override +protected void onRestoreInstanceState(Parcelable state) { + // Check whether we saved the state in onSaveInstanceState + if (state == null || !state.getClass().equals(SavedState.class)) { + // Didn't save the state, so call superclass + super.onRestoreInstanceState(state); + return; + } + + // Cast state to custom BaseSavedState and pass to superclass + SavedState myState = (SavedState) state; + super.onRestoreInstanceState(myState.getSuperState()); + + // Set this Preference's widget to reflect the restored state + mNumberPicker.setValue(myState.value); +} +</pre> + |
