PreferenceActivity.java revision 468c3230dafc2d131bdeded7b5a6825988166244
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.preference;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport com.android.internal.util.XmlUtils;
20b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
21b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport org.xmlpull.v1.XmlPullParser;
22b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport org.xmlpull.v1.XmlPullParserException;
23b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
24b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.app.Fragment;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ListActivity;
26b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.content.Context;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
28b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.content.res.Configuration;
29b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.content.res.TypedArray;
30b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.content.res.XmlResourceParser;
31b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.graphics.drawable.Drawable;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
3519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ngimport android.text.TextUtils;
36b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.util.AttributeSet;
37b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.util.Log;
38b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.util.Xml;
39b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.view.LayoutInflater;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View;
41b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.view.ViewGroup;
4219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ngimport android.view.View.OnClickListener;
43b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.widget.ArrayAdapter;
4419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ngimport android.widget.Button;
45b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.widget.ImageView;
46b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.widget.ListView;
47b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport android.widget.TextView;
48b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
49b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport java.io.IOException;
50b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport java.util.ArrayList;
51b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackbornimport java.util.List;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
54b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * This is the base class for an activity to show a hierarchy of preferences
55b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * to the user.  Prior to {@link android.os.Build.VERSION_CODES#HONEYCOMB}
56b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * this class only allowed the display of a single set of preference; this
57b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * functionality should now be found in the new {@link PreferenceFragment}
58b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * class.  If you are using PreferenceActivity in its old mode, the documentation
59b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * there applies to the deprecated APIs here.
60b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *
61b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>This activity shows one or more headers of preferences, each of with
62b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * is associated with a {@link PreferenceFragment} to display the preferences
63b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * of that header.  The actual layout and display of these associations can
64b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * however vary; currently there are two major approaches it may take:
65b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *
66b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <ul>
67b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <li>On a small screen it may display only the headers as a single list
68b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * when first launched.  Selecting one of the header items will re-launch
69b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * the activity with it only showing the PreferenceFragment of that header.
70b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <li>On a large screen in may display both the headers and current
71b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * PreferenceFragment together as panes.  Selecting a header item switches
72b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * to showing the correct PreferenceFragment for that item.
73b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * </ul>
74b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *
75b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>Subclasses of PreferenceActivity should implement
76b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * {@link #onBuildHeaders} to populate the header list with the desired
77b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * items.  Doing this implicitly switches the class into its new "headers
78b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * + fragments" mode rather than the old style of just showing a single
79b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * preferences list.
80b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *
81b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <a name="SampleCode"></a>
82b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <h3>Sample Code</h3>
83b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *
84b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>The following sample code shows a simple preference activity that
85b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * has two different sets of preferences.  The implementation, consisting
86b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * of the activity itself as well as its two preference fragments is:</p>
87b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *
88b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * {@sample development/samples/ApiDemos/src/com/example/android/apis/preference/PreferenceWithHeaders.java
89b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *      activity}
9019ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng *
91b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * <p>The preference_headers resource describes the headers to be displayed
92b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * and the fragments associated with them.  It is:
93b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *
94b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * {@sample development/samples/ApiDemos/res/xml/preference_headers.xml headers}
95b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn *
96b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn * <p>The first header is shown by Prefs1Fragment, which populates itself
97b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn * from the following XML resource:</p>
98b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn *
99b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn * {@sample development/samples/ApiDemos/res/xml/fragmented_preferences.xml preferences}
100b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn *
101b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn * <p>Note that this XML resource contains a preference screen holding another
102b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn * fragment, the Prefs1FragmentInner implemented here.  This allows the user
103b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn * to traverse down a hierarchy of preferences; pressing back will pop each
104b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn * fragment off the stack to return to the previous preferences.
105b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn *
106b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn * <p>See {@link PreferenceFragment} for information on implementing the
107b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn * fragments themselves.
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic abstract class PreferenceActivity extends ListActivity implements
110b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        PreferenceManager.OnPreferenceTreeClickListener,
111b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        PreferenceFragment.OnPreferenceStartFragmentCallback {
112b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    private static final String TAG = "PreferenceActivity";
11319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PREFERENCES_TAG = "android:preferences";
11519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
116b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    /**
117b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * When starting this activity, the invoking Intent can contain this extra
118b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * string to specify which fragment should be initially displayed.
119b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     */
120b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    public static final String EXTRA_SHOW_FRAGMENT = ":android:show_fragment";
121b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
122b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    /**
123b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * When starting this activity and using {@link #EXTRA_SHOW_FRAGMENT},
124b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * this extra can also be specify to supply a Bundle of arguments to pass
125b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * to that fragment when it is instantiated during the initial creation
126b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * of PreferenceActivity.
127b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     */
128b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    public static final String EXTRA_SHOW_FRAGMENT_ARGUMENTS = ":android:show_fragment_args";
129b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn
130b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    /**
131b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * When starting this activity, the invoking Intent can contain this extra
132b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * boolean that the header list should not be displayed.  This is most often
133b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * used in conjunction with {@link #EXTRA_SHOW_FRAGMENT} to launch
134b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * the activity to display a specific fragment that the user has navigated
135b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * to.
136b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     */
137b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    public static final String EXTRA_NO_HEADERS = ":android:no_headers";
138b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
139b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    private static final String BACK_STACK_PREFS = ":android:prefs";
140b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn
14119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    // extras that allow any preference activity to be launched as part of a wizard
14219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
14319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    // show Back and Next buttons? takes boolean parameter
14419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    // Back will then return RESULT_CANCELED and Next RESULT_OK
14519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    private static final String EXTRA_PREFS_SHOW_BUTTON_BAR = "extra_prefs_show_button_bar";
14619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
14709dbf1844016682ed461d080e32a43d0086e767dFreeman Ng    // add a Skip button?
14809dbf1844016682ed461d080e32a43d0086e767dFreeman Ng    private static final String EXTRA_PREFS_SHOW_SKIP = "extra_prefs_show_skip";
14909dbf1844016682ed461d080e32a43d0086e767dFreeman Ng
15019ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    // specify custom text for the Back or Next buttons, or cause a button to not appear
15119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    // at all by setting it to null
15219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    private static final String EXTRA_PREFS_SET_NEXT_TEXT = "extra_prefs_set_next_text";
15319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    private static final String EXTRA_PREFS_SET_BACK_TEXT = "extra_prefs_set_back_text";
15419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
155b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    // --- State for new mode when showing a list of headers + prefs fragment
156b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
157b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    private final ArrayList<Header> mHeaders = new ArrayList<Header>();
158b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
159b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    private HeaderAdapter mAdapter;
160b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
161b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    private View mPrefsContainer;
162b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
163b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    private boolean mSinglePane;
164b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
165b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    // --- State for old mode when showing a single preference list
16619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private PreferenceManager mPreferenceManager;
16819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
169e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell    private Bundle mSavedInstanceState;
170e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell
171b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    // --- Common state
172b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
173b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    private Button mNextButton;
174b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The starting request code given out to preference framework.
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int FIRST_REQUEST_CODE = 100;
17919ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int MSG_BIND_PREFERENCES = 0;
181b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    private static final int MSG_BUILD_HEADERS = 1;
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Handler mHandler = new Handler() {
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void handleMessage(Message msg) {
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            switch (msg.what) {
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case MSG_BIND_PREFERENCES:
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    bindPreferences();
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    break;
189b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                case MSG_BUILD_HEADERS:
190b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                    onBuildHeaders(mHeaders);
191b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                    mAdapter.notifyDataSetChanged();
192b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                    break;
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
197468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler    private static class HeaderAdapter extends ArrayAdapter<Header> {
198468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler        private static class HeaderViewHolder {
199468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            ImageView icon;
200468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            TextView title;
201468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            TextView summary;
202468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler        }
203b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
204b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        private LayoutInflater mInflater;
205b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
206b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        public HeaderAdapter(Context context, List<Header> objects) {
207b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            super(context, 0, objects);
208b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
209b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
210b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
211b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        @Override
212b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        public View getView(int position, View convertView, ViewGroup parent) {
213b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            HeaderViewHolder holder;
214b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            View view;
215b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
216b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            if (convertView == null) {
217b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                view = mInflater.inflate(com.android.internal.R.layout.preference_list_item,
218b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                        parent, false);
219b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                holder = new HeaderViewHolder();
220468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.icon = (ImageView) view.findViewById(com.android.internal.R.id.icon);
221468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.title = (TextView) view.findViewById(com.android.internal.R.id.title);
222468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.summary = (TextView) view.findViewById(com.android.internal.R.id.summary);
223b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                view.setTag(holder);
224b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            } else {
225b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                view = convertView;
226468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder = (HeaderViewHolder) view.getTag();
227b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            }
228b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
229468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            // All view fields must be updated every time, because the view may be recycled
230b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            Header header = getItem(position);
231468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            if (header.icon == null) {
232468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.icon.setImageDrawable(null);
233468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.icon.setImageResource(header.iconRes);
234468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            } else {
235468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.icon.setImageResource(0);
236468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.icon.setImageDrawable(header.icon);
237468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            }
238468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            holder.title.setText(header.title);
239468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            if (TextUtils.isEmpty(header.summary)) {
240468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.summary.setVisibility(View.GONE);
241468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            } else {
242468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.summary.setVisibility(View.VISIBLE);
243468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler                holder.summary.setText(header.summary);
244468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler            }
245b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
246b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            return view;
247b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
248b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
249b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
250b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
251b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * Description of a single Header item that the user can select.
252b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
253b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    public static class Header {
254b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        /**
255b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         * Title of the header that is shown to the user.
256b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * @attr ref android.R.styleable#PreferenceHeader_title
257b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         */
258468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler        public CharSequence title;
259b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
260b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        /**
261b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         * Optional summary describing what this header controls.
262b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * @attr ref android.R.styleable#PreferenceHeader_summary
263b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         */
264468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler        public CharSequence summary;
265b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
266b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        /**
267b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         * Optional icon resource to show for this header.
268b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * @attr ref android.R.styleable#PreferenceHeader_icon
269b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         */
270468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler        public int iconRes;
271b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
272b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        /**
273b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         * Optional icon drawable to show for this header.  (If this is non-null,
274b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         * the iconRes will be ignored.)
275b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         */
276468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler        public Drawable icon;
277b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
278b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        /**
279b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         * Full class name of the fragment to display when this header is
280b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         * selected.
281b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn         * @attr ref android.R.styleable#PreferenceHeader_fragment
282b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn         */
283468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler        public String fragment;
284b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn
285b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        /**
286b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn         * Optional arguments to supply to the fragment when it is
287b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn         * instantiated.
288b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn         */
289468c3230dafc2d131bdeded7b5a6825988166244Andrew Stadler        public Bundle fragmentArguments;
290b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
291b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onCreate(Bundle savedInstanceState) {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onCreate(savedInstanceState);
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setContentView(com.android.internal.R.layout.preference_list_content);
29719ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
298b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        mPrefsContainer = findViewById(com.android.internal.R.id.prefs);
299b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        boolean hidingHeaders = onIsHidingHeaders();
300b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        mSinglePane = hidingHeaders || !onIsMultiPane();
301b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        String initialFragment = getIntent().getStringExtra(EXTRA_SHOW_FRAGMENT);
302b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        Bundle initialArguments = getIntent().getBundleExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS);
303b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
304b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (initialFragment != null && mSinglePane) {
305b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // If we are just showing a fragment, we want to run in
306b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // new fragment mode, but don't need to compute and show
307b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // the headers.
308b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            getListView().setVisibility(View.GONE);
309b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            mPrefsContainer.setVisibility(View.VISIBLE);
310b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn            switchToHeader(initialFragment, initialArguments);
311b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
312b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        } else {
313b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // We need to try to build the headers.
314b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            onBuildHeaders(mHeaders);
315b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
316b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // If there are headers, then at this point we need to show
317b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // them and, depending on the screen, we may also show in-line
318b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // the currently selected preference fragment.
319b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            if (mHeaders.size() > 0) {
320b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                mAdapter = new HeaderAdapter(this, mHeaders);
321b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                setListAdapter(mAdapter);
322b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                if (!mSinglePane) {
323b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    mPrefsContainer.setVisibility(View.VISIBLE);
324def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                    if (initialFragment == null) {
325b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                        Header h = onGetInitialHeader();
326b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                        initialFragment = h.fragment;
327b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                        initialArguments = h.fragmentArguments;
328b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                    }
329b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn                    switchToHeader(initialFragment, initialArguments);
330b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                }
331b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
332b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // If there are no headers, we are in the old "just show a screen
333b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            // of preferences" mode.
334b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            } else {
335b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                mPreferenceManager = new PreferenceManager(this, FIRST_REQUEST_CODE);
336b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                mPreferenceManager.setOnPreferenceTreeClickListener(this);
337b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            }
338b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
339b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
340b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        getListView().setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);
341b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
34219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng        // see if we should show Back/Next buttons
34319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng        Intent intent = getIntent();
34419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng        if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_BUTTON_BAR, false)) {
34519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
34619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            findViewById(com.android.internal.R.id.button_bar).setVisibility(View.VISIBLE);
34719ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
34819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            Button backButton = (Button)findViewById(com.android.internal.R.id.back_button);
34919ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            backButton.setOnClickListener(new OnClickListener() {
35019ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                public void onClick(View v) {
35119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                    setResult(RESULT_CANCELED);
35219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                    finish();
35319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                }
35419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            });
35509dbf1844016682ed461d080e32a43d0086e767dFreeman Ng            Button skipButton = (Button)findViewById(com.android.internal.R.id.skip_button);
35609dbf1844016682ed461d080e32a43d0086e767dFreeman Ng            skipButton.setOnClickListener(new OnClickListener() {
35709dbf1844016682ed461d080e32a43d0086e767dFreeman Ng                public void onClick(View v) {
35809dbf1844016682ed461d080e32a43d0086e767dFreeman Ng                    setResult(RESULT_OK);
35909dbf1844016682ed461d080e32a43d0086e767dFreeman Ng                    finish();
36009dbf1844016682ed461d080e32a43d0086e767dFreeman Ng                }
36109dbf1844016682ed461d080e32a43d0086e767dFreeman Ng            });
36219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            mNextButton = (Button)findViewById(com.android.internal.R.id.next_button);
36319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            mNextButton.setOnClickListener(new OnClickListener() {
36419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                public void onClick(View v) {
36519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                    setResult(RESULT_OK);
36619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                    finish();
36719ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                }
36819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            });
36919ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
37019ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            // set our various button parameters
37119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            if (intent.hasExtra(EXTRA_PREFS_SET_NEXT_TEXT)) {
37219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_NEXT_TEXT);
37319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                if (TextUtils.isEmpty(buttonText)) {
37419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                    mNextButton.setVisibility(View.GONE);
37519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                }
37619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                else {
37719ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                    mNextButton.setText(buttonText);
37819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                }
37919ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            }
38019ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            if (intent.hasExtra(EXTRA_PREFS_SET_BACK_TEXT)) {
38119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                String buttonText = intent.getStringExtra(EXTRA_PREFS_SET_BACK_TEXT);
38219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                if (TextUtils.isEmpty(buttonText)) {
38319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                    backButton.setVisibility(View.GONE);
38419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                }
38519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                else {
38619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                    backButton.setText(buttonText);
38719ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng                }
38819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng            }
38909dbf1844016682ed461d080e32a43d0086e767dFreeman Ng            if (intent.getBooleanExtra(EXTRA_PREFS_SHOW_SKIP, false)) {
39009dbf1844016682ed461d080e32a43d0086e767dFreeman Ng                skipButton.setVisibility(View.VISIBLE);
39109dbf1844016682ed461d080e32a43d0086e767dFreeman Ng            }
39219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng        }
393b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
394b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
395b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
396b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * Called to determine if the activity should run in multi-pane mode.
397b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * The default implementation returns true if the screen is large
398b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * enough.
399b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
400b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    public boolean onIsMultiPane() {
401b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        Configuration config = getResources().getConfiguration();
402b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if ((config.screenLayout&Configuration.SCREENLAYOUT_SIZE_MASK)
403b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                == Configuration.SCREENLAYOUT_SIZE_XLARGE
404b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                && config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
405b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            return true;
406b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
407b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        return false;
408b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
409b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
410b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
411b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * Called to determine whether the header list should be hidden.  The
412b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * default implementation hides the list if the activity is being re-launched
413b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * when not in multi-pane mode.
414b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
415b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    public boolean onIsHidingHeaders() {
416b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        return getIntent().getBooleanExtra(EXTRA_NO_HEADERS, false);
417b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
418b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
419b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
420b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * Called to determine the initial header to be shown.  The default
421b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * implementation simply returns the fragment of the first header.  Note
422b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * that the returned Header object does not actually need to exist in
423b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * your header list -- whatever its fragment is will simply be used to
424b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * show for the initial UI.
425b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
426b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    public Header onGetInitialHeader() {
427b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        return mHeaders.get(0);
428b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
429b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
430b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
431b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * Called when the activity needs its list of headers build.  By
432b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * implementing this and adding at least one item to the list, you
433b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * will cause the activity to run in its modern fragment mode.  Note
434b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * that this function may not always be called; for example, if the
435b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * activity has been asked to display a particular fragment without
436b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * the header list, there is no need to build the headers.
437b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
438b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * <p>Typical implementations will use {@link #loadHeadersFromResource}
439b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * to fill in the list from a resource.
440b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
441b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @param target The list in which to place the headers.
442b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
443b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    public void onBuildHeaders(List<Header> target) {
444b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
445b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
446b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
447b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * Call when you need to change the headers being displayed.  Will result
448b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * in onBuildHeaders() later being called to retrieve the new list.
449b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     */
450b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    public void invalidateHeaders() {
451b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        if (!mHandler.hasMessages(MSG_BUILD_HEADERS)) {
452b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn            mHandler.sendEmptyMessage(MSG_BUILD_HEADERS);
453b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        }
454b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    }
455b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn
456b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    /**
457b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * Parse the given XML file as a header description, adding each
458b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * parsed Header into the target list.
459b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
460b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @param resid The XML resource to load and parse.
461b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @param target The list in which the parsed headers should be placed.
462b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
463b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    public void loadHeadersFromResource(int resid, List<Header> target) {
464b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        XmlResourceParser parser = null;
465b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        try {
466b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            parser = getResources().getXml(resid);
467b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            AttributeSet attrs = Xml.asAttributeSet(parser);
468b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
469b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            int type;
470b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
471b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    && type != XmlPullParser.START_TAG) {
472b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            }
473b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
474b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            String nodeName = parser.getName();
475def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn            if (!"preference-headers".equals(nodeName)) {
476b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                throw new RuntimeException(
477def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                        "XML document must start with <preference-headers> tag; found"
478b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                        + nodeName + " at " + parser.getPositionDescription());
479b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            }
480b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
481def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn            Bundle curBundle = null;
482def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn
483b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            int outerDepth = parser.getDepth();
484b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
485b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                   && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
486b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
487b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    continue;
488b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                }
489b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
490b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                nodeName = parser.getName();
491def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                if ("header".equals(nodeName)) {
492b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    Header header = new Header();
493b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
494b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    TypedArray sa = getResources().obtainAttributes(attrs,
495b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                            com.android.internal.R.styleable.PreferenceHeader);
496b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    header.title = sa.getText(
497b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                            com.android.internal.R.styleable.PreferenceHeader_title);
498b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    header.summary = sa.getText(
499b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                            com.android.internal.R.styleable.PreferenceHeader_summary);
500b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    header.iconRes = sa.getResourceId(
501b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                            com.android.internal.R.styleable.PreferenceHeader_icon, 0);
502b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    header.fragment = sa.getString(
503b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                            com.android.internal.R.styleable.PreferenceHeader_fragment);
504b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    sa.recycle();
505b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
506def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                    if (curBundle == null) {
507def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                        curBundle = new Bundle();
508def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                    }
509def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                    getResources().parseBundleExtras(parser, curBundle);
510def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                    if (curBundle.size() > 0) {
511def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                        header.fragmentArguments = curBundle;
512def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                        curBundle = null;
513def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                    }
514b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
515def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                    target.add(header);
516b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                } else {
517b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    XmlUtils.skipCurrentTag(parser);
518b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                }
519b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            }
520b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
521b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        } catch (XmlPullParserException e) {
522b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            throw new RuntimeException("Error parsing headers", e);
523b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        } catch (IOException e) {
524b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            throw new RuntimeException("Error parsing headers", e);
525b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        } finally {
526b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            if (parser != null) parser.close();
527b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
52819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onStop() {
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onStop();
53419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
535b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mPreferenceManager != null) {
536b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            mPreferenceManager.dispatchActivityStop();
537b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onDestroy() {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onDestroy();
543b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
544b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mPreferenceManager != null) {
545b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            mPreferenceManager.dispatchActivityDestroy();
546b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onSaveInstanceState(Bundle outState) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onSaveInstanceState(outState);
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
553b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mPreferenceManager != null) {
554b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            final PreferenceScreen preferenceScreen = getPreferenceScreen();
555b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            if (preferenceScreen != null) {
556b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                Bundle container = new Bundle();
557b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                preferenceScreen.saveHierarchyState(container);
558b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                outState.putBundle(PREFERENCES_TAG, container);
559b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onRestoreInstanceState(Bundle state) {
565b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mPreferenceManager != null) {
566b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            Bundle container = state.getBundle(PREFERENCES_TAG);
567b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            if (container != null) {
568b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                final PreferenceScreen preferenceScreen = getPreferenceScreen();
569b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                if (preferenceScreen != null) {
570b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    preferenceScreen.restoreHierarchyState(container);
571b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    mSavedInstanceState = state;
572b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    return;
573b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                }
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
576e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell
577e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell        // Only call this if we didn't save the instance state for later.
578e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell        // If we did save it, it will be restored when we bind the adapter.
579e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell        super.onRestoreInstanceState(state);
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onActivityResult(requestCode, resultCode, data);
58519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
586b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mPreferenceManager != null) {
587b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            mPreferenceManager.dispatchActivityResult(requestCode, resultCode, data);
588b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onContentChanged() {
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        super.onContentChanged();
594b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
595b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mPreferenceManager != null) {
596b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            postBindPreferences();
597b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
598b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
599b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
600b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    @Override
601b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    protected void onListItemClick(ListView l, View v, int position, long id) {
602b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        super.onListItemClick(l, v, position, id);
603b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
604b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mAdapter != null) {
605b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            onHeaderClick(mHeaders.get(position), position);
606b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
607b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
608b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
609b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
610b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * Called when the user selects an item in the header list.  The default
61172dc780f57b4396b808032d592c41d35644a3277Jean-Baptiste Queru     * implementation will call either {@link #startWithFragment(String, Bundle)}
61272dc780f57b4396b808032d592c41d35644a3277Jean-Baptiste Queru     * or {@link #switchToHeader(String, Bundle)} as appropriate.
613b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
614b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @param header The header that was selected.
615b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @param position The header's position in the list.
616b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
617b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    public void onHeaderClick(Header header, int position) {
618b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mSinglePane) {
619b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn            startWithFragment(header.fragment, header.fragmentArguments);
620b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        } else {
621b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn            switchToHeader(header.fragment, header.fragmentArguments);
622b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
623b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
624b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
625b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
626b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * Start a new instance of this activity, showing only the given
627b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * preference fragment.  When launched in this mode, the header list
628b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * will be hidden and the given preference fragment will be instantiated
629b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * and fill the entire activity.
630b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
631b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @param fragmentName The name of the fragment to display.
632b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * @param args Optional arguments to supply to the fragment.
633b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
634b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    public void startWithFragment(String fragmentName, Bundle args) {
635b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        Intent intent = new Intent(Intent.ACTION_MAIN);
636b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        intent.setClass(this, getClass());
637b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        intent.putExtra(EXTRA_SHOW_FRAGMENT, fragmentName);
638b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        intent.putExtra(EXTRA_SHOW_FRAGMENT_ARGUMENTS, args);
639b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        intent.putExtra(EXTRA_NO_HEADERS, true);
640b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        startActivity(intent);
641b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    }
642b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
643b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    /**
644b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * When in two-pane mode, switch the fragment pane to show the given
645b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * preference fragment.
646b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
647b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @param fragmentName The name of the fragment to display.
648b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn     * @param args Optional arguments to supply to the fragment.
649b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     */
650b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn    public void switchToHeader(String fragmentName, Bundle args) {
651def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn        getFragmentManager().popBackStack(BACK_STACK_PREFS, POP_BACK_STACK_INCLUSIVE);
652b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn
653b7a2e4772220c4b41df1260cedaf8912f4b07547Dianne Hackborn        Fragment f = Fragment.instantiate(this, fragmentName, args);
654def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn        getFragmentManager().openTransaction().replace(
655def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn                com.android.internal.R.id.prefs, f).commit();
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
658b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    @Override
659b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) {
660def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn        Fragment f = Fragment.instantiate(this, pref.getFragment(), pref.getExtras());
661def1537e9e8d0dd190cde5310ddae8b921088c9bDianne Hackborn        getFragmentManager().openTransaction().replace(com.android.internal.R.id.prefs, f)
662b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn                .addToBackStack(BACK_STACK_PREFS).commit();
663b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn        return true;
664b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn    }
665b3cf10ffa8ff9cac0da8b23a0d84076b3f501400Dianne Hackborn
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Posts a message to bind the preferences to the list view.
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * <p>
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Binding late is preferred as any custom preference types created in
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@link #onCreate(Bundle)} are able to have their views recycled.
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void postBindPreferences() {
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mHandler.hasMessages(MSG_BIND_PREFERENCES)) return;
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler.obtainMessage(MSG_BIND_PREFERENCES).sendToTarget();
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
67619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void bindPreferences() {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final PreferenceScreen preferenceScreen = getPreferenceScreen();
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (preferenceScreen != null) {
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            preferenceScreen.bind(getListView());
681e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell            if (mSavedInstanceState != null) {
682e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell                super.onRestoreInstanceState(mSavedInstanceState);
683e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell                mSavedInstanceState = null;
684e7fea45863afb10335cb7845aebcf2907d3c3e41Adam Powell            }
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
68719ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the {@link PreferenceManager} used by this activity.
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The {@link PreferenceManager}.
691b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
692b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @deprecated This function is not relevant for a modern fragment-based
693b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * PreferenceActivity.
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
695b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    @Deprecated
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PreferenceManager getPreferenceManager() {
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mPreferenceManager;
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
69919ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void requirePreferenceManager() {
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPreferenceManager == null) {
702b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            if (mAdapter == null) {
703b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                throw new RuntimeException("This should be called after super.onCreate.");
704b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            }
705b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            throw new RuntimeException(
706b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn                    "Modern two-pane PreferenceActivity requires use of a PreferenceFragment");
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Sets the root of the preference hierarchy that this activity is showing.
71219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng     *
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
714b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
715b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @deprecated This function is not relevant for a modern fragment-based
716b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * PreferenceActivity.
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
718b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    @Deprecated
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
720b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        requirePreferenceManager();
721b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPreferenceManager.setPreferences(preferenceScreen) && preferenceScreen != null) {
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            postBindPreferences();
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            CharSequence title = getPreferenceScreen().getTitle();
7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Set the title of the activity
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (title != null) {
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                setTitle(title);
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
73119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Gets the root of the preference hierarchy that this activity is showing.
73419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng     *
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The {@link PreferenceScreen} that is the root of the preference
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         hierarchy.
737b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
738b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @deprecated This function is not relevant for a modern fragment-based
739b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * PreferenceActivity.
7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
741b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    @Deprecated
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public PreferenceScreen getPreferenceScreen() {
743b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        if (mPreferenceManager != null) {
744b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn            return mPreferenceManager.getPreferenceScreen();
745b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        }
746b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn        return null;
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
74819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Adds preferences from activities that match the given {@link Intent}.
75119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng     *
7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param intent The {@link Intent} to query activities.
753b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
754b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @deprecated This function is not relevant for a modern fragment-based
755b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * PreferenceActivity.
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
757b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    @Deprecated
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addPreferencesFromIntent(Intent intent) {
7599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        requirePreferenceManager();
76019ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
7619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setPreferenceScreen(mPreferenceManager.inflateFromIntent(intent, getPreferenceScreen()));
7629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
76319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Inflates the given XML resource and adds the preference hierarchy to the current
7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * preference hierarchy.
76719ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng     *
7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param preferencesResId The XML resource ID to inflate.
769b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
770b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @deprecated This function is not relevant for a modern fragment-based
771b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * PreferenceActivity.
7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
773b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    @Deprecated
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addPreferencesFromResource(int preferencesResId) {
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        requirePreferenceManager();
77619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        setPreferenceScreen(mPreferenceManager.inflateFromResource(this, preferencesResId,
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                getPreferenceScreen()));
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * {@inheritDoc}
783b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
784b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @deprecated This function is not relevant for a modern fragment-based
785b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * PreferenceActivity.
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
787b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    @Deprecated
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
79119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Finds a {@link Preference} based on its key.
79419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng     *
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param key The key of the preference to retrieve.
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The {@link Preference} with the key, or null.
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @see PreferenceGroup#findPreference(CharSequence)
798b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     *
799b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * @deprecated This function is not relevant for a modern fragment-based
800b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn     * PreferenceActivity.
8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
802b1ad5977bc8178b6d350ebe9099daded4c1ef603Dianne Hackborn    @Deprecated
8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public Preference findPreference(CharSequence key) {
80419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPreferenceManager == null) {
8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
80819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mPreferenceManager.findPreference(key);
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void onNewIntent(Intent intent) {
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPreferenceManager != null) {
8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPreferenceManager.dispatchNewIntent(intent);
8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
81819ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng
81919ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    // give subclasses access to the Next button
82019ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    /** @hide */
82119ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    protected boolean hasNextButton() {
82219ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng        return mNextButton != null;
82319ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    }
82419ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    /** @hide */
82519ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    protected Button getNextButton() {
82619ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng        return mNextButton;
82719ea2e0d788810473136ceca46c1c28326daff5eFreeman Ng    }
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
829