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