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