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