• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.preference;
18 
19 import java.util.ArrayList;
20 import java.util.HashSet;
21 import java.util.List;
22 
23 import android.app.Activity;
24 import android.app.Dialog;
25 import android.content.Context;
26 import android.content.DialogInterface;
27 import android.content.Intent;
28 import android.content.SharedPreferences;
29 import android.content.pm.ActivityInfo;
30 import android.content.pm.PackageManager;
31 import android.content.pm.ResolveInfo;
32 import android.content.pm.PackageManager.NameNotFoundException;
33 import android.content.res.XmlResourceParser;
34 import android.os.Bundle;
35 import android.util.Log;
36 
37 /**
38  * Used to help create {@link Preference} hierarchies
39  * from activities or XML.
40  * <p>
41  * In most cases, clients should use
42  * {@link PreferenceActivity#addPreferencesFromIntent} or
43  * {@link PreferenceActivity#addPreferencesFromResource(int)}.
44  *
45  * @see PreferenceActivity
46  */
47 public class PreferenceManager {
48 
49     private static final String TAG = "PreferenceManager";
50 
51     /**
52      * The Activity meta-data key for its XML preference hierarchy.
53      */
54     public static final String METADATA_KEY_PREFERENCES = "android.preference";
55 
56     public static final String KEY_HAS_SET_DEFAULT_VALUES = "_has_set_default_values";
57 
58     /**
59      * @see #getActivity()
60      */
61     private Activity mActivity;
62 
63     /**
64      * The context to use. This should always be set.
65      *
66      * @see #mActivity
67      */
68     private Context mContext;
69 
70     /**
71      * The counter for unique IDs.
72      */
73     private long mNextId = 0;
74 
75     /**
76      * The counter for unique request codes.
77      */
78     private int mNextRequestCode;
79 
80     /**
81      * Cached shared preferences.
82      */
83     private SharedPreferences mSharedPreferences;
84 
85     /**
86      * If in no-commit mode, the shared editor to give out (which will be
87      * committed when exiting no-commit mode).
88      */
89     private SharedPreferences.Editor mEditor;
90 
91     /**
92      * Blocks commits from happening on the shared editor. This is used when
93      * inflating the hierarchy. Do not set this directly, use {@link #setNoCommit(boolean)}
94      */
95     private boolean mNoCommit;
96 
97     /**
98      * The SharedPreferences name that will be used for all {@link Preference}s
99      * managed by this instance.
100      */
101     private String mSharedPreferencesName;
102 
103     /**
104      * The SharedPreferences mode that will be used for all {@link Preference}s
105      * managed by this instance.
106      */
107     private int mSharedPreferencesMode;
108 
109     /**
110      * The {@link PreferenceScreen} at the root of the preference hierarchy.
111      */
112     private PreferenceScreen mPreferenceScreen;
113 
114     /**
115      * List of activity result listeners.
116      */
117     private List<OnActivityResultListener> mActivityResultListeners;
118 
119     /**
120      * List of activity stop listeners.
121      */
122     private List<OnActivityStopListener> mActivityStopListeners;
123 
124     /**
125      * List of activity destroy listeners.
126      */
127     private List<OnActivityDestroyListener> mActivityDestroyListeners;
128 
129     /**
130      * List of dialogs that should be dismissed when we receive onNewIntent in
131      * our PreferenceActivity.
132      */
133     private List<DialogInterface> mPreferencesScreens;
134 
135     private OnPreferenceTreeClickListener mOnPreferenceTreeClickListener;
136 
PreferenceManager(Activity activity, int firstRequestCode)137     PreferenceManager(Activity activity, int firstRequestCode) {
138         mActivity = activity;
139         mNextRequestCode = firstRequestCode;
140 
141         init(activity);
142     }
143 
144     /**
145      * This constructor should ONLY be used when getting default values from
146      * an XML preference hierarchy.
147      * <p>
148      * The {@link PreferenceManager#PreferenceManager(Activity)}
149      * should be used ANY time a preference will be displayed, since some preference
150      * types need an Activity for managed queries.
151      */
PreferenceManager(Context context)152     private PreferenceManager(Context context) {
153         init(context);
154     }
155 
init(Context context)156     private void init(Context context) {
157         mContext = context;
158 
159         setSharedPreferencesName(getDefaultSharedPreferencesName(context));
160     }
161 
162     /**
163      * Returns a list of {@link Activity} (indirectly) that match a given
164      * {@link Intent}.
165      *
166      * @param queryIntent The Intent to match.
167      * @return The list of {@link ResolveInfo} that point to the matched
168      *         activities.
169      */
queryIntentActivities(Intent queryIntent)170     private List<ResolveInfo> queryIntentActivities(Intent queryIntent) {
171         return mContext.getPackageManager().queryIntentActivities(queryIntent,
172                 PackageManager.GET_META_DATA);
173     }
174 
175     /**
176      * Inflates a preference hierarchy from the preference hierarchies of
177      * {@link Activity Activities} that match the given {@link Intent}. An
178      * {@link Activity} defines its preference hierarchy with meta-data using
179      * the {@link #METADATA_KEY_PREFERENCES} key.
180      * <p>
181      * If a preference hierarchy is given, the new preference hierarchies will
182      * be merged in.
183      *
184      * @param queryIntent The intent to match activities.
185      * @param rootPreferences Optional existing hierarchy to merge the new
186      *            hierarchies into.
187      * @return The root hierarchy (if one was not provided, the new hierarchy's
188      *         root).
189      */
inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences)190     PreferenceScreen inflateFromIntent(Intent queryIntent, PreferenceScreen rootPreferences) {
191         final List<ResolveInfo> activities = queryIntentActivities(queryIntent);
192         final HashSet<String> inflatedRes = new HashSet<String>();
193 
194         for (int i = activities.size() - 1; i >= 0; i--) {
195             final ActivityInfo activityInfo = activities.get(i).activityInfo;
196             final Bundle metaData = activityInfo.metaData;
197 
198             if ((metaData == null) || !metaData.containsKey(METADATA_KEY_PREFERENCES)) {
199                 continue;
200             }
201 
202             // Need to concat the package with res ID since the same res ID
203             // can be re-used across contexts
204             final String uniqueResId = activityInfo.packageName + ":"
205                     + activityInfo.metaData.getInt(METADATA_KEY_PREFERENCES);
206 
207             if (!inflatedRes.contains(uniqueResId)) {
208                 inflatedRes.add(uniqueResId);
209 
210                 final Context context;
211                 try {
212                     context = mContext.createPackageContext(activityInfo.packageName, 0);
213                 } catch (NameNotFoundException e) {
214                     Log.w(TAG, "Could not create context for " + activityInfo.packageName + ": "
215                         + Log.getStackTraceString(e));
216                     continue;
217                 }
218 
219                 final PreferenceInflater inflater = new PreferenceInflater(context, this);
220                 final XmlResourceParser parser = activityInfo.loadXmlMetaData(context
221                         .getPackageManager(), METADATA_KEY_PREFERENCES);
222                 rootPreferences = (PreferenceScreen) inflater
223                         .inflate(parser, rootPreferences, true);
224                 parser.close();
225             }
226         }
227 
228         rootPreferences.onAttachedToHierarchy(this);
229 
230         return rootPreferences;
231     }
232 
233     /**
234      * Inflates a preference hierarchy from XML. If a preference hierarchy is
235      * given, the new preference hierarchies will be merged in.
236      *
237      * @param context The context of the resource.
238      * @param resId The resource ID of the XML to inflate.
239      * @param rootPreferences Optional existing hierarchy to merge the new
240      *            hierarchies into.
241      * @return The root hierarchy (if one was not provided, the new hierarchy's
242      *         root).
243      * @hide
244      */
inflateFromResource(Context context, int resId, PreferenceScreen rootPreferences)245     public PreferenceScreen inflateFromResource(Context context, int resId,
246             PreferenceScreen rootPreferences) {
247         // Block commits
248         setNoCommit(true);
249 
250         final PreferenceInflater inflater = new PreferenceInflater(context, this);
251         rootPreferences = (PreferenceScreen) inflater.inflate(resId, rootPreferences, true);
252         rootPreferences.onAttachedToHierarchy(this);
253 
254         // Unblock commits
255         setNoCommit(false);
256 
257         return rootPreferences;
258     }
259 
createPreferenceScreen(Context context)260     public PreferenceScreen createPreferenceScreen(Context context) {
261         final PreferenceScreen preferenceScreen = new PreferenceScreen(context, null);
262         preferenceScreen.onAttachedToHierarchy(this);
263         return preferenceScreen;
264     }
265 
266     /**
267      * Called by a preference to get a unique ID in its hierarchy.
268      *
269      * @return A unique ID.
270      */
getNextId()271     long getNextId() {
272         synchronized (this) {
273             return mNextId++;
274         }
275     }
276 
277     /**
278      * Returns the current name of the SharedPreferences file that preferences managed by
279      * this will use.
280      *
281      * @return The name that can be passed to {@link Context#getSharedPreferences(String, int)}.
282      * @see Context#getSharedPreferences(String, int)
283      */
getSharedPreferencesName()284     public String getSharedPreferencesName() {
285         return mSharedPreferencesName;
286     }
287 
288     /**
289      * Sets the name of the SharedPreferences file that preferences managed by this
290      * will use.
291      *
292      * @param sharedPreferencesName The name of the SharedPreferences file.
293      * @see Context#getSharedPreferences(String, int)
294      */
setSharedPreferencesName(String sharedPreferencesName)295     public void setSharedPreferencesName(String sharedPreferencesName) {
296         mSharedPreferencesName = sharedPreferencesName;
297         mSharedPreferences = null;
298     }
299 
300     /**
301      * Returns the current mode of the SharedPreferences file that preferences managed by
302      * this will use.
303      *
304      * @return The mode that can be passed to {@link Context#getSharedPreferences(String, int)}.
305      * @see Context#getSharedPreferences(String, int)
306      */
getSharedPreferencesMode()307     public int getSharedPreferencesMode() {
308         return mSharedPreferencesMode;
309     }
310 
311     /**
312      * Sets the mode of the SharedPreferences file that preferences managed by this
313      * will use.
314      *
315      * @param sharedPreferencesMode The mode of the SharedPreferences file.
316      * @see Context#getSharedPreferences(String, int)
317      */
setSharedPreferencesMode(int sharedPreferencesMode)318     public void setSharedPreferencesMode(int sharedPreferencesMode) {
319         mSharedPreferencesMode = sharedPreferencesMode;
320         mSharedPreferences = null;
321     }
322 
323     /**
324      * Gets a SharedPreferences instance that preferences managed by this will
325      * use.
326      *
327      * @return A SharedPreferences instance pointing to the file that contains
328      *         the values of preferences that are managed by this.
329      */
getSharedPreferences()330     public SharedPreferences getSharedPreferences() {
331         if (mSharedPreferences == null) {
332             mSharedPreferences = mContext.getSharedPreferences(mSharedPreferencesName,
333                     mSharedPreferencesMode);
334         }
335 
336         return mSharedPreferences;
337     }
338 
339     /**
340      * Gets a SharedPreferences instance that points to the default file that is
341      * used by the preference framework in the given context.
342      *
343      * @param context The context of the preferences whose values are wanted.
344      * @return A SharedPreferences instance that can be used to retrieve and
345      *         listen to values of the preferences.
346      */
getDefaultSharedPreferences(Context context)347     public static SharedPreferences getDefaultSharedPreferences(Context context) {
348         return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
349                 getDefaultSharedPreferencesMode());
350     }
351 
getDefaultSharedPreferencesName(Context context)352     private static String getDefaultSharedPreferencesName(Context context) {
353         return context.getPackageName() + "_preferences";
354     }
355 
getDefaultSharedPreferencesMode()356     private static int getDefaultSharedPreferencesMode() {
357         return Context.MODE_PRIVATE;
358     }
359 
360     /**
361      * Returns the root of the preference hierarchy managed by this class.
362      *
363      * @return The {@link PreferenceScreen} object that is at the root of the hierarchy.
364      */
getPreferenceScreen()365     PreferenceScreen getPreferenceScreen() {
366         return mPreferenceScreen;
367     }
368 
369     /**
370      * Sets the root of the preference hierarchy.
371      *
372      * @param preferenceScreen The root {@link PreferenceScreen} of the preference hierarchy.
373      * @return Whether the {@link PreferenceScreen} given is different than the previous.
374      */
setPreferences(PreferenceScreen preferenceScreen)375     boolean setPreferences(PreferenceScreen preferenceScreen) {
376         if (preferenceScreen != mPreferenceScreen) {
377             mPreferenceScreen = preferenceScreen;
378             return true;
379         }
380 
381         return false;
382     }
383 
384     /**
385      * Finds a {@link Preference} based on its key.
386      *
387      * @param key The key of the preference to retrieve.
388      * @return The {@link Preference} with the key, or null.
389      * @see PreferenceGroup#findPreference(CharSequence)
390      */
findPreference(CharSequence key)391     public Preference findPreference(CharSequence key) {
392         if (mPreferenceScreen == null) {
393             return null;
394         }
395 
396         return mPreferenceScreen.findPreference(key);
397     }
398 
399     /**
400      * Sets the default values from a preference hierarchy in XML. This should
401      * be called by the application's main activity.
402      * <p>
403      * If {@code readAgain} is false, this will only set the default values if this
404      * method has never been called in the past (or the
405      * {@link #KEY_HAS_SET_DEFAULT_VALUES} in the default value shared
406      * preferences file is false). To attempt to set the default values again
407      * bypassing this check, set {@code readAgain} to true.
408      *
409      * @param context The context of the shared preferences.
410      * @param resId The resource ID of the preference hierarchy XML file.
411      * @param readAgain Whether to re-read the default values.
412      *            <p>
413      *            Note: this will NOT reset preferences back to their default
414      *            values. For that functionality, use
415      *            {@link PreferenceManager#getDefaultSharedPreferences(Context)}
416      *            and clear it followed by a call to this method with this
417      *            parameter set to true.
418      */
setDefaultValues(Context context, int resId, boolean readAgain)419     public static void setDefaultValues(Context context, int resId, boolean readAgain) {
420 
421         // Use the default shared preferences name and mode
422         setDefaultValues(context, getDefaultSharedPreferencesName(context),
423                 getDefaultSharedPreferencesMode(), resId, readAgain);
424     }
425 
426     /**
427      * Similar to {@link #setDefaultValues(Context, int, boolean)} but allows
428      * the client to provide the filename and mode of the shared preferences
429      * file.
430      *
431      * @see #setDefaultValues(Context, int, boolean)
432      * @see #setSharedPreferencesName(String)
433      * @see #setSharedPreferencesMode(int)
434      */
setDefaultValues(Context context, String sharedPreferencesName, int sharedPreferencesMode, int resId, boolean readAgain)435     public static void setDefaultValues(Context context, String sharedPreferencesName,
436             int sharedPreferencesMode, int resId, boolean readAgain) {
437         final SharedPreferences defaultValueSp = context.getSharedPreferences(
438                 KEY_HAS_SET_DEFAULT_VALUES, Context.MODE_PRIVATE);
439 
440         if (readAgain || !defaultValueSp.getBoolean(KEY_HAS_SET_DEFAULT_VALUES, false)) {
441             final PreferenceManager pm = new PreferenceManager(context);
442             pm.setSharedPreferencesName(sharedPreferencesName);
443             pm.setSharedPreferencesMode(sharedPreferencesMode);
444             pm.inflateFromResource(context, resId, null);
445 
446             SharedPreferences.Editor editor =
447                     defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true);
448             try {
449                 editor.apply();
450             } catch (AbstractMethodError unused) {
451                 // The app injected its own pre-Gingerbread
452                 // SharedPreferences.Editor implementation without
453                 // an apply method.
454                 editor.commit();
455             }
456         }
457     }
458 
459     /**
460      * Returns an editor to use when modifying the shared preferences.
461      * <p>
462      * Do NOT commit unless {@link #shouldCommit()} returns true.
463      *
464      * @return An editor to use to write to shared preferences.
465      * @see #shouldCommit()
466      */
getEditor()467     SharedPreferences.Editor getEditor() {
468 
469         if (mNoCommit) {
470             if (mEditor == null) {
471                 mEditor = getSharedPreferences().edit();
472             }
473 
474             return mEditor;
475         } else {
476             return getSharedPreferences().edit();
477         }
478     }
479 
480     /**
481      * Whether it is the client's responsibility to commit on the
482      * {@link #getEditor()}. This will return false in cases where the writes
483      * should be batched, for example when inflating preferences from XML.
484      *
485      * @return Whether the client should commit.
486      */
shouldCommit()487     boolean shouldCommit() {
488         return !mNoCommit;
489     }
490 
setNoCommit(boolean noCommit)491     private void setNoCommit(boolean noCommit) {
492         if (!noCommit && mEditor != null) {
493             try {
494                 mEditor.apply();
495             } catch (AbstractMethodError unused) {
496                 // The app injected its own pre-Gingerbread
497                 // SharedPreferences.Editor implementation without
498                 // an apply method.
499                 mEditor.commit();
500             }
501         }
502         mNoCommit = noCommit;
503     }
504 
505     /**
506      * Returns the activity that shows the preferences. This is useful for doing
507      * managed queries, but in most cases the use of {@link #getContext()} is
508      * preferred.
509      * <p>
510      * This will return null if this class was instantiated with a Context
511      * instead of Activity. For example, when setting the default values.
512      *
513      * @return The activity that shows the preferences.
514      * @see #mContext
515      */
getActivity()516     Activity getActivity() {
517         return mActivity;
518     }
519 
520     /**
521      * Returns the context. This is preferred over {@link #getActivity()} when
522      * possible.
523      *
524      * @return The context.
525      */
getContext()526     Context getContext() {
527         return mContext;
528     }
529 
530     /**
531      * Registers a listener.
532      *
533      * @see OnActivityResultListener
534      */
registerOnActivityResultListener(OnActivityResultListener listener)535     void registerOnActivityResultListener(OnActivityResultListener listener) {
536         synchronized (this) {
537             if (mActivityResultListeners == null) {
538                 mActivityResultListeners = new ArrayList<OnActivityResultListener>();
539             }
540 
541             if (!mActivityResultListeners.contains(listener)) {
542                 mActivityResultListeners.add(listener);
543             }
544         }
545     }
546 
547     /**
548      * Unregisters a listener.
549      *
550      * @see OnActivityResultListener
551      */
unregisterOnActivityResultListener(OnActivityResultListener listener)552     void unregisterOnActivityResultListener(OnActivityResultListener listener) {
553         synchronized (this) {
554             if (mActivityResultListeners != null) {
555                 mActivityResultListeners.remove(listener);
556             }
557         }
558     }
559 
560     /**
561      * Called by the {@link PreferenceManager} to dispatch a subactivity result.
562      */
dispatchActivityResult(int requestCode, int resultCode, Intent data)563     void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
564         List<OnActivityResultListener> list;
565 
566         synchronized (this) {
567             if (mActivityResultListeners == null) return;
568             list = new ArrayList<OnActivityResultListener>(mActivityResultListeners);
569         }
570 
571         final int N = list.size();
572         for (int i = 0; i < N; i++) {
573             if (list.get(i).onActivityResult(requestCode, resultCode, data)) {
574                 break;
575             }
576         }
577     }
578 
579     /**
580      * Registers a listener.
581      *
582      * @see OnActivityStopListener
583      */
registerOnActivityStopListener(OnActivityStopListener listener)584     void registerOnActivityStopListener(OnActivityStopListener listener) {
585         synchronized (this) {
586             if (mActivityStopListeners == null) {
587                 mActivityStopListeners = new ArrayList<OnActivityStopListener>();
588             }
589 
590             if (!mActivityStopListeners.contains(listener)) {
591                 mActivityStopListeners.add(listener);
592             }
593         }
594     }
595 
596     /**
597      * Unregisters a listener.
598      *
599      * @see OnActivityStopListener
600      */
unregisterOnActivityStopListener(OnActivityStopListener listener)601     void unregisterOnActivityStopListener(OnActivityStopListener listener) {
602         synchronized (this) {
603             if (mActivityStopListeners != null) {
604                 mActivityStopListeners.remove(listener);
605             }
606         }
607     }
608 
609     /**
610      * Called by the {@link PreferenceManager} to dispatch the activity stop
611      * event.
612      */
dispatchActivityStop()613     void dispatchActivityStop() {
614         List<OnActivityStopListener> list;
615 
616         synchronized (this) {
617             if (mActivityStopListeners == null) return;
618             list = new ArrayList<OnActivityStopListener>(mActivityStopListeners);
619         }
620 
621         final int N = list.size();
622         for (int i = 0; i < N; i++) {
623             list.get(i).onActivityStop();
624         }
625     }
626 
627     /**
628      * Registers a listener.
629      *
630      * @see OnActivityDestroyListener
631      */
registerOnActivityDestroyListener(OnActivityDestroyListener listener)632     void registerOnActivityDestroyListener(OnActivityDestroyListener listener) {
633         synchronized (this) {
634             if (mActivityDestroyListeners == null) {
635                 mActivityDestroyListeners = new ArrayList<OnActivityDestroyListener>();
636             }
637 
638             if (!mActivityDestroyListeners.contains(listener)) {
639                 mActivityDestroyListeners.add(listener);
640             }
641         }
642     }
643 
644     /**
645      * Unregisters a listener.
646      *
647      * @see OnActivityDestroyListener
648      */
unregisterOnActivityDestroyListener(OnActivityDestroyListener listener)649     void unregisterOnActivityDestroyListener(OnActivityDestroyListener listener) {
650         synchronized (this) {
651             if (mActivityDestroyListeners != null) {
652                 mActivityDestroyListeners.remove(listener);
653             }
654         }
655     }
656 
657     /**
658      * Called by the {@link PreferenceManager} to dispatch the activity destroy
659      * event.
660      */
dispatchActivityDestroy()661     void dispatchActivityDestroy() {
662         List<OnActivityDestroyListener> list = null;
663 
664         synchronized (this) {
665             if (mActivityDestroyListeners != null) {
666                 list = new ArrayList<OnActivityDestroyListener>(mActivityDestroyListeners);
667             }
668         }
669 
670         if (list != null) {
671             final int N = list.size();
672             for (int i = 0; i < N; i++) {
673                 list.get(i).onActivityDestroy();
674             }
675         }
676 
677         // Dismiss any PreferenceScreens still showing
678         dismissAllScreens();
679     }
680 
681     /**
682      * Returns a request code that is unique for the activity. Each subsequent
683      * call to this method should return another unique request code.
684      *
685      * @return A unique request code that will never be used by anyone other
686      *         than the caller of this method.
687      */
getNextRequestCode()688     int getNextRequestCode() {
689         synchronized (this) {
690             return mNextRequestCode++;
691         }
692     }
693 
addPreferencesScreen(DialogInterface screen)694     void addPreferencesScreen(DialogInterface screen) {
695         synchronized (this) {
696 
697             if (mPreferencesScreens == null) {
698                 mPreferencesScreens = new ArrayList<DialogInterface>();
699             }
700 
701             mPreferencesScreens.add(screen);
702         }
703     }
704 
removePreferencesScreen(DialogInterface screen)705     void removePreferencesScreen(DialogInterface screen) {
706         synchronized (this) {
707 
708             if (mPreferencesScreens == null) {
709                 return;
710             }
711 
712             mPreferencesScreens.remove(screen);
713         }
714     }
715 
716     /**
717      * Called by {@link PreferenceActivity} to dispatch the new Intent event.
718      *
719      * @param intent The new Intent.
720      */
dispatchNewIntent(Intent intent)721     void dispatchNewIntent(Intent intent) {
722         dismissAllScreens();
723     }
724 
dismissAllScreens()725     private void dismissAllScreens() {
726         // Remove any of the previously shown preferences screens
727         ArrayList<DialogInterface> screensToDismiss;
728 
729         synchronized (this) {
730 
731             if (mPreferencesScreens == null) {
732                 return;
733             }
734 
735             screensToDismiss = new ArrayList<DialogInterface>(mPreferencesScreens);
736             mPreferencesScreens.clear();
737         }
738 
739         for (int i = screensToDismiss.size() - 1; i >= 0; i--) {
740             screensToDismiss.get(i).dismiss();
741         }
742     }
743 
744     /**
745      * Sets the callback to be invoked when a {@link Preference} in the
746      * hierarchy rooted at this {@link PreferenceManager} is clicked.
747      *
748      * @param listener The callback to be invoked.
749      */
setOnPreferenceTreeClickListener(OnPreferenceTreeClickListener listener)750     void setOnPreferenceTreeClickListener(OnPreferenceTreeClickListener listener) {
751         mOnPreferenceTreeClickListener = listener;
752     }
753 
getOnPreferenceTreeClickListener()754     OnPreferenceTreeClickListener getOnPreferenceTreeClickListener() {
755         return mOnPreferenceTreeClickListener;
756     }
757 
758     /**
759      * Interface definition for a callback to be invoked when a
760      * {@link Preference} in the hierarchy rooted at this {@link PreferenceScreen} is
761      * clicked.
762      */
763     interface OnPreferenceTreeClickListener {
764         /**
765          * Called when a preference in the tree rooted at this
766          * {@link PreferenceScreen} has been clicked.
767          *
768          * @param preferenceScreen The {@link PreferenceScreen} that the
769          *        preference is located in.
770          * @param preference The preference that was clicked.
771          * @return Whether the click was handled.
772          */
onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)773         boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference);
774     }
775 
776     /**
777      * Interface definition for a class that will be called when the container's activity
778      * receives an activity result.
779      */
780     public interface OnActivityResultListener {
781 
782         /**
783          * See Activity's onActivityResult.
784          *
785          * @return Whether the request code was handled (in which case
786          *         subsequent listeners will not be called.
787          */
onActivityResult(int requestCode, int resultCode, Intent data)788         boolean onActivityResult(int requestCode, int resultCode, Intent data);
789     }
790 
791     /**
792      * Interface definition for a class that will be called when the container's activity
793      * is stopped.
794      */
795     public interface OnActivityStopListener {
796 
797         /**
798          * See Activity's onStop.
799          */
onActivityStop()800         void onActivityStop();
801     }
802 
803     /**
804      * Interface definition for a class that will be called when the container's activity
805      * is destroyed.
806      */
807     public interface OnActivityDestroyListener {
808 
809         /**
810          * See Activity's onDestroy.
811          */
onActivityDestroy()812         void onActivityDestroy();
813     }
814 
815 }
816