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