blob: 54fc0e783d040ed374894c1c07625b6558623e5d [file] [log] [blame]
/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.calendar;
import android.app.Activity;
import android.app.FragmentManager;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Vibrator;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.preference.RingtonePreference;
import android.provider.CalendarContract;
import android.provider.CalendarContract.CalendarCache;
import android.provider.SearchRecentSuggestions;
import android.text.TextUtils;
import android.text.format.Time;
import android.widget.Toast;
import com.android.calendar.alerts.AlertReceiver;
import com.android.timezonepicker.TimeZoneInfo;
import com.android.timezonepicker.TimeZonePickerDialog;
import com.android.timezonepicker.TimeZonePickerDialog.OnTimeZoneSetListener;
import com.android.timezonepicker.TimeZonePickerUtils;
public class GeneralPreferences extends PreferenceFragment implements
OnSharedPreferenceChangeListener, OnPreferenceChangeListener, OnTimeZoneSetListener {
// The name of the shared preferences file. This name must be maintained for historical
// reasons, as it's what PreferenceManager assigned the first time the file was created.
static final String SHARED_PREFS_NAME = "com.android.calendar_preferences";
static final String SHARED_PREFS_NAME_NO_BACKUP = "com.android.calendar_preferences_no_backup";
private static final String FRAG_TAG_TIME_ZONE_PICKER = "TimeZonePicker";
// Preference keys
public static final String KEY_HIDE_DECLINED = "preferences_hide_declined";
public static final String KEY_WEEK_START_DAY = "preferences_week_start_day";
public static final String KEY_SHOW_WEEK_NUM = "preferences_show_week_num";
public static final String KEY_DAYS_PER_WEEK = "preferences_days_per_week";
public static final String KEY_SKIP_SETUP = "preferences_skip_setup";
public static final String KEY_CLEAR_SEARCH_HISTORY = "preferences_clear_search_history";
public static final String KEY_ALERTS_CATEGORY = "preferences_alerts_category";
public static final String KEY_ALERTS = "preferences_alerts";
public static final String KEY_ALERTS_VIBRATE = "preferences_alerts_vibrate";
public static final String KEY_ALERTS_RINGTONE = "preferences_alerts_ringtone";
public static final String KEY_ALERTS_POPUP = "preferences_alerts_popup";
public static final String KEY_SHOW_CONTROLS = "preferences_show_controls";
public static final String KEY_DEFAULT_REMINDER = "preferences_default_reminder";
public static final int NO_REMINDER = -1;
public static final String NO_REMINDER_STRING = "-1";
public static final int REMINDER_DEFAULT_TIME = 10; // in minutes
public static final String KEY_DEFAULT_CELL_HEIGHT = "preferences_default_cell_height";
public static final String KEY_VERSION = "preferences_version";
/** Key to SharePreference for default view (CalendarController.ViewType) */
public static final String KEY_START_VIEW = "preferred_startView";
/**
* Key to SharePreference for default detail view (CalendarController.ViewType)
* Typically used by widget
*/
public static final String KEY_DETAILED_VIEW = "preferred_detailedView";
public static final String KEY_DEFAULT_CALENDAR = "preference_defaultCalendar";
// These must be in sync with the array preferences_week_start_day_values
public static final String WEEK_START_DEFAULT = "-1";
public static final String WEEK_START_SATURDAY = "7";
public static final String WEEK_START_SUNDAY = "1";
public static final String WEEK_START_MONDAY = "2";
// These keys are kept to enable migrating users from previous versions
private static final String KEY_ALERTS_TYPE = "preferences_alerts_type";
private static final String ALERT_TYPE_ALERTS = "0";
private static final String ALERT_TYPE_STATUS_BAR = "1";
private static final String ALERT_TYPE_OFF = "2";
static final String KEY_HOME_TZ_ENABLED = "preferences_home_tz_enabled";
static final String KEY_HOME_TZ = "preferences_home_tz";
// Default preference values
public static final int DEFAULT_START_VIEW = CalendarController.ViewType.WEEK;
public static final int DEFAULT_DETAILED_VIEW = CalendarController.ViewType.DAY;
public static final boolean DEFAULT_SHOW_WEEK_NUM = false;
// This should match the XML file.
public static final String DEFAULT_RINGTONE = "content://settings/system/notification_sound";
CheckBoxPreference mAlert;
CheckBoxPreference mVibrate;
RingtonePreference mRingtone;
CheckBoxPreference mPopup;
CheckBoxPreference mUseHomeTZ;
CheckBoxPreference mHideDeclined;
Preference mHomeTZ;
TimeZonePickerUtils mTzPickerUtils;
ListPreference mWeekStart;
ListPreference mDefaultReminder;
private String mTimeZoneId;
/** Return a properly configured SharedPreferences instance */
public static SharedPreferences getSharedPreferences(Context context) {
return context.getSharedPreferences(SHARED_PREFS_NAME, Context.MODE_PRIVATE);
}
/** Set the default shared preferences in the proper context */
public static void setDefaultValues(Context context) {
PreferenceManager.setDefaultValues(context, SHARED_PREFS_NAME, Context.MODE_PRIVATE,
R.xml.general_preferences, false);
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
final Activity activity = getActivity();
// Make sure to always use the same preferences file regardless of the package name
// we're running under
final PreferenceManager preferenceManager = getPreferenceManager();
final SharedPreferences sharedPreferences = getSharedPreferences(activity);
preferenceManager.setSharedPreferencesName(SHARED_PREFS_NAME);
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.general_preferences);
final PreferenceScreen preferenceScreen = getPreferenceScreen();
mAlert = (CheckBoxPreference) preferenceScreen.findPreference(KEY_ALERTS);
mVibrate = (CheckBoxPreference) preferenceScreen.findPreference(KEY_ALERTS_VIBRATE);
Vibrator vibrator = (Vibrator) activity.getSystemService(Context.VIBRATOR_SERVICE);
if (vibrator == null || !vibrator.hasVibrator()) {
PreferenceCategory mAlertGroup = (PreferenceCategory) preferenceScreen
.findPreference(KEY_ALERTS_CATEGORY);
mAlertGroup.removePreference(mVibrate);
}
mRingtone = (RingtonePreference) preferenceScreen.findPreference(KEY_ALERTS_RINGTONE);
String ringToneUri = Utils.getRingTonePreference(activity);
// Set the ringToneUri to the backup-able shared pref only so that
// the Ringtone dialog will open up with the correct value.
final Editor editor = preferenceScreen.getEditor();
editor.putString(GeneralPreferences.KEY_ALERTS_RINGTONE, ringToneUri).apply();
String ringtoneDisplayString = getRingtoneTitleFromUri(activity, ringToneUri);
mRingtone.setSummary(ringtoneDisplayString == null ? "" : ringtoneDisplayString);
mPopup = (CheckBoxPreference) preferenceScreen.findPreference(KEY_ALERTS_POPUP);
mUseHomeTZ = (CheckBoxPreference) preferenceScreen.findPreference(KEY_HOME_TZ_ENABLED);
mHideDeclined = (CheckBoxPreference) preferenceScreen.findPreference(KEY_HIDE_DECLINED);
mWeekStart = (ListPreference) preferenceScreen.findPreference(KEY_WEEK_START_DAY);
mDefaultReminder = (ListPreference) preferenceScreen.findPreference(KEY_DEFAULT_REMINDER);
mHomeTZ = preferenceScreen.findPreference(KEY_HOME_TZ);
mWeekStart.setSummary(mWeekStart.getEntry());
mDefaultReminder.setSummary(mDefaultReminder.getEntry());
// This triggers an asynchronous call to the provider to refresh the data in shared pref
mTimeZoneId = Utils.getTimeZone(activity, null);
SharedPreferences prefs = CalendarUtils.getSharedPreferences(activity,
Utils.SHARED_PREFS_NAME);
// Utils.getTimeZone will return the currentTimeZone instead of the one
// in the shared_pref if home time zone is disabled. So if home tz is
// off, we will explicitly read it.
if (!prefs.getBoolean(KEY_HOME_TZ_ENABLED, false)) {
mTimeZoneId = prefs.getString(KEY_HOME_TZ, Time.getCurrentTimezone());
}
mHomeTZ.setOnPreferenceClickListener(new OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
showTimezoneDialog();
return true;
}
});
if (mTzPickerUtils == null) {
mTzPickerUtils = new TimeZonePickerUtils(getActivity());
}
CharSequence timezoneName = mTzPickerUtils.getGmtDisplayName(getActivity(), mTimeZoneId,
System.currentTimeMillis(), false);
mHomeTZ.setSummary(timezoneName != null ? timezoneName : mTimeZoneId);
TimeZonePickerDialog tzpd = (TimeZonePickerDialog) activity.getFragmentManager()
.findFragmentByTag(FRAG_TAG_TIME_ZONE_PICKER);
if (tzpd != null) {
tzpd.setOnTimeZoneSetListener(this);
}
migrateOldPreferences(sharedPreferences);
updateChildPreferences();
}
private void showTimezoneDialog() {
final Activity activity = getActivity();
if (activity == null) {
return;
}
Bundle b = new Bundle();
b.putLong(TimeZonePickerDialog.BUNDLE_START_TIME_MILLIS, System.currentTimeMillis());
b.putString(TimeZonePickerDialog.BUNDLE_TIME_ZONE, Utils.getTimeZone(activity, null));
FragmentManager fm = getActivity().getFragmentManager();
TimeZonePickerDialog tzpd = (TimeZonePickerDialog) fm
.findFragmentByTag(FRAG_TAG_TIME_ZONE_PICKER);
if (tzpd != null) {
tzpd.dismiss();
}
tzpd = new TimeZonePickerDialog();
tzpd.setArguments(b);
tzpd.setOnTimeZoneSetListener(this);
tzpd.show(fm, FRAG_TAG_TIME_ZONE_PICKER);
}
@Override
public void onStart() {
super.onStart();
getPreferenceScreen().getSharedPreferences()
.registerOnSharedPreferenceChangeListener(this);
setPreferenceListeners(this);
}
/**
* Sets up all the preference change listeners to use the specified
* listener.
*/
private void setPreferenceListeners(OnPreferenceChangeListener listener) {
mUseHomeTZ.setOnPreferenceChangeListener(listener);
mHomeTZ.setOnPreferenceChangeListener(listener);
mWeekStart.setOnPreferenceChangeListener(listener);
mDefaultReminder.setOnPreferenceChangeListener(listener);
mRingtone.setOnPreferenceChangeListener(listener);
mHideDeclined.setOnPreferenceChangeListener(listener);
mVibrate.setOnPreferenceChangeListener(listener);
}
@Override
public void onStop() {
getPreferenceScreen().getSharedPreferences()
.unregisterOnSharedPreferenceChangeListener(this);
setPreferenceListeners(null);
super.onStop();
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
Activity a = getActivity();
if (key.equals(KEY_ALERTS)) {
updateChildPreferences();
if (a != null) {
Intent intent = new Intent();
intent.setClass(a, AlertReceiver.class);
if (mAlert.isChecked()) {
intent.setAction(AlertReceiver.ACTION_DISMISS_OLD_REMINDERS);
} else {
intent.setAction(AlertReceiver.EVENT_REMINDER_APP_ACTION);
}
a.sendBroadcast(intent);
}
}
if (a != null) {
BackupManager.dataChanged(a.getPackageName());
}
}
/**
* Handles time zone preference changes
*/
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String tz;
final Activity activity = getActivity();
if (preference == mUseHomeTZ) {
if ((Boolean)newValue) {
tz = mTimeZoneId;
} else {
tz = CalendarCache.TIMEZONE_TYPE_AUTO;
}
Utils.setTimeZone(activity, tz);
return true;
} else if (preference == mHideDeclined) {
mHideDeclined.setChecked((Boolean) newValue);
Intent intent = new Intent(Utils.getWidgetScheduledUpdateAction(activity));
intent.setDataAndType(CalendarContract.CONTENT_URI, Utils.APPWIDGET_DATA_TYPE);
activity.sendBroadcast(intent);
return true;
} else if (preference == mWeekStart) {
mWeekStart.setValue((String) newValue);
mWeekStart.setSummary(mWeekStart.getEntry());
} else if (preference == mDefaultReminder) {
mDefaultReminder.setValue((String) newValue);
mDefaultReminder.setSummary(mDefaultReminder.getEntry());
} else if (preference == mRingtone) {
if (newValue instanceof String) {
Utils.setRingTonePreference(activity, (String) newValue);
String ringtone = getRingtoneTitleFromUri(activity, (String) newValue);
mRingtone.setSummary(ringtone == null ? "" : ringtone);
}
return true;
} else if (preference == mVibrate) {
mVibrate.setChecked((Boolean) newValue);
return true;
} else {
return true;
}
return false;
}
public String getRingtoneTitleFromUri(Context context, String uri) {
if (TextUtils.isEmpty(uri)) {
return null;
}
Ringtone ring = RingtoneManager.getRingtone(getActivity(), Uri.parse(uri));
if (ring != null) {
return ring.getTitle(context);
}
return null;
}
/**
* If necessary, upgrades previous versions of preferences to the current
* set of keys and values.
* @param prefs the preferences to upgrade
*/
private void migrateOldPreferences(SharedPreferences prefs) {
// If needed, migrate vibration setting from a previous version
mVibrate.setChecked(Utils.getDefaultVibrate(getActivity(), prefs));
// If needed, migrate the old alerts type settin
if (!prefs.contains(KEY_ALERTS) && prefs.contains(KEY_ALERTS_TYPE)) {
String type = prefs.getString(KEY_ALERTS_TYPE, ALERT_TYPE_STATUS_BAR);
if (type.equals(ALERT_TYPE_OFF)) {
mAlert.setChecked(false);
mPopup.setChecked(false);
mPopup.setEnabled(false);
} else if (type.equals(ALERT_TYPE_STATUS_BAR)) {
mAlert.setChecked(true);
mPopup.setChecked(false);
mPopup.setEnabled(true);
} else if (type.equals(ALERT_TYPE_ALERTS)) {
mAlert.setChecked(true);
mPopup.setChecked(true);
mPopup.setEnabled(true);
}
// clear out the old setting
prefs.edit().remove(KEY_ALERTS_TYPE).commit();
}
}
/**
* Keeps the dependent settings in sync with the parent preference, so for
* example, when notifications are turned off, we disable the preferences
* for configuring the exact notification behavior.
*/
private void updateChildPreferences() {
if (mAlert.isChecked()) {
mVibrate.setEnabled(true);
mRingtone.setEnabled(true);
mPopup.setEnabled(true);
} else {
mVibrate.setEnabled(false);
mRingtone.setEnabled(false);
mPopup.setEnabled(false);
}
}
@Override
public boolean onPreferenceTreeClick(
PreferenceScreen preferenceScreen, Preference preference) {
final String key = preference.getKey();
if (KEY_CLEAR_SEARCH_HISTORY.equals(key)) {
SearchRecentSuggestions suggestions = new SearchRecentSuggestions(getActivity(),
Utils.getSearchAuthority(getActivity()),
CalendarRecentSuggestionsProvider.MODE);
suggestions.clearHistory();
Toast.makeText(getActivity(), R.string.search_history_cleared,
Toast.LENGTH_SHORT).show();
return true;
} else {
return super.onPreferenceTreeClick(preferenceScreen, preference);
}
}
@Override
public void onTimeZoneSet(TimeZoneInfo tzi) {
if (mTzPickerUtils == null) {
mTzPickerUtils = new TimeZonePickerUtils(getActivity());
}
final CharSequence timezoneName = mTzPickerUtils.getGmtDisplayName(
getActivity(), tzi.mTzId, System.currentTimeMillis(), false);
mHomeTZ.setSummary(timezoneName);
Utils.setTimeZone(getActivity(), tzi.mTzId);
}
}