GeneralPreferences.java revision 974343a44435bedc104d89fa98fdeb1ccf362501
1/* 2 * Copyright (C) 2007 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.calendar; 18 19import android.app.Activity; 20import android.app.FragmentManager; 21import android.app.backup.BackupManager; 22import android.content.Context; 23import android.content.Intent; 24import android.content.SharedPreferences; 25import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 26import android.media.Ringtone; 27import android.media.RingtoneManager; 28import android.net.Uri; 29import android.os.Bundle; 30import android.os.Vibrator; 31import android.preference.CheckBoxPreference; 32import android.preference.ListPreference; 33import android.preference.Preference; 34import android.preference.Preference.OnPreferenceChangeListener; 35import android.preference.Preference.OnPreferenceClickListener; 36import android.preference.PreferenceCategory; 37import android.preference.PreferenceFragment; 38import android.preference.PreferenceManager; 39import android.preference.PreferenceScreen; 40import android.preference.RingtonePreference; 41import android.provider.CalendarContract; 42import android.provider.CalendarContract.CalendarCache; 43import android.provider.SearchRecentSuggestions; 44import android.text.TextUtils; 45import android.widget.Toast; 46 47import com.android.calendar.alerts.AlertReceiver; 48import com.android.timezonepicker.TimeZoneInfo; 49import com.android.timezonepicker.TimeZonePickerDialog; 50import com.android.timezonepicker.TimeZonePickerDialog.OnTimeZoneSetListener; 51import com.android.timezonepicker.TimeZonePickerUtils; 52 53public class GeneralPreferences extends PreferenceFragment implements 54 OnSharedPreferenceChangeListener, OnPreferenceChangeListener, OnTimeZoneSetListener { 55 // The name of the shared preferences file. This name must be maintained for historical 56 // reasons, as it's what PreferenceManager assigned the first time the file was created. 57 static final String SHARED_PREFS_NAME = "com.android.calendar_preferences"; 58 59 private static final String FRAG_TAG_TIME_ZONE_PICKER = "TimeZonePicker"; 60 61 // Preference keys 62 public static final String KEY_HIDE_DECLINED = "preferences_hide_declined"; 63 public static final String KEY_WEEK_START_DAY = "preferences_week_start_day"; 64 public static final String KEY_SHOW_WEEK_NUM = "preferences_show_week_num"; 65 public static final String KEY_DAYS_PER_WEEK = "preferences_days_per_week"; 66 public static final String KEY_SKIP_SETUP = "preferences_skip_setup"; 67 68 public static final String KEY_CLEAR_SEARCH_HISTORY = "preferences_clear_search_history"; 69 70 public static final String KEY_ALERTS_CATEGORY = "preferences_alerts_category"; 71 public static final String KEY_ALERTS = "preferences_alerts"; 72 public static final String KEY_ALERTS_VIBRATE = "preferences_alerts_vibrate"; 73 public static final String KEY_ALERTS_RINGTONE = "preferences_alerts_ringtone"; 74 public static final String KEY_ALERTS_POPUP = "preferences_alerts_popup"; 75 76 public static final String KEY_SHOW_CONTROLS = "preferences_show_controls"; 77 78 public static final String KEY_DEFAULT_REMINDER = "preferences_default_reminder"; 79 public static final int NO_REMINDER = -1; 80 public static final String NO_REMINDER_STRING = "-1"; 81 public static final int REMINDER_DEFAULT_TIME = 10; // in minutes 82 83 public static final String KEY_DEFAULT_CELL_HEIGHT = "preferences_default_cell_height"; 84 public static final String KEY_VERSION = "preferences_version"; 85 86 /** Key to SharePreference for default view (CalendarController.ViewType) */ 87 public static final String KEY_START_VIEW = "preferred_startView"; 88 /** 89 * Key to SharePreference for default detail view (CalendarController.ViewType) 90 * Typically used by widget 91 */ 92 public static final String KEY_DETAILED_VIEW = "preferred_detailedView"; 93 public static final String KEY_DEFAULT_CALENDAR = "preference_defaultCalendar"; 94 95 // These must be in sync with the array preferences_week_start_day_values 96 public static final String WEEK_START_DEFAULT = "-1"; 97 public static final String WEEK_START_SATURDAY = "7"; 98 public static final String WEEK_START_SUNDAY = "1"; 99 public static final String WEEK_START_MONDAY = "2"; 100 101 // These keys are kept to enable migrating users from previous versions 102 private static final String KEY_ALERTS_TYPE = "preferences_alerts_type"; 103 private static final String ALERT_TYPE_ALERTS = "0"; 104 private static final String ALERT_TYPE_STATUS_BAR = "1"; 105 private static final String ALERT_TYPE_OFF = "2"; 106 static final String KEY_HOME_TZ_ENABLED = "preferences_home_tz_enabled"; 107 static final String KEY_HOME_TZ = "preferences_home_tz"; 108 109 // Default preference values 110 public static final int DEFAULT_START_VIEW = CalendarController.ViewType.WEEK; 111 public static final int DEFAULT_DETAILED_VIEW = CalendarController.ViewType.DAY; 112 public static final boolean DEFAULT_SHOW_WEEK_NUM = false; 113 114 CheckBoxPreference mAlert; 115 CheckBoxPreference mVibrate; 116 RingtonePreference mRingtone; 117 CheckBoxPreference mPopup; 118 CheckBoxPreference mUseHomeTZ; 119 CheckBoxPreference mHideDeclined; 120 Preference mHomeTZ; 121 ListPreference mWeekStart; 122 ListPreference mDefaultReminder; 123 124 /** Return a properly configured SharedPreferences instance */ 125 public static SharedPreferences getSharedPreferences(Context context) { 126 return context.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE); 127 } 128 129 /** Set the default shared preferences in the proper context */ 130 public static void setDefaultValues(Context context) { 131 PreferenceManager.setDefaultValues(context, SHARED_PREFS_NAME, Context.MODE_PRIVATE, 132 R.xml.general_preferences, false); 133 } 134 135 @Override 136 public void onCreate(Bundle icicle) { 137 super.onCreate(icicle); 138 139 final Activity activity = getActivity(); 140 141 // Make sure to always use the same preferences file regardless of the package name 142 // we're running under 143 final PreferenceManager preferenceManager = getPreferenceManager(); 144 final SharedPreferences sharedPreferences = getSharedPreferences(activity); 145 preferenceManager.setSharedPreferencesName(SHARED_PREFS_NAME); 146 147 // Load the preferences from an XML resource 148 addPreferencesFromResource(R.xml.general_preferences); 149 150 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 151 mAlert = (CheckBoxPreference) preferenceScreen.findPreference(KEY_ALERTS); 152 mVibrate = (CheckBoxPreference) preferenceScreen.findPreference(KEY_ALERTS_VIBRATE); 153 Vibrator vibrator = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE); 154 if (vibrator == null || !vibrator.hasVibrator()) { 155 PreferenceCategory mAlertGroup = (PreferenceCategory) preferenceScreen 156 .findPreference(KEY_ALERTS_CATEGORY); 157 mAlertGroup.removePreference(mVibrate); 158 } 159 160 mRingtone = (RingtonePreference) preferenceScreen.findPreference(KEY_ALERTS_RINGTONE); 161 String ringToneUri = Utils.getSharedPreference(activity, KEY_ALERTS_RINGTONE, ""); 162 if (!TextUtils.isEmpty(ringToneUri)) { 163 String ringtone = getRingtoneTitleFromUri(getActivity(), ringToneUri); 164 mRingtone.setSummary(ringtone == null ? "" : ringtone); 165 } 166 167 mPopup = (CheckBoxPreference) preferenceScreen.findPreference(KEY_ALERTS_POPUP); 168 mUseHomeTZ = (CheckBoxPreference) preferenceScreen.findPreference(KEY_HOME_TZ_ENABLED); 169 mHideDeclined = (CheckBoxPreference) preferenceScreen.findPreference(KEY_HIDE_DECLINED); 170 mWeekStart = (ListPreference) preferenceScreen.findPreference(KEY_WEEK_START_DAY); 171 mDefaultReminder = (ListPreference) preferenceScreen.findPreference(KEY_DEFAULT_REMINDER); 172 mHomeTZ = preferenceScreen.findPreference(KEY_HOME_TZ); 173 mWeekStart.setSummary(mWeekStart.getEntry()); 174 mDefaultReminder.setSummary(mDefaultReminder.getEntry()); 175 176 String timezone = Utils.getTimeZone(activity, null); 177 mHomeTZ.setOnPreferenceClickListener(new OnPreferenceClickListener() { 178 @Override 179 public boolean onPreferenceClick(Preference preference) { 180 showTimezoneDialog(); 181 return true; 182 } 183 }); 184 185 String timezoneName = TimeZonePickerUtils.getGmtDisplayName(timezone, 186 System.currentTimeMillis()); 187 mHomeTZ.setSummary(timezoneName != null ? timezoneName : timezone); 188 189 TimeZonePickerDialog tzpd = (TimeZonePickerDialog) activity.getFragmentManager() 190 .findFragmentByTag(FRAG_TAG_TIME_ZONE_PICKER); 191 if (tzpd != null) { 192 tzpd.setOnTimeZoneSetListener(this); 193 } 194 195 migrateOldPreferences(sharedPreferences); 196 197 updateChildPreferences(); 198 } 199 200 private void showTimezoneDialog() { 201 final Activity activity = getActivity(); 202 if (activity == null) { 203 return; 204 } 205 206 Bundle b = new Bundle(); 207 b.putLong(TimeZonePickerDialog.BUNDLE_START_TIME_MILLIS, System.currentTimeMillis()); 208 b.putString(TimeZonePickerDialog.BUNDLE_TIME_ZONE, Utils.getTimeZone(activity, null)); 209 210 FragmentManager fm = getActivity().getFragmentManager(); 211 TimeZonePickerDialog tzpd = (TimeZonePickerDialog) fm 212 .findFragmentByTag(FRAG_TAG_TIME_ZONE_PICKER); 213 if (tzpd != null) { 214 tzpd.dismiss(); 215 } 216 tzpd = new TimeZonePickerDialog(); 217 tzpd.setArguments(b); 218 tzpd.setOnTimeZoneSetListener(this); 219 tzpd.show(fm, FRAG_TAG_TIME_ZONE_PICKER); 220 } 221 222 @Override 223 public void onStart() { 224 super.onStart(); 225 getPreferenceScreen().getSharedPreferences() 226 .registerOnSharedPreferenceChangeListener(this); 227 setPreferenceListeners(this); 228 } 229 230 /** 231 * Sets up all the preference change listeners to use the specified 232 * listener. 233 */ 234 private void setPreferenceListeners(OnPreferenceChangeListener listener) { 235 mUseHomeTZ.setOnPreferenceChangeListener(listener); 236 mHomeTZ.setOnPreferenceChangeListener(listener); 237 mWeekStart.setOnPreferenceChangeListener(listener); 238 mDefaultReminder.setOnPreferenceChangeListener(listener); 239 mRingtone.setOnPreferenceChangeListener(listener); 240 mHideDeclined.setOnPreferenceChangeListener(listener); 241 mVibrate.setOnPreferenceChangeListener(listener); 242 } 243 244 @Override 245 public void onStop() { 246 getPreferenceScreen().getSharedPreferences() 247 .unregisterOnSharedPreferenceChangeListener(this); 248 setPreferenceListeners(null); 249 super.onStop(); 250 } 251 252 @Override 253 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 254 Activity a = getActivity(); 255 if (key.equals(KEY_ALERTS)) { 256 updateChildPreferences(); 257 if (a != null) { 258 Intent intent = new Intent(); 259 intent.setClass(a, AlertReceiver.class); 260 if (mAlert.isChecked()) { 261 intent.setAction(AlertReceiver.ACTION_DISMISS_OLD_REMINDERS); 262 } else { 263 intent.setAction(AlertReceiver.EVENT_REMINDER_APP_ACTION); 264 } 265 a.sendBroadcast(intent); 266 } 267 } 268 if (a != null) { 269 BackupManager.dataChanged(a.getPackageName()); 270 } 271 } 272 273 /** 274 * Handles time zone preference changes 275 */ 276 @Override 277 public boolean onPreferenceChange(Preference preference, Object newValue) { 278 String tz; 279 if (preference == mUseHomeTZ) { 280 if ((Boolean)newValue) { 281 tz = mHomeTZ.getSummary().toString(); 282 } else { 283 tz = CalendarCache.TIMEZONE_TYPE_AUTO; 284 } 285 Utils.setTimeZone(getActivity(), tz); 286 return true; 287 } else if (preference == mHideDeclined) { 288 mHideDeclined.setChecked((Boolean) newValue); 289 Activity act = getActivity(); 290 Intent intent = new Intent(Utils.getWidgetScheduledUpdateAction(act)); 291 intent.setDataAndType(CalendarContract.CONTENT_URI, Utils.APPWIDGET_DATA_TYPE); 292 act.sendBroadcast(intent); 293 return true; 294 } else if (preference == mWeekStart) { 295 mWeekStart.setValue((String) newValue); 296 mWeekStart.setSummary(mWeekStart.getEntry()); 297 } else if (preference == mDefaultReminder) { 298 mDefaultReminder.setValue((String) newValue); 299 mDefaultReminder.setSummary(mDefaultReminder.getEntry()); 300 } else if (preference == mRingtone) { 301 if (newValue instanceof String) { 302 String ringtone = getRingtoneTitleFromUri(getActivity(), (String) newValue); 303 mRingtone.setSummary(ringtone == null ? "" : ringtone); 304 } 305 return true; 306 } else if (preference == mVibrate) { 307 mVibrate.setChecked((Boolean) newValue); 308 return true; 309 } else { 310 return true; 311 } 312 return false; 313 } 314 315 public String getRingtoneTitleFromUri(Context context, String uri) { 316 if (TextUtils.isEmpty(uri)) { 317 return null; 318 } 319 320 Ringtone ring = RingtoneManager.getRingtone(getActivity(), Uri.parse(uri)); 321 if (ring != null) { 322 return ring.getTitle(context); 323 } 324 return null; 325 } 326 327 /** 328 * If necessary, upgrades previous versions of preferences to the current 329 * set of keys and values. 330 * @param prefs the preferences to upgrade 331 */ 332 private void migrateOldPreferences(SharedPreferences prefs) { 333 // If needed, migrate vibration setting from a previous version 334 335 mVibrate.setChecked(Utils.getDefaultVibrate(getActivity(), prefs)); 336 337 // If needed, migrate the old alerts type settin 338 if (!prefs.contains(KEY_ALERTS) && prefs.contains(KEY_ALERTS_TYPE)) { 339 String type = prefs.getString(KEY_ALERTS_TYPE, ALERT_TYPE_STATUS_BAR); 340 if (type.equals(ALERT_TYPE_OFF)) { 341 mAlert.setChecked(false); 342 mPopup.setChecked(false); 343 mPopup.setEnabled(false); 344 } else if (type.equals(ALERT_TYPE_STATUS_BAR)) { 345 mAlert.setChecked(true); 346 mPopup.setChecked(false); 347 mPopup.setEnabled(true); 348 } else if (type.equals(ALERT_TYPE_ALERTS)) { 349 mAlert.setChecked(true); 350 mPopup.setChecked(true); 351 mPopup.setEnabled(true); 352 } 353 // clear out the old setting 354 prefs.edit().remove(KEY_ALERTS_TYPE).commit(); 355 } 356 } 357 358 /** 359 * Keeps the dependent settings in sync with the parent preference, so for 360 * example, when notifications are turned off, we disable the preferences 361 * for configuring the exact notification behavior. 362 */ 363 private void updateChildPreferences() { 364 if (mAlert.isChecked()) { 365 mVibrate.setEnabled(true); 366 mRingtone.setEnabled(true); 367 mPopup.setEnabled(true); 368 } else { 369 mVibrate.setEnabled(false); 370 mRingtone.setEnabled(false); 371 mPopup.setEnabled(false); 372 } 373 } 374 375 376 @Override 377 public boolean onPreferenceTreeClick( 378 PreferenceScreen preferenceScreen, Preference preference) { 379 final String key = preference.getKey(); 380 if (KEY_CLEAR_SEARCH_HISTORY.equals(key)) { 381 SearchRecentSuggestions suggestions = new SearchRecentSuggestions(getActivity(), 382 Utils.getSearchAuthority(getActivity()), 383 CalendarRecentSuggestionsProvider.MODE); 384 suggestions.clearHistory(); 385 Toast.makeText(getActivity(), R.string.search_history_cleared, 386 Toast.LENGTH_SHORT).show(); 387 return true; 388 } else { 389 return super.onPreferenceTreeClick(preferenceScreen, preference); 390 } 391 } 392 393 @Override 394 public void onTimeZoneSet(TimeZoneInfo tzi) { 395 final String timezoneName = TimeZonePickerUtils.getGmtDisplayName(tzi.mTzId, 396 System.currentTimeMillis()); 397 mHomeTZ.setSummary(timezoneName); 398 Utils.setTimeZone(getActivity(), tzi.mTzId); 399 } 400} 401