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