blob: 60765a99da07035ce800acbcb6b0ef14776f2cb6 [file] [log] [blame]
Amith Yamasanid7993472010-08-18 13:59:28 -07001/*
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
17package com.android.settings;
18
19import android.app.Dialog;
20import android.app.DialogFragment;
Daisuke Miyakawab5647c52010-09-10 18:04:02 -070021import android.app.Fragment;
Amith Yamasanid7993472010-08-18 13:59:28 -070022import android.content.ContentResolver;
Amith Yamasani350938e2013-04-09 10:22:47 -070023import android.content.Context;
Hung-ying Tyan0ee51e02011-01-25 16:42:14 +080024import android.content.DialogInterface;
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070025import android.content.Intent;
Amith Yamasanid7993472010-08-18 13:59:28 -070026import android.content.pm.PackageManager;
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070027import android.net.Uri;
Amith Yamasanid7993472010-08-18 13:59:28 -070028import android.os.Bundle;
Amith Yamasani9627a8e2012-09-23 12:54:14 -070029import android.preference.Preference;
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070030import android.preference.PreferenceActivity;
Amith Yamasanid7993472010-08-18 13:59:28 -070031import android.preference.PreferenceFragment;
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070032import android.text.TextUtils;
Amith Yamasanid7993472010-08-18 13:59:28 -070033import android.util.Log;
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070034import android.view.Menu;
35import android.view.MenuInflater;
36import android.view.MenuItem;
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -070037import android.widget.Button;
Amith Yamasanid7993472010-08-18 13:59:28 -070038
Daisuke Miyakawaf58090d2010-09-12 17:27:33 -070039/**
Amith Yamasanid7993472010-08-18 13:59:28 -070040 * Base class for Settings fragments, with some helper functions and dialog management.
41 */
Gilles Debunne64650542011-08-23 11:01:35 -070042public class SettingsPreferenceFragment extends PreferenceFragment implements DialogCreatable {
Amith Yamasanid7993472010-08-18 13:59:28 -070043
44 private static final String TAG = "SettingsPreferenceFragment";
45
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070046 private static final int MENU_HELP = Menu.FIRST + 100;
47
Amith Yamasanid7993472010-08-18 13:59:28 -070048 private SettingsDialogFragment mDialogFragment;
49
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070050 private String mHelpUrl;
51
Amith Yamasani350938e2013-04-09 10:22:47 -070052 // Cache the content resolver for async callbacks
53 private ContentResolver mContentResolver;
54
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070055 @Override
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);
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070063 }
64 }
65
Daisuke Miyakawab5647c52010-09-10 18:04:02 -070066 @Override
Amith Yamasanid7993472010-08-18 13:59:28 -070067 public void onActivityCreated(Bundle savedInstanceState) {
68 super.onActivityCreated(savedInstanceState);
Amith Yamasanib3a593e2012-04-23 18:03:52 -070069 if (!TextUtils.isEmpty(mHelpUrl)) {
70 setHasOptionsMenu(true);
71 }
Amith Yamasanid7993472010-08-18 13:59:28 -070072 }
73
Amith Yamasani9627a8e2012-09-23 12:54:14 -070074 protected void removePreference(String key) {
75 Preference pref = findPreference(key);
76 if (pref != null) {
77 getPreferenceScreen().removePreference(pref);
78 }
79 }
80
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070081 /**
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 */
85 protected int getHelpResource() {
86 return 0;
87 }
88
89 @Override
90 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
Amith Yamasaniaeb57ed2012-12-06 14:40:51 -080091 if (mHelpUrl != null && getActivity() != null) {
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070092 MenuItem helpItem = menu.add(0, MENU_HELP, 0, R.string.help_label);
Amith Yamasaniaeb57ed2012-12-06 14:40:51 -080093 HelpUtils.prepareHelpMenuItem(getActivity(), helpItem, mHelpUrl);
Amith Yamasanib0b37ae2012-04-23 15:35:36 -070094 }
95 }
96
Daisuke Miyakawab5647c52010-09-10 18:04:02 -070097 /*
98 * The name is intentionally made different from Activity#finish(), so that
99 * users won't misunderstand its meaning.
100 */
101 public final void finishFragment() {
102 getActivity().onBackPressed();
103 }
104
Amith Yamasanid7993472010-08-18 13:59:28 -0700105 // Some helpers for functions used by the settings fragments when they were activities
106
107 /**
108 * Returns the ContentResolver from the owning Activity.
109 */
110 protected ContentResolver getContentResolver() {
Amith Yamasani350938e2013-04-09 10:22:47 -0700111 Context context = getActivity();
112 if (context != null) {
113 mContentResolver = context.getContentResolver();
114 }
115 return mContentResolver;
Amith Yamasanid7993472010-08-18 13:59:28 -0700116 }
117
118 /**
119 * Returns the specified system service from the owning Activity.
120 */
121 protected Object getSystemService(final String name) {
122 return getActivity().getSystemService(name);
123 }
124
125 /**
Amith Yamasanid7993472010-08-18 13:59:28 -0700126 * Returns the PackageManager from the owning Activity.
127 */
128 protected PackageManager getPackageManager() {
129 return getActivity().getPackageManager();
130 }
131
Dianne Hackborn0385cf12011-01-24 16:22:13 -0800132 @Override
133 public void onDetach() {
134 if (isRemoving()) {
135 if (mDialogFragment != null) {
136 mDialogFragment.dismiss();
137 mDialogFragment = null;
138 }
139 }
140 super.onDetach();
141 }
142
Amith Yamasanid7993472010-08-18 13:59:28 -0700143 // Dialog management
144
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);
Daisuke Miyakawa21c1abc2010-09-12 15:42:56 -0700150 mDialogFragment.show(getActivity().getFragmentManager(), Integer.toString(dialogId));
Amith Yamasanid7993472010-08-18 13:59:28 -0700151 }
152
153 public Dialog onCreateDialog(int dialogId) {
154 return null;
155 }
156
157 protected void removeDialog(int dialogId) {
Hung-ying Tyanadc83d82011-01-24 15:05:27 +0800158 // 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) {
Amith Yamasanid7993472010-08-18 13:59:28 -0700162 mDialogFragment.dismiss();
163 }
164 mDialogFragment = null;
165 }
166
Hung-ying Tyan0ee51e02011-01-25 16:42:14 +0800167 /**
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 */
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 */
183 protected void setOnDismissListener(DialogInterface.OnDismissListener listener) {
184 if (mDialogFragment != null) {
185 mDialogFragment.mOnDismissListener = listener;
186 }
187 }
188
Amith Yamasanic861cf82012-10-02 14:51:46 -0700189 public void onDialogShowing() {
190 // override in subclass to attach a dismiss listener, for instance
191 }
192
Amith Yamasani43c69782010-12-01 09:04:36 -0800193 public static class SettingsDialogFragment extends DialogFragment {
Svetoslav Ganov749ba652010-12-09 14:53:02 -0800194 private static final String KEY_DIALOG_ID = "key_dialog_id";
195 private static final String KEY_PARENT_FRAGMENT_ID = "key_parent_fragment_id";
196
Amith Yamasanid7993472010-08-18 13:59:28 -0700197 private int mDialogId;
198
Svetoslav Ganov749ba652010-12-09 14:53:02 -0800199 private Fragment mParentFragment;
200
Hung-ying Tyan0ee51e02011-01-25 16:42:14 +0800201 private DialogInterface.OnCancelListener mOnCancelListener;
202 private DialogInterface.OnDismissListener mOnDismissListener;
203
Svetoslav Ganov749ba652010-12-09 14:53:02 -0800204 public SettingsDialogFragment() {
205 /* do nothing */
206 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700207
Amith Yamasani43c69782010-12-01 09:04:36 -0800208 public SettingsDialogFragment(DialogCreatable fragment, int dialogId) {
Amith Yamasanid7993472010-08-18 13:59:28 -0700209 mDialogId = dialogId;
Svetoslav Ganov749ba652010-12-09 14:53:02 -0800210 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
Dianne Hackborn300768f2011-01-27 20:39:21 -0800218 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
Amith Yamasanic861cf82012-10-02 14:51:46 -0700227 public void onStart() {
228 super.onStart();
229
230 if (mParentFragment != null && mParentFragment instanceof SettingsPreferenceFragment) {
231 ((SettingsPreferenceFragment) mParentFragment).onDialogShowing();
232 }
233 }
234
235 @Override
Dianne Hackborn300768f2011-01-27 20:39:21 -0800236 public Dialog onCreateDialog(Bundle savedInstanceState) {
Svetoslav Ganov749ba652010-12-09 14:53:02 -0800237 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(
Amith Yamasani258f7c72013-02-05 10:56:55 -0800244 (mParentFragment != null
245 ? mParentFragment.getClass().getName()
246 : mParentFragmentId)
247 + " must implement "
248 + DialogCreatable.class.getName());
Svetoslav Ganov749ba652010-12-09 14:53:02 -0800249 }
250 }
Amith Yamasani8875ede2011-01-31 12:46:57 -0800251 // 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 }
Svetoslav Ganov749ba652010-12-09 14:53:02 -0800256 }
Svetoslav Ganov749ba652010-12-09 14:53:02 -0800257 return ((DialogCreatable) mParentFragment).onCreateDialog(mDialogId);
Amith Yamasanid7993472010-08-18 13:59:28 -0700258 }
259
Hung-ying Tyan0ee51e02011-01-25 16:42:14 +0800260 @Override
261 public void onCancel(DialogInterface dialog) {
262 super.onCancel(dialog);
263 if (mOnCancelListener != null) {
264 mOnCancelListener.onCancel(dialog);
265 }
266 }
267
268 @Override
269 public void onDismiss(DialogInterface dialog) {
270 super.onDismiss(dialog);
271 if (mOnDismissListener != null) {
272 mOnDismissListener.onDismiss(dialog);
273 }
274 }
Amith Yamasani8875ede2011-01-31 12:46:57 -0800275
Amith Yamasanid7993472010-08-18 13:59:28 -0700276 public int getDialogId() {
277 return mDialogId;
278 }
Hung-ying Tyan18eb39d2011-01-28 16:17:27 +0800279
280 @Override
281 public void onDetach() {
282 super.onDetach();
283
Amith Yamasani8875ede2011-01-31 12:46:57 -0800284 // 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 }
Hung-ying Tyan18eb39d2011-01-28 16:17:27 +0800290 }
291 }
Amith Yamasanid7993472010-08-18 13:59:28 -0700292 }
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -0700293
294 protected boolean hasNextButton() {
Daisuke Miyakawa79c5fd92011-01-15 14:58:00 -0800295 return ((ButtonBarHandler)getActivity()).hasNextButton();
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -0700296 }
297
298 protected Button getNextButton() {
Daisuke Miyakawa79c5fd92011-01-15 14:58:00 -0800299 return ((ButtonBarHandler)getActivity()).getNextButton();
Daisuke Miyakawa9c8bde52010-08-25 11:58:37 -0700300 }
301
Daisuke Miyakawa6ebf8612010-09-10 09:48:51 -0700302 public void finish() {
303 getActivity().onBackPressed();
304 }
305
Daisuke Miyakawab5647c52010-09-10 18:04:02 -0700306 public boolean startFragment(
307 Fragment caller, String fragmentClass, int requestCode, Bundle extras) {
Daisuke Miyakawa25af1502010-09-24 11:29:31 -0700308 if (getActivity() instanceof PreferenceActivity) {
309 PreferenceActivity preferenceActivity = (PreferenceActivity)getActivity();
Gilles Debunne64650542011-08-23 11:01:35 -0700310 preferenceActivity.startPreferencePanel(fragmentClass, extras,
311 R.string.lock_settings_picker_title, null, caller, requestCode);
Daisuke Miyakawa25af1502010-09-24 11:29:31 -0700312 return true;
Daisuke Miyakawab5647c52010-09-10 18:04:02 -0700313 } else {
Daisuke Miyakawa25af1502010-09-24 11:29:31 -0700314 Log.w(TAG, "Parent isn't PreferenceActivity, thus there's no way to launch the "
315 + "given Fragment (name: " + fragmentClass + ", requestCode: " + requestCode
316 + ")");
Daisuke Miyakawab5647c52010-09-10 18:04:02 -0700317 return false;
318 }
319 }
320
Amith Yamasanid7993472010-08-18 13:59:28 -0700321}