Home | History | Annotate | Download | only in preference
      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 
    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      */
    152     private PreferenceManager(Context context) {
    153         init(context);
    154     }
    155 
    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      */
    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      */
    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      */
    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 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    347     public static SharedPreferences getDefaultSharedPreferences(Context context) {
    348         return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
    349                 getDefaultSharedPreferencesMode());
    350     }
    351 
    352     private static String getDefaultSharedPreferencesName(Context context) {
    353         return context.getPackageName() + "_preferences";
    354     }
    355 
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    487     boolean shouldCommit() {
    488         return !mNoCommit;
    489     }
    490 
    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      */
    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      */
    526     Context getContext() {
    527         return mContext;
    528     }
    529 
    530     /**
    531      * Registers a listener.
    532      *
    533      * @see OnActivityResultListener
    534      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    688     int getNextRequestCode() {
    689         synchronized (this) {
    690             return mNextRequestCode++;
    691         }
    692     }
    693 
    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 
    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      */
    721     void dispatchNewIntent(Intent intent) {
    722         dismissAllScreens();
    723     }
    724 
    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      */
    750     void setOnPreferenceTreeClickListener(OnPreferenceTreeClickListener listener) {
    751         mOnPreferenceTreeClickListener = listener;
    752     }
    753 
    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          */
    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          */
    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          */
    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          */
    812         void onActivityDestroy();
    813     }
    814 
    815 }
    816