1 /* 2 * Copyright (C) 2010 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 com.android.settings; 18 19 import android.app.Activity; 20 import android.app.Dialog; 21 import android.content.ContentResolver; 22 import android.content.Context; 23 import android.content.DialogInterface; 24 import android.content.Intent; 25 import android.content.pm.PackageManager; 26 import android.os.Bundle; 27 import android.text.TextUtils; 28 import android.util.ArrayMap; 29 import android.util.Log; 30 import android.view.LayoutInflater; 31 import android.view.View; 32 import android.view.ViewGroup; 33 import android.widget.Button; 34 35 import androidx.annotation.VisibleForTesting; 36 import androidx.annotation.XmlRes; 37 import androidx.fragment.app.DialogFragment; 38 import androidx.fragment.app.Fragment; 39 import androidx.preference.Preference; 40 import androidx.preference.PreferenceGroup; 41 import androidx.preference.PreferenceScreen; 42 import androidx.recyclerview.widget.LinearLayoutManager; 43 import androidx.recyclerview.widget.RecyclerView; 44 45 import com.android.settings.core.InstrumentedPreferenceFragment; 46 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 47 import com.android.settings.support.actionbar.HelpResourceProvider; 48 import com.android.settings.widget.HighlightablePreferenceGroupAdapter; 49 import com.android.settings.widget.LoadingViewController; 50 import com.android.settingslib.CustomDialogPreferenceCompat; 51 import com.android.settingslib.CustomEditTextPreferenceCompat; 52 import com.android.settingslib.core.instrumentation.Instrumentable; 53 import com.android.settingslib.search.Indexable; 54 import com.android.settingslib.widget.LayoutPreference; 55 56 import com.google.android.material.appbar.AppBarLayout; 57 58 import java.util.UUID; 59 60 /** 61 * Base class for Settings fragments, with some helper functions and dialog management. 62 */ 63 public abstract class SettingsPreferenceFragment extends InstrumentedPreferenceFragment 64 implements DialogCreatable, HelpResourceProvider, Indexable { 65 66 private static final String TAG = "SettingsPreference"; 67 68 private static final String SAVE_HIGHLIGHTED_KEY = "android:preference_highlighted"; 69 70 private static final int ORDER_FIRST = -1; 71 72 private SettingsDialogFragment mDialogFragment; 73 // Cache the content resolver for async callbacks 74 private ContentResolver mContentResolver; 75 76 private RecyclerView.Adapter mCurrentRootAdapter; 77 private boolean mIsDataSetObserverRegistered = false; 78 private RecyclerView.AdapterDataObserver mDataSetObserver = 79 new RecyclerView.AdapterDataObserver() { 80 @Override 81 public void onChanged() { 82 onDataSetChanged(); 83 } 84 85 @Override 86 public void onItemRangeChanged(int positionStart, int itemCount) { 87 onDataSetChanged(); 88 } 89 90 @Override 91 public void onItemRangeChanged(int positionStart, int itemCount, Object payload) { 92 onDataSetChanged(); 93 } 94 95 @Override 96 public void onItemRangeInserted(int positionStart, int itemCount) { 97 onDataSetChanged(); 98 } 99 100 @Override 101 public void onItemRangeRemoved(int positionStart, int itemCount) { 102 onDataSetChanged(); 103 } 104 105 @Override 106 public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) { 107 onDataSetChanged(); 108 } 109 }; 110 111 @VisibleForTesting 112 ViewGroup mPinnedHeaderFrameLayout; 113 private AppBarLayout mAppBarLayout; 114 private LayoutPreference mHeader; 115 private View mEmptyView; 116 private LinearLayoutManager mLayoutManager; 117 private ArrayMap<String, Preference> mPreferenceCache; 118 private boolean mAnimationAllowed; 119 120 @VisibleForTesting 121 public HighlightablePreferenceGroupAdapter mAdapter; 122 @VisibleForTesting 123 public boolean mPreferenceHighlighted = false; 124 125 @Override onCreate(Bundle icicle)126 public void onCreate(Bundle icicle) { 127 super.onCreate(icicle); 128 129 if (icicle != null) { 130 mPreferenceHighlighted = icicle.getBoolean(SAVE_HIGHLIGHTED_KEY); 131 } 132 HighlightablePreferenceGroupAdapter.adjustInitialExpandedChildCount(this /* host */); 133 } 134 135 @Override onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)136 public View onCreateView(LayoutInflater inflater, ViewGroup container, 137 Bundle savedInstanceState) { 138 final View root = super.onCreateView(inflater, container, savedInstanceState); 139 mPinnedHeaderFrameLayout = root.findViewById(R.id.pinned_header); 140 mAppBarLayout = getActivity().findViewById(R.id.app_bar); 141 return root; 142 } 143 144 @Override addPreferencesFromResource(@mlRes int preferencesResId)145 public void addPreferencesFromResource(@XmlRes int preferencesResId) { 146 super.addPreferencesFromResource(preferencesResId); 147 checkAvailablePrefs(getPreferenceScreen()); 148 } 149 150 @VisibleForTesting checkAvailablePrefs(PreferenceGroup preferenceGroup)151 void checkAvailablePrefs(PreferenceGroup preferenceGroup) { 152 if (preferenceGroup == null) return; 153 for (int i = 0; i < preferenceGroup.getPreferenceCount(); i++) { 154 Preference pref = preferenceGroup.getPreference(i); 155 if (pref instanceof SelfAvailablePreference 156 && !((SelfAvailablePreference) pref).isAvailable(getContext())) { 157 pref.setVisible(false); 158 } else if (pref instanceof PreferenceGroup) { 159 checkAvailablePrefs((PreferenceGroup) pref); 160 } 161 } 162 } 163 setPinnedHeaderView(int layoutResId)164 public View setPinnedHeaderView(int layoutResId) { 165 final LayoutInflater inflater = getActivity().getLayoutInflater(); 166 final View pinnedHeader = 167 inflater.inflate(layoutResId, mPinnedHeaderFrameLayout, false); 168 setPinnedHeaderView(pinnedHeader); 169 return pinnedHeader; 170 } 171 setPinnedHeaderView(View pinnedHeader)172 public void setPinnedHeaderView(View pinnedHeader) { 173 mPinnedHeaderFrameLayout.addView(pinnedHeader); 174 mPinnedHeaderFrameLayout.setVisibility(View.VISIBLE); 175 } 176 showPinnedHeader(boolean show)177 public void showPinnedHeader(boolean show) { 178 mPinnedHeaderFrameLayout.setVisibility(show ? View.VISIBLE : View.INVISIBLE); 179 } 180 181 @Override onSaveInstanceState(Bundle outState)182 public void onSaveInstanceState(Bundle outState) { 183 super.onSaveInstanceState(outState); 184 185 if (mAdapter != null) { 186 outState.putBoolean(SAVE_HIGHLIGHTED_KEY, mAdapter.isHighlightRequested()); 187 } 188 } 189 190 @Override onActivityCreated(Bundle savedInstanceState)191 public void onActivityCreated(Bundle savedInstanceState) { 192 super.onActivityCreated(savedInstanceState); 193 setHasOptionsMenu(true); 194 } 195 196 @Override onResume()197 public void onResume() { 198 super.onResume(); 199 highlightPreferenceIfNeeded(); 200 } 201 202 @Override onBindPreferences()203 protected void onBindPreferences() { 204 registerObserverIfNeeded(); 205 } 206 207 @Override onUnbindPreferences()208 protected void onUnbindPreferences() { 209 unregisterObserverIfNeeded(); 210 } 211 setLoading(boolean loading, boolean animate)212 public void setLoading(boolean loading, boolean animate) { 213 View loadingContainer = getView().findViewById(R.id.loading_container); 214 LoadingViewController.handleLoadingContainer(loadingContainer, getListView(), 215 !loading /* done */, 216 animate); 217 } 218 registerObserverIfNeeded()219 public void registerObserverIfNeeded() { 220 if (!mIsDataSetObserverRegistered) { 221 if (mCurrentRootAdapter != null) { 222 mCurrentRootAdapter.unregisterAdapterDataObserver(mDataSetObserver); 223 } 224 mCurrentRootAdapter = getListView().getAdapter(); 225 mCurrentRootAdapter.registerAdapterDataObserver(mDataSetObserver); 226 mIsDataSetObserverRegistered = true; 227 onDataSetChanged(); 228 } 229 } 230 unregisterObserverIfNeeded()231 public void unregisterObserverIfNeeded() { 232 if (mIsDataSetObserverRegistered) { 233 if (mCurrentRootAdapter != null) { 234 mCurrentRootAdapter.unregisterAdapterDataObserver(mDataSetObserver); 235 mCurrentRootAdapter = null; 236 } 237 mIsDataSetObserverRegistered = false; 238 } 239 } 240 highlightPreferenceIfNeeded()241 public void highlightPreferenceIfNeeded() { 242 if (!isAdded()) { 243 return; 244 } 245 if (mAdapter != null) { 246 mAdapter.requestHighlight(getView(), getListView(), mAppBarLayout); 247 } 248 } 249 250 /** 251 * Returns initial expanded child count. 252 * <p/> 253 * Only override this method if the initial expanded child must be determined at run time. 254 */ getInitialExpandedChildCount()255 public int getInitialExpandedChildCount() { 256 return 0; 257 } 258 259 /** 260 * Whether preference is allowing to be displayed to the user. 261 * 262 * @param preference to check if it can be displayed to the user (not hidding in expand area). 263 * @return {@code true} when preference is allowing to be displayed to the user. 264 * {@code false} when preference is hidden in expand area and not been displayed to the user. 265 */ isPreferenceExpanded(Preference preference)266 protected boolean isPreferenceExpanded(Preference preference) { 267 return ((mAdapter == null) 268 || (mAdapter.getPreferenceAdapterPosition(preference) != RecyclerView.NO_POSITION)); 269 } 270 onDataSetChanged()271 protected void onDataSetChanged() { 272 highlightPreferenceIfNeeded(); 273 updateEmptyView(); 274 } 275 getHeaderView()276 public LayoutPreference getHeaderView() { 277 return mHeader; 278 } 279 setHeaderView(int resource)280 protected void setHeaderView(int resource) { 281 mHeader = new LayoutPreference(getPrefContext(), resource); 282 mHeader.setSelectable(false); 283 addPreferenceToTop(mHeader); 284 } 285 setHeaderView(View view)286 protected void setHeaderView(View view) { 287 mHeader = new LayoutPreference(getPrefContext(), view); 288 mHeader.setSelectable(false); 289 addPreferenceToTop(mHeader); 290 } 291 addPreferenceToTop(LayoutPreference preference)292 private void addPreferenceToTop(LayoutPreference preference) { 293 preference.setOrder(ORDER_FIRST); 294 if (getPreferenceScreen() != null) { 295 getPreferenceScreen().addPreference(preference); 296 } 297 } 298 299 @Override setPreferenceScreen(PreferenceScreen preferenceScreen)300 public void setPreferenceScreen(PreferenceScreen preferenceScreen) { 301 if (preferenceScreen != null && !preferenceScreen.isAttached()) { 302 // Without ids generated, the RecyclerView won't animate changes to the preferences. 303 preferenceScreen.setShouldUseGeneratedIds(mAnimationAllowed); 304 } 305 super.setPreferenceScreen(preferenceScreen); 306 if (preferenceScreen != null) { 307 if (mHeader != null) { 308 preferenceScreen.addPreference(mHeader); 309 } 310 } 311 } 312 313 @VisibleForTesting updateEmptyView()314 void updateEmptyView() { 315 if (mEmptyView == null) return; 316 if (getPreferenceScreen() != null) { 317 final View listContainer = getActivity().findViewById(android.R.id.list_container); 318 boolean show = (getPreferenceScreen().getPreferenceCount() 319 - (mHeader != null ? 1 : 0)) <= 0 320 || (listContainer != null && listContainer.getVisibility() != View.VISIBLE); 321 mEmptyView.setVisibility(show ? View.VISIBLE : View.GONE); 322 } else { 323 mEmptyView.setVisibility(View.VISIBLE); 324 } 325 } 326 setEmptyView(View v)327 public void setEmptyView(View v) { 328 if (mEmptyView != null) { 329 mEmptyView.setVisibility(View.GONE); 330 } 331 mEmptyView = v; 332 updateEmptyView(); 333 } 334 getEmptyView()335 public View getEmptyView() { 336 return mEmptyView; 337 } 338 339 @Override onCreateLayoutManager()340 public RecyclerView.LayoutManager onCreateLayoutManager() { 341 mLayoutManager = new LinearLayoutManager(getContext()); 342 return mLayoutManager; 343 } 344 345 @Override onCreateAdapter(PreferenceScreen preferenceScreen)346 protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) { 347 final Bundle arguments = getArguments(); 348 mAdapter = new HighlightablePreferenceGroupAdapter(preferenceScreen, 349 arguments == null 350 ? null : arguments.getString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY), 351 mPreferenceHighlighted); 352 return mAdapter; 353 } 354 setAnimationAllowed(boolean animationAllowed)355 protected void setAnimationAllowed(boolean animationAllowed) { 356 mAnimationAllowed = animationAllowed; 357 } 358 cacheRemoveAllPrefs(PreferenceGroup group)359 protected void cacheRemoveAllPrefs(PreferenceGroup group) { 360 mPreferenceCache = new ArrayMap<>(); 361 final int N = group.getPreferenceCount(); 362 for (int i = 0; i < N; i++) { 363 Preference p = group.getPreference(i); 364 if (TextUtils.isEmpty(p.getKey())) { 365 continue; 366 } 367 mPreferenceCache.put(p.getKey(), p); 368 } 369 } 370 getCachedPreference(String key)371 protected Preference getCachedPreference(String key) { 372 return mPreferenceCache != null ? mPreferenceCache.remove(key) : null; 373 } 374 removeCachedPrefs(PreferenceGroup group)375 protected void removeCachedPrefs(PreferenceGroup group) { 376 for (Preference p : mPreferenceCache.values()) { 377 group.removePreference(p); 378 } 379 mPreferenceCache = null; 380 } 381 getCachedCount()382 protected int getCachedCount() { 383 return mPreferenceCache != null ? mPreferenceCache.size() : 0; 384 } 385 386 @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) removePreference(String key)387 public boolean removePreference(String key) { 388 return removePreference(getPreferenceScreen(), key); 389 } 390 391 @VisibleForTesting removePreference(PreferenceGroup group, String key)392 boolean removePreference(PreferenceGroup group, String key) { 393 final int preferenceCount = group.getPreferenceCount(); 394 for (int i = 0; i < preferenceCount; i++) { 395 final Preference preference = group.getPreference(i); 396 final String curKey = preference.getKey(); 397 398 if (TextUtils.equals(curKey, key)) { 399 return group.removePreference(preference); 400 } 401 402 if (preference instanceof PreferenceGroup) { 403 if (removePreference((PreferenceGroup) preference, key)) { 404 return true; 405 } 406 } 407 } 408 return false; 409 } 410 411 /* 412 * The name is intentionally made different from Activity#finish(), so that 413 * users won't misunderstand its meaning. 414 */ finishFragment()415 public final void finishFragment() { 416 getActivity().onBackPressed(); 417 } 418 419 // Some helpers for functions used by the settings fragments when they were activities 420 421 /** 422 * Returns the ContentResolver from the owning Activity. 423 */ getContentResolver()424 protected ContentResolver getContentResolver() { 425 Context context = getActivity(); 426 if (context != null) { 427 mContentResolver = context.getContentResolver(); 428 } 429 return mContentResolver; 430 } 431 432 /** 433 * Returns the specified system service from the owning Activity. 434 */ getSystemService(final String name)435 protected Object getSystemService(final String name) { 436 return getActivity().getSystemService(name); 437 } 438 439 /** 440 * Returns the specified system service from the owning Activity. 441 */ getSystemService(final Class<T> serviceClass)442 protected <T> T getSystemService(final Class<T> serviceClass) { 443 return getActivity().getSystemService(serviceClass); 444 } 445 446 /** 447 * Returns the PackageManager from the owning Activity. 448 */ getPackageManager()449 protected PackageManager getPackageManager() { 450 return getActivity().getPackageManager(); 451 } 452 453 @Override onDetach()454 public void onDetach() { 455 if (isRemoving()) { 456 if (mDialogFragment != null) { 457 mDialogFragment.dismiss(); 458 mDialogFragment = null; 459 } 460 } 461 super.onDetach(); 462 } 463 464 // Dialog management 465 showDialog(int dialogId)466 protected void showDialog(int dialogId) { 467 if (mDialogFragment != null) { 468 Log.e(TAG, "Old dialog fragment not null!"); 469 } 470 mDialogFragment = SettingsDialogFragment.newInstance(this, dialogId); 471 mDialogFragment.show(getChildFragmentManager(), Integer.toString(dialogId)); 472 } 473 474 @Override onCreateDialog(int dialogId)475 public Dialog onCreateDialog(int dialogId) { 476 return null; 477 } 478 479 @Override getDialogMetricsCategory(int dialogId)480 public int getDialogMetricsCategory(int dialogId) { 481 return 0; 482 } 483 removeDialog(int dialogId)484 protected void removeDialog(int dialogId) { 485 // mDialogFragment may not be visible yet in parent fragment's onResume(). 486 // To be able to dismiss dialog at that time, don't check 487 // mDialogFragment.isVisible(). 488 if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) { 489 mDialogFragment.dismissAllowingStateLoss(); 490 } 491 mDialogFragment = null; 492 } 493 494 /** 495 * Sets the OnCancelListener of the dialog shown. This method can only be 496 * called after showDialog(int) and before removeDialog(int). The method 497 * does nothing otherwise. 498 */ setOnCancelListener(DialogInterface.OnCancelListener listener)499 protected void setOnCancelListener(DialogInterface.OnCancelListener listener) { 500 if (mDialogFragment != null) { 501 mDialogFragment.mOnCancelListener = listener; 502 } 503 } 504 505 /** 506 * Sets the OnDismissListener of the dialog shown. This method can only be 507 * called after showDialog(int) and before removeDialog(int). The method 508 * does nothing otherwise. 509 */ setOnDismissListener(DialogInterface.OnDismissListener listener)510 protected void setOnDismissListener(DialogInterface.OnDismissListener listener) { 511 if (mDialogFragment != null) { 512 mDialogFragment.mOnDismissListener = listener; 513 } 514 } 515 onDialogShowing()516 public void onDialogShowing() { 517 // override in subclass to attach a dismiss listener, for instance 518 } 519 520 @Override onDisplayPreferenceDialog(Preference preference)521 public void onDisplayPreferenceDialog(Preference preference) { 522 if (preference.getKey() == null) { 523 // Auto-key preferences that don't have a key, so the dialog can find them. 524 preference.setKey(UUID.randomUUID().toString()); 525 } 526 DialogFragment f = null; 527 if (preference instanceof RestrictedListPreference) { 528 f = RestrictedListPreference.RestrictedListPreferenceDialogFragment 529 .newInstance(preference.getKey()); 530 } else if (preference instanceof CustomListPreference) { 531 f = CustomListPreference.CustomListPreferenceDialogFragment 532 .newInstance(preference.getKey()); 533 } else if (preference instanceof CustomDialogPreferenceCompat) { 534 f = CustomDialogPreferenceCompat.CustomPreferenceDialogFragment 535 .newInstance(preference.getKey()); 536 } else if (preference instanceof CustomEditTextPreferenceCompat) { 537 f = CustomEditTextPreferenceCompat.CustomPreferenceDialogFragment 538 .newInstance(preference.getKey()); 539 } else { 540 super.onDisplayPreferenceDialog(preference); 541 return; 542 } 543 f.setTargetFragment(this, 0); 544 f.show(getFragmentManager(), "dialog_preference"); 545 onDialogShowing(); 546 } 547 548 public static class SettingsDialogFragment extends InstrumentedDialogFragment { 549 private static final String KEY_DIALOG_ID = "key_dialog_id"; 550 private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id"; 551 552 private Fragment mParentFragment; 553 554 private DialogInterface.OnCancelListener mOnCancelListener; 555 private DialogInterface.OnDismissListener mOnDismissListener; 556 newInstance(DialogCreatable fragment, int dialogId)557 public static SettingsDialogFragment newInstance(DialogCreatable fragment, int dialogId) { 558 if (!(fragment instanceof Fragment)) { 559 throw new IllegalArgumentException("fragment argument must be an instance of " 560 + Fragment.class.getName()); 561 } 562 563 final SettingsDialogFragment settingsDialogFragment = new SettingsDialogFragment(); 564 settingsDialogFragment.setParentFragment(fragment); 565 settingsDialogFragment.setDialogId(dialogId); 566 567 return settingsDialogFragment; 568 } 569 570 @Override getMetricsCategory()571 public int getMetricsCategory() { 572 if (mParentFragment == null) { 573 return Instrumentable.METRICS_CATEGORY_UNKNOWN; 574 } 575 final int metricsCategory = 576 ((DialogCreatable) mParentFragment).getDialogMetricsCategory(mDialogId); 577 if (metricsCategory <= 0) { 578 throw new IllegalStateException("Dialog must provide a metrics category"); 579 } 580 return metricsCategory; 581 } 582 583 @Override onSaveInstanceState(Bundle outState)584 public void onSaveInstanceState(Bundle outState) { 585 super.onSaveInstanceState(outState); 586 if (mParentFragment != null) { 587 outState.putInt(KEY_DIALOG_ID, mDialogId); 588 outState.putInt(KEY_PARENT_FRAGMENT_ID, mParentFragment.getId()); 589 } 590 } 591 592 @Override onStart()593 public void onStart() { 594 super.onStart(); 595 596 if (mParentFragment != null && mParentFragment instanceof SettingsPreferenceFragment) { 597 ((SettingsPreferenceFragment) mParentFragment).onDialogShowing(); 598 } 599 } 600 601 @Override onCreateDialog(Bundle savedInstanceState)602 public Dialog onCreateDialog(Bundle savedInstanceState) { 603 if (savedInstanceState != null) { 604 mDialogId = savedInstanceState.getInt(KEY_DIALOG_ID, 0); 605 mParentFragment = getParentFragment(); 606 int mParentFragmentId = savedInstanceState.getInt(KEY_PARENT_FRAGMENT_ID, -1); 607 if (mParentFragment == null) { 608 mParentFragment = getFragmentManager().findFragmentById(mParentFragmentId); 609 } 610 if (!(mParentFragment instanceof DialogCreatable)) { 611 throw new IllegalArgumentException( 612 (mParentFragment != null 613 ? mParentFragment.getClass().getName() 614 : mParentFragmentId) 615 + " must implement " 616 + DialogCreatable.class.getName()); 617 } 618 // This dialog fragment could be created from non-SettingsPreferenceFragment 619 if (mParentFragment instanceof SettingsPreferenceFragment) { 620 // restore mDialogFragment in mParentFragment 621 ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = this; 622 } 623 } 624 return ((DialogCreatable) mParentFragment).onCreateDialog(mDialogId); 625 } 626 627 @Override onCancel(DialogInterface dialog)628 public void onCancel(DialogInterface dialog) { 629 super.onCancel(dialog); 630 if (mOnCancelListener != null) { 631 mOnCancelListener.onCancel(dialog); 632 } 633 } 634 635 @Override onDismiss(DialogInterface dialog)636 public void onDismiss(DialogInterface dialog) { 637 super.onDismiss(dialog); 638 if (mOnDismissListener != null) { 639 mOnDismissListener.onDismiss(dialog); 640 } 641 } 642 getDialogId()643 public int getDialogId() { 644 return mDialogId; 645 } 646 647 @Override onDetach()648 public void onDetach() { 649 super.onDetach(); 650 651 // This dialog fragment could be created from non-SettingsPreferenceFragment 652 if (mParentFragment instanceof SettingsPreferenceFragment) { 653 // in case the dialog is not explicitly removed by removeDialog() 654 if (((SettingsPreferenceFragment) mParentFragment).mDialogFragment == this) { 655 ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = null; 656 } 657 } 658 } 659 setParentFragment(DialogCreatable fragment)660 private void setParentFragment(DialogCreatable fragment) { 661 mParentFragment = (Fragment) fragment; 662 } 663 setDialogId(int dialogId)664 private void setDialogId(int dialogId) { 665 mDialogId = dialogId; 666 } 667 } 668 hasNextButton()669 protected boolean hasNextButton() { 670 return ((ButtonBarHandler) getActivity()).hasNextButton(); 671 } 672 getNextButton()673 protected Button getNextButton() { 674 return ((ButtonBarHandler) getActivity()).getNextButton(); 675 } 676 finish()677 public void finish() { 678 Activity activity = getActivity(); 679 if (activity == null) return; 680 if (getFragmentManager().getBackStackEntryCount() > 0) { 681 getFragmentManager().popBackStack(); 682 } else { 683 activity.finish(); 684 } 685 } 686 getIntent()687 protected Intent getIntent() { 688 if (getActivity() == null) { 689 return null; 690 } 691 return getActivity().getIntent(); 692 } 693 setResult(int result, Intent intent)694 protected void setResult(int result, Intent intent) { 695 if (getActivity() == null) { 696 return; 697 } 698 getActivity().setResult(result, intent); 699 } 700 setResult(int result)701 protected void setResult(int result) { 702 if (getActivity() == null) { 703 return; 704 } 705 getActivity().setResult(result); 706 } 707 isFinishingOrDestroyed()708 protected boolean isFinishingOrDestroyed() { 709 final Activity activity = getActivity(); 710 return activity == null || activity.isFinishing() || activity.isDestroyed(); 711 } 712 } 713