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