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