• 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.Dialog;
20 import android.app.DialogFragment;
21 import android.app.Fragment;
22 import android.content.ContentResolver;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.content.pm.PackageManager;
27 import android.net.Uri;
28 import android.os.Bundle;
29 import android.preference.Preference;
30 import android.preference.PreferenceActivity;
31 import android.preference.PreferenceFragment;
32 import android.text.TextUtils;
33 import android.util.Log;
34 import android.view.Menu;
35 import android.view.MenuInflater;
36 import android.view.MenuItem;
37 import android.widget.Button;
38 
39 /**
40  * Base class for Settings fragments, with some helper functions and dialog management.
41  */
42 public class SettingsPreferenceFragment extends PreferenceFragment implements DialogCreatable {
43 
44     private static final String TAG = "SettingsPreferenceFragment";
45 
46     private static final int MENU_HELP = Menu.FIRST + 100;
47 
48     private SettingsDialogFragment mDialogFragment;
49 
50     private String mHelpUrl;
51 
52     // Cache the content resolver for async callbacks
53     private ContentResolver mContentResolver;
54 
55     @Override
onCreate(Bundle icicle)56     public void onCreate(Bundle icicle) {
57         super.onCreate(icicle);
58 
59         // Prepare help url and enable menu if necessary
60         int helpResource = getHelpResource();
61         if (helpResource != 0) {
62             mHelpUrl = getResources().getString(helpResource);
63         }
64     }
65 
66     @Override
onActivityCreated(Bundle savedInstanceState)67     public void onActivityCreated(Bundle savedInstanceState) {
68         super.onActivityCreated(savedInstanceState);
69         if (!TextUtils.isEmpty(mHelpUrl)) {
70             setHasOptionsMenu(true);
71         }
72     }
73 
removePreference(String key)74     protected void removePreference(String key) {
75         Preference pref = findPreference(key);
76         if (pref != null) {
77             getPreferenceScreen().removePreference(pref);
78         }
79     }
80 
81     /**
82      * Override this if you want to show a help item in the menu, by returning the resource id.
83      * @return the resource id for the help url
84      */
getHelpResource()85     protected int getHelpResource() {
86         return 0;
87     }
88 
89     @Override
onCreateOptionsMenu(Menu menu, MenuInflater inflater)90     public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
91         if (mHelpUrl != null && getActivity() != null) {
92             MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_label);
93             HelpUtils.prepareHelpMenuItem(getActivity(), helpItem, mHelpUrl);
94         }
95     }
96 
97     /*
98      * The name is intentionally made different from Activity#finish(), so that
99      * users won't misunderstand its meaning.
100      */
finishFragment()101     public final void finishFragment() {
102         getActivity().onBackPressed();
103     }
104 
105     // Some helpers for functions used by the settings fragments when they were activities
106 
107     /**
108      * Returns the ContentResolver from the owning Activity.
109      */
getContentResolver()110     protected ContentResolver getContentResolver() {
111         Context context = getActivity();
112         if (context != null) {
113             mContentResolver = context.getContentResolver();
114         }
115         return mContentResolver;
116     }
117 
118     /**
119      * Returns the specified system service from the owning Activity.
120      */
getSystemService(final String name)121     protected Object getSystemService(final String name) {
122         return getActivity().getSystemService(name);
123     }
124 
125     /**
126      * Returns the PackageManager from the owning Activity.
127      */
getPackageManager()128     protected PackageManager getPackageManager() {
129         return getActivity().getPackageManager();
130     }
131 
132     @Override
onDetach()133     public void onDetach() {
134         if (isRemoving()) {
135             if (mDialogFragment != null) {
136                 mDialogFragment.dismiss();
137                 mDialogFragment = null;
138             }
139         }
140         super.onDetach();
141     }
142 
143     // Dialog management
144 
showDialog(int dialogId)145     protected void showDialog(int dialogId) {
146         if (mDialogFragment != null) {
147             Log.e(TAG, "Old dialog fragment not null!");
148         }
149         mDialogFragment = new SettingsDialogFragment(this, dialogId);
150         mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
151     }
152 
onCreateDialog(int dialogId)153     public Dialog onCreateDialog(int dialogId) {
154         return null;
155     }
156 
removeDialog(int dialogId)157     protected void removeDialog(int dialogId) {
158         // mDialogFragment may not be visible yet in parent fragment's onResume().
159         // To be able to dismiss dialog at that time, don't check
160         // mDialogFragment.isVisible().
161         if (mDialogFragment != null && mDialogFragment.getDialogId() == dialogId) {
162             mDialogFragment.dismiss();
163         }
164         mDialogFragment = null;
165     }
166 
167     /**
168      * Sets the OnCancelListener of the dialog shown. This method can only be
169      * called after showDialog(int) and before removeDialog(int). The method
170      * does nothing otherwise.
171      */
setOnCancelListener(DialogInterface.OnCancelListener listener)172     protected void setOnCancelListener(DialogInterface.OnCancelListener listener) {
173         if (mDialogFragment != null) {
174             mDialogFragment.mOnCancelListener = listener;
175         }
176     }
177 
178     /**
179      * Sets the OnDismissListener of the dialog shown. This method can only be
180      * called after showDialog(int) and before removeDialog(int). The method
181      * does nothing otherwise.
182      */
setOnDismissListener(DialogInterface.OnDismissListener listener)183     protected void setOnDismissListener(DialogInterface.OnDismissListener listener) {
184         if (mDialogFragment != null) {
185             mDialogFragment.mOnDismissListener = listener;
186         }
187     }
188 
onDialogShowing()189     public void onDialogShowing() {
190         // override in subclass to attach a dismiss listener, for instance
191     }
192 
193     public static class SettingsDialogFragment extends DialogFragment {
194         private static final String KEY_DIALOG_ID = "key_dialog_id";
195         private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id";
196 
197         private int mDialogId;
198 
199         private Fragment mParentFragment;
200 
201         private DialogInterface.OnCancelListener mOnCancelListener;
202         private DialogInterface.OnDismissListener mOnDismissListener;
203 
SettingsDialogFragment()204         public SettingsDialogFragment() {
205             /* do nothing */
206         }
207 
SettingsDialogFragment(DialogCreatable fragment, int dialogId)208         public SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
209             mDialogId = dialogId;
210             if (!(fragment instanceof Fragment)) {
211                 throw new IllegalArgumentException("fragment argument must be an instance of "
212                         + Fragment.class.getName());
213             }
214             mParentFragment = (Fragment) fragment;
215         }
216 
217         @Override
onSaveInstanceState(Bundle outState)218         public void onSaveInstanceState(Bundle outState) {
219             super.onSaveInstanceState(outState);
220             if (mParentFragment != null) {
221                 outState.putInt(KEY_DIALOG_ID, mDialogId);
222                 outState.putInt(KEY_PARENT_FRAGMENT_ID, mParentFragment.getId());
223             }
224         }
225 
226         @Override
onStart()227         public void onStart() {
228             super.onStart();
229 
230             if (mParentFragment != null && mParentFragment instanceof SettingsPreferenceFragment) {
231                 ((SettingsPreferenceFragment) mParentFragment).onDialogShowing();
232             }
233         }
234 
235         @Override
onCreateDialog(Bundle savedInstanceState)236         public Dialog onCreateDialog(Bundle savedInstanceState) {
237             if (savedInstanceState != null) {
238                 mDialogId = savedInstanceState.getInt(KEY_DIALOG_ID, 0);
239                 int mParentFragmentId = savedInstanceState.getInt(KEY_PARENT_FRAGMENT_ID, -1);
240                 if (mParentFragmentId > -1) {
241                     mParentFragment = getFragmentManager().findFragmentById(mParentFragmentId);
242                     if (!(mParentFragment instanceof DialogCreatable)) {
243                         throw new IllegalArgumentException(
244                                 (mParentFragment != null
245                                         ? mParentFragment.getClass().getName()
246                                         : mParentFragmentId)
247                                 + " must implement "
248                                 + DialogCreatable.class.getName());
249                     }
250                 }
251                 // This dialog fragment could be created from non-SettingsPreferenceFragment
252                 if (mParentFragment instanceof SettingsPreferenceFragment) {
253                     // restore mDialogFragment in mParentFragment
254                     ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = this;
255                 }
256             }
257             return ((DialogCreatable) mParentFragment).onCreateDialog(mDialogId);
258         }
259 
260         @Override
onCancel(DialogInterface dialog)261         public void onCancel(DialogInterface dialog) {
262             super.onCancel(dialog);
263             if (mOnCancelListener != null) {
264                 mOnCancelListener.onCancel(dialog);
265             }
266         }
267 
268         @Override
onDismiss(DialogInterface dialog)269         public void onDismiss(DialogInterface dialog) {
270             super.onDismiss(dialog);
271             if (mOnDismissListener != null) {
272                 mOnDismissListener.onDismiss(dialog);
273             }
274         }
275 
getDialogId()276         public int getDialogId() {
277             return mDialogId;
278         }
279 
280         @Override
onDetach()281         public void onDetach() {
282             super.onDetach();
283 
284             // This dialog fragment could be created from non-SettingsPreferenceFragment
285             if (mParentFragment instanceof SettingsPreferenceFragment) {
286                 // in case the dialog is not explicitly removed by removeDialog()
287                 if (((SettingsPreferenceFragment) mParentFragment).mDialogFragment == this) {
288                     ((SettingsPreferenceFragment) mParentFragment).mDialogFragment = null;
289                 }
290             }
291         }
292     }
293 
hasNextButton()294     protected boolean hasNextButton() {
295         return ((ButtonBarHandler)getActivity()).hasNextButton();
296     }
297 
getNextButton()298     protected Button getNextButton() {
299         return ((ButtonBarHandler)getActivity()).getNextButton();
300     }
301 
finish()302     public void finish() {
303         getActivity().onBackPressed();
304     }
305 
startFragment( Fragment caller, String fragmentClass, int requestCode, Bundle extras)306     public boolean startFragment(
307             Fragment caller, String fragmentClass, int requestCode, Bundle extras) {
308         if (getActivity() instanceof PreferenceActivity) {
309             PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
310             preferenceActivity.startPreferencePanel(fragmentClass, extras,
311                     R.string.lock_settings_picker_title, null, caller, requestCode);
312             return true;
313         } else {
314             Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
315                     + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
316                     + ")");
317             return false;
318         }
319     }
320 
321 }
322