• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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