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