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