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             defaultValueSp.edit().putBoolean(KEY_HAS_SET_DEFAULT_VALUES, true).commit();
    447         }
    448     }
    449 
    450     /**
    451      * Returns an editor to use when modifying the shared preferences.
    452      * <p>
    453      * Do NOT commit unless {@link #shouldCommit()} returns true.
    454      *
    455      * @return An editor to use to write to shared preferences.
    456      * @see #shouldCommit()
    457      */
    458     SharedPreferences.Editor getEditor() {
    459 
    460         if (mNoCommit) {
    461             if (mEditor == null) {
    462                 mEditor = getSharedPreferences().edit();
    463             }
    464 
    465             return mEditor;
    466         } else {
    467             return getSharedPreferences().edit();
    468         }
    469     }
    470 
    471     /**
    472      * Whether it is the client's responsibility to commit on the
    473      * {@link #getEditor()}. This will return false in cases where the writes
    474      * should be batched, for example when inflating preferences from XML.
    475      *
    476      * @return Whether the client should commit.
    477      */
    478     boolean shouldCommit() {
    479         return !mNoCommit;
    480     }
    481 
    482     private void setNoCommit(boolean noCommit) {
    483         if (!noCommit && mEditor != null) {
    484             mEditor.commit();
    485         }
    486 
    487         mNoCommit = noCommit;
    488     }
    489 
    490     /**
    491      * Returns the activity that shows the preferences. This is useful for doing
    492      * managed queries, but in most cases the use of {@link #getContext()} is
    493      * preferred.
    494      * <p>
    495      * This will return null if this class was instantiated with a Context
    496      * instead of Activity. For example, when setting the default values.
    497      *
    498      * @return The activity that shows the preferences.
    499      * @see #mContext
    500      */
    501     Activity getActivity() {
    502         return mActivity;
    503     }
    504 
    505     /**
    506      * Returns the context. This is preferred over {@link #getActivity()} when
    507      * possible.
    508      *
    509      * @return The context.
    510      */
    511     Context getContext() {
    512         return mContext;
    513     }
    514 
    515     /**
    516      * Registers a listener.
    517      *
    518      * @see OnActivityResultListener
    519      */
    520     void registerOnActivityResultListener(OnActivityResultListener listener) {
    521         synchronized (this) {
    522             if (mActivityResultListeners == null) {
    523                 mActivityResultListeners = new ArrayList<OnActivityResultListener>();
    524             }
    525 
    526             if (!mActivityResultListeners.contains(listener)) {
    527                 mActivityResultListeners.add(listener);
    528             }
    529         }
    530     }
    531 
    532     /**
    533      * Unregisters a listener.
    534      *
    535      * @see OnActivityResultListener
    536      */
    537     void unregisterOnActivityResultListener(OnActivityResultListener listener) {
    538         synchronized (this) {
    539             if (mActivityResultListeners != null) {
    540                 mActivityResultListeners.remove(listener);
    541             }
    542         }
    543     }
    544 
    545     /**
    546      * Called by the {@link PreferenceManager} to dispatch a subactivity result.
    547      */
    548     void dispatchActivityResult(int requestCode, int resultCode, Intent data) {
    549         List<OnActivityResultListener> list;
    550 
    551         synchronized (this) {
    552             if (mActivityResultListeners == null) return;
    553             list = new ArrayList<OnActivityResultListener>(mActivityResultListeners);
    554         }
    555 
    556         final int N = list.size();
    557         for (int i = 0; i < N; i++) {
    558             if (list.get(i).onActivityResult(requestCode, resultCode, data)) {
    559                 break;
    560             }
    561         }
    562     }
    563 
    564     /**
    565      * Registers a listener.
    566      *
    567      * @see OnActivityStopListener
    568      */
    569     void registerOnActivityStopListener(OnActivityStopListener listener) {
    570         synchronized (this) {
    571             if (mActivityStopListeners == null) {
    572                 mActivityStopListeners = new ArrayList<OnActivityStopListener>();
    573             }
    574 
    575             if (!mActivityStopListeners.contains(listener)) {
    576                 mActivityStopListeners.add(listener);
    577             }
    578         }
    579     }
    580 
    581     /**
    582      * Unregisters a listener.
    583      *
    584      * @see OnActivityStopListener
    585      */
    586     void unregisterOnActivityStopListener(OnActivityStopListener listener) {
    587         synchronized (this) {
    588             if (mActivityStopListeners != null) {
    589                 mActivityStopListeners.remove(listener);
    590             }
    591         }
    592     }
    593 
    594     /**
    595      * Called by the {@link PreferenceManager} to dispatch the activity stop
    596      * event.
    597      */
    598     void dispatchActivityStop() {
    599         List<OnActivityStopListener> list;
    600 
    601         synchronized (this) {
    602             if (mActivityStopListeners == null) return;
    603             list = new ArrayList<OnActivityStopListener>(mActivityStopListeners);
    604         }
    605 
    606         final int N = list.size();
    607         for (int i = 0; i < N; i++) {
    608             list.get(i).onActivityStop();
    609         }
    610     }
    611 
    612     /**
    613      * Registers a listener.
    614      *
    615      * @see OnActivityDestroyListener
    616      */
    617     void registerOnActivityDestroyListener(OnActivityDestroyListener listener) {
    618         synchronized (this) {
    619             if (mActivityDestroyListeners == null) {
    620                 mActivityDestroyListeners = new ArrayList<OnActivityDestroyListener>();
    621             }
    622 
    623             if (!mActivityDestroyListeners.contains(listener)) {
    624                 mActivityDestroyListeners.add(listener);
    625             }
    626         }
    627     }
    628 
    629     /**
    630      * Unregisters a listener.
    631      *
    632      * @see OnActivityDestroyListener
    633      */
    634     void unregisterOnActivityDestroyListener(OnActivityDestroyListener listener) {
    635         synchronized (this) {
    636             if (mActivityDestroyListeners != null) {
    637                 mActivityDestroyListeners.remove(listener);
    638             }
    639         }
    640     }
    641 
    642     /**
    643      * Called by the {@link PreferenceManager} to dispatch the activity destroy
    644      * event.
    645      */
    646     void dispatchActivityDestroy() {
    647         List<OnActivityDestroyListener> list = null;
    648 
    649         synchronized (this) {
    650             if (mActivityDestroyListeners != null) {
    651                 list = new ArrayList<OnActivityDestroyListener>(mActivityDestroyListeners);
    652             }
    653         }
    654 
    655         if (list != null) {
    656             final int N = list.size();
    657             for (int i = 0; i < N; i++) {
    658                 list.get(i).onActivityDestroy();
    659             }
    660         }
    661 
    662         // Dismiss any PreferenceScreens still showing
    663         dismissAllScreens();
    664     }
    665 
    666     /**
    667      * Returns a request code that is unique for the activity. Each subsequent
    668      * call to this method should return another unique request code.
    669      *
    670      * @return A unique request code that will never be used by anyone other
    671      *         than the caller of this method.
    672      */
    673     int getNextRequestCode() {
    674         synchronized (this) {
    675             return mNextRequestCode++;
    676         }
    677     }
    678 
    679     void addPreferencesScreen(DialogInterface screen) {
    680         synchronized (this) {
    681 
    682             if (mPreferencesScreens == null) {
    683                 mPreferencesScreens = new ArrayList<DialogInterface>();
    684             }
    685 
    686             mPreferencesScreens.add(screen);
    687         }
    688     }
    689 
    690     void removePreferencesScreen(DialogInterface screen) {
    691         synchronized (this) {
    692 
    693             if (mPreferencesScreens == null) {
    694                 return;
    695             }
    696 
    697             mPreferencesScreens.remove(screen);
    698         }
    699     }
    700 
    701     /**
    702      * Called by {@link PreferenceActivity} to dispatch the new Intent event.
    703      *
    704      * @param intent The new Intent.
    705      */
    706     void dispatchNewIntent(Intent intent) {
    707         dismissAllScreens();
    708     }
    709 
    710     private void dismissAllScreens() {
    711         // Remove any of the previously shown preferences screens
    712         ArrayList<DialogInterface> screensToDismiss;
    713 
    714         synchronized (this) {
    715 
    716             if (mPreferencesScreens == null) {
    717                 return;
    718             }
    719 
    720             screensToDismiss = new ArrayList<DialogInterface>(mPreferencesScreens);
    721             mPreferencesScreens.clear();
    722         }
    723 
    724         for (int i = screensToDismiss.size() - 1; i >= 0; i--) {
    725             screensToDismiss.get(i).dismiss();
    726         }
    727     }
    728 
    729     /**
    730      * Sets the callback to be invoked when a {@link Preference} in the
    731      * hierarchy rooted at this {@link PreferenceManager} is clicked.
    732      *
    733      * @param listener The callback to be invoked.
    734      */
    735     void setOnPreferenceTreeClickListener(OnPreferenceTreeClickListener listener) {
    736         mOnPreferenceTreeClickListener = listener;
    737     }
    738 
    739     OnPreferenceTreeClickListener getOnPreferenceTreeClickListener() {
    740         return mOnPreferenceTreeClickListener;
    741     }
    742 
    743     /**
    744      * Interface definition for a callback to be invoked when a
    745      * {@link Preference} in the hierarchy rooted at this {@link PreferenceScreen} is
    746      * clicked.
    747      */
    748     interface OnPreferenceTreeClickListener {
    749         /**
    750          * Called when a preference in the tree rooted at this
    751          * {@link PreferenceScreen} has been clicked.
    752          *
    753          * @param preferenceScreen The {@link PreferenceScreen} that the
    754          *        preference is located in.
    755          * @param preference The preference that was clicked.
    756          * @return Whether the click was handled.
    757          */
    758         boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference);
    759     }
    760 
    761     /**
    762      * Interface definition for a class that will be called when the container's activity
    763      * receives an activity result.
    764      */
    765     public interface OnActivityResultListener {
    766 
    767         /**
    768          * See Activity's onActivityResult.
    769          *
    770          * @return Whether the request code was handled (in which case
    771          *         subsequent listeners will not be called.
    772          */
    773         boolean onActivityResult(int requestCode, int resultCode, Intent data);
    774     }
    775 
    776     /**
    777      * Interface definition for a class that will be called when the container's activity
    778      * is stopped.
    779      */
    780     public interface OnActivityStopListener {
    781 
    782         /**
    783          * See Activity's onStop.
    784          */
    785         void onActivityStop();
    786     }
    787 
    788     /**
    789      * Interface definition for a class that will be called when the container's activity
    790      * is destroyed.
    791      */
    792     public interface OnActivityDestroyListener {
    793 
    794         /**
    795          * See Activity's onDestroy.
    796          */
    797         void onActivityDestroy();
    798     }
    799 
    800 }
    801