Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2008 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.Activity;
     20 import android.app.AlarmManager;
     21 import android.app.DatePickerDialog;
     22 import android.app.Dialog;
     23 import android.app.TimePickerDialog;
     24 import android.content.BroadcastReceiver;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.IntentFilter;
     28 import android.content.SharedPreferences;
     29 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
     30 import android.os.Bundle;
     31 import android.os.SystemClock;
     32 import android.preference.CheckBoxPreference;
     33 import android.preference.ListPreference;
     34 import android.preference.Preference;
     35 import android.preference.PreferenceScreen;
     36 import android.provider.Settings;
     37 import android.provider.Settings.SettingNotFoundException;
     38 import android.text.format.DateFormat;
     39 import android.widget.DatePicker;
     40 import android.widget.TimePicker;
     41 
     42 import java.text.SimpleDateFormat;
     43 import java.util.Calendar;
     44 import java.util.Date;
     45 import java.util.TimeZone;
     46 
     47 public class DateTimeSettings extends SettingsPreferenceFragment
     48         implements OnSharedPreferenceChangeListener,
     49                 TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
     50 
     51     private static final String HOURS_12 = "12";
     52     private static final String HOURS_24 = "24";
     53 
     54     // Used for showing the current date format, which looks like "12/31/2010", "2010/12/13", etc.
     55     // The date value is dummy (independent of actual date).
     56     private Calendar mDummyDate;
     57 
     58     private static final String KEY_DATE_FORMAT = "date_format";
     59     private static final String KEY_AUTO_TIME = "auto_time";
     60     private static final String KEY_AUTO_TIME_ZONE = "auto_zone";
     61 
     62     private static final int DIALOG_DATEPICKER = 0;
     63     private static final int DIALOG_TIMEPICKER = 1;
     64 
     65     // have we been launched from the setup wizard?
     66     protected static final String EXTRA_IS_FIRST_RUN = "firstRun";
     67 
     68     private CheckBoxPreference mAutoTimePref;
     69     private Preference mTimePref;
     70     private Preference mTime24Pref;
     71     private CheckBoxPreference mAutoTimeZonePref;
     72     private Preference mTimeZone;
     73     private Preference mDatePref;
     74     private ListPreference mDateFormat;
     75 
     76     @Override
     77     public void onCreate(Bundle icicle) {
     78         super.onCreate(icicle);
     79 
     80         addPreferencesFromResource(R.xml.date_time_prefs);
     81 
     82         initUI();
     83     }
     84 
     85     private void initUI() {
     86         boolean autoTimeEnabled = getAutoState(Settings.Global.AUTO_TIME);
     87         boolean autoTimeZoneEnabled = getAutoState(Settings.Global.AUTO_TIME_ZONE);
     88 
     89         Intent intent = getActivity().getIntent();
     90         boolean isFirstRun = intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
     91 
     92         mDummyDate = Calendar.getInstance();
     93 
     94         mAutoTimePref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME);
     95         mAutoTimePref.setChecked(autoTimeEnabled);
     96         mAutoTimeZonePref = (CheckBoxPreference) findPreference(KEY_AUTO_TIME_ZONE);
     97         // Override auto-timezone if it's a wifi-only device or if we're still in setup wizard.
     98         // TODO: Remove the wifiOnly test when auto-timezone is implemented based on wifi-location.
     99         if (Utils.isWifiOnly(getActivity()) || isFirstRun) {
    100             getPreferenceScreen().removePreference(mAutoTimeZonePref);
    101             autoTimeZoneEnabled = false;
    102         }
    103         mAutoTimeZonePref.setChecked(autoTimeZoneEnabled);
    104 
    105         mTimePref = findPreference("time");
    106         mTime24Pref = findPreference("24 hour");
    107         mTimeZone = findPreference("timezone");
    108         mDatePref = findPreference("date");
    109         mDateFormat = (ListPreference) findPreference(KEY_DATE_FORMAT);
    110         if (isFirstRun) {
    111             getPreferenceScreen().removePreference(mTime24Pref);
    112             getPreferenceScreen().removePreference(mDateFormat);
    113         }
    114 
    115         String [] dateFormats = getResources().getStringArray(R.array.date_format_values);
    116         String [] formattedDates = new String[dateFormats.length];
    117         String currentFormat = getDateFormat();
    118         // Initialize if DATE_FORMAT is not set in the system settings
    119         // This can happen after a factory reset (or data wipe)
    120         if (currentFormat == null) {
    121             currentFormat = "";
    122         }
    123 
    124         // Prevents duplicated values on date format selector.
    125         mDummyDate.set(mDummyDate.get(Calendar.YEAR), mDummyDate.DECEMBER, 31, 13, 0, 0);
    126 
    127         for (int i = 0; i < formattedDates.length; i++) {
    128             String formatted =
    129                     DateFormat.getDateFormatForSetting(getActivity(), dateFormats[i])
    130                     .format(mDummyDate.getTime());
    131 
    132             if (dateFormats[i].length() == 0) {
    133                 formattedDates[i] = getResources().
    134                     getString(R.string.normal_date_format, formatted);
    135             } else {
    136                 formattedDates[i] = formatted;
    137             }
    138         }
    139 
    140         mDateFormat.setEntries(formattedDates);
    141         mDateFormat.setEntryValues(R.array.date_format_values);
    142         mDateFormat.setValue(currentFormat);
    143 
    144         mTimePref.setEnabled(!autoTimeEnabled);
    145         mDatePref.setEnabled(!autoTimeEnabled);
    146         mTimeZone.setEnabled(!autoTimeZoneEnabled);
    147     }
    148 
    149     @Override
    150     public void onResume() {
    151         super.onResume();
    152 
    153         getPreferenceScreen().getSharedPreferences()
    154                 .registerOnSharedPreferenceChangeListener(this);
    155 
    156         ((CheckBoxPreference)mTime24Pref).setChecked(is24Hour());
    157 
    158         // Register for time ticks and other reasons for time change
    159         IntentFilter filter = new IntentFilter();
    160         filter.addAction(Intent.ACTION_TIME_TICK);
    161         filter.addAction(Intent.ACTION_TIME_CHANGED);
    162         filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
    163         getActivity().registerReceiver(mIntentReceiver, filter, null, null);
    164 
    165         updateTimeAndDateDisplay(getActivity());
    166     }
    167 
    168     @Override
    169     public void onPause() {
    170         super.onPause();
    171         getActivity().unregisterReceiver(mIntentReceiver);
    172         getPreferenceScreen().getSharedPreferences()
    173                 .unregisterOnSharedPreferenceChangeListener(this);
    174     }
    175 
    176     public void updateTimeAndDateDisplay(Context context) {
    177         java.text.DateFormat shortDateFormat = DateFormat.getDateFormat(context);
    178         final Calendar now = Calendar.getInstance();
    179         mDummyDate.setTimeZone(now.getTimeZone());
    180         // We use December 31st because it's unambiguous when demonstrating the date format.
    181         // We use 13:00 so we can demonstrate the 12/24 hour options.
    182         mDummyDate.set(now.get(Calendar.YEAR), 11, 31, 13, 0, 0);
    183         Date dummyDate = mDummyDate.getTime();
    184         mTimePref.setSummary(DateFormat.getTimeFormat(getActivity()).format(now.getTime()));
    185         mTimeZone.setSummary(getTimeZoneText(now.getTimeZone()));
    186         mDatePref.setSummary(shortDateFormat.format(now.getTime()));
    187         mDateFormat.setSummary(shortDateFormat.format(dummyDate));
    188         mTime24Pref.setSummary(DateFormat.getTimeFormat(getActivity()).format(dummyDate));
    189     }
    190 
    191     @Override
    192     public void onDateSet(DatePicker view, int year, int month, int day) {
    193         final Activity activity = getActivity();
    194         if (activity != null) {
    195             setDate(activity, year, month, day);
    196             updateTimeAndDateDisplay(activity);
    197         }
    198     }
    199 
    200     @Override
    201     public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
    202         final Activity activity = getActivity();
    203         if (activity != null) {
    204             setTime(activity, hourOfDay, minute);
    205             updateTimeAndDateDisplay(activity);
    206         }
    207 
    208         // We don't need to call timeUpdated() here because the TIME_CHANGED
    209         // broadcast is sent by the AlarmManager as a side effect of setting the
    210         // SystemClock time.
    211     }
    212 
    213     @Override
    214     public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
    215         if (key.equals(KEY_DATE_FORMAT)) {
    216             String format = preferences.getString(key,
    217                     getResources().getString(R.string.default_date_format));
    218             Settings.System.putString(getContentResolver(),
    219                     Settings.System.DATE_FORMAT, format);
    220             updateTimeAndDateDisplay(getActivity());
    221         } else if (key.equals(KEY_AUTO_TIME)) {
    222             boolean autoEnabled = preferences.getBoolean(key, true);
    223             Settings.Global.putInt(getContentResolver(), Settings.Global.AUTO_TIME,
    224                     autoEnabled ? 1 : 0);
    225             mTimePref.setEnabled(!autoEnabled);
    226             mDatePref.setEnabled(!autoEnabled);
    227         } else if (key.equals(KEY_AUTO_TIME_ZONE)) {
    228             boolean autoZoneEnabled = preferences.getBoolean(key, true);
    229             Settings.Global.putInt(
    230                     getContentResolver(), Settings.Global.AUTO_TIME_ZONE, autoZoneEnabled ? 1 : 0);
    231             mTimeZone.setEnabled(!autoZoneEnabled);
    232         }
    233     }
    234 
    235     @Override
    236     public Dialog onCreateDialog(int id) {
    237         final Calendar calendar = Calendar.getInstance();
    238         switch (id) {
    239         case DIALOG_DATEPICKER:
    240             DatePickerDialog d = new DatePickerDialog(
    241                     getActivity(),
    242                     this,
    243                     calendar.get(Calendar.YEAR),
    244                     calendar.get(Calendar.MONTH),
    245                     calendar.get(Calendar.DAY_OF_MONTH));
    246             configureDatePicker(d.getDatePicker());
    247             return d;
    248         case DIALOG_TIMEPICKER:
    249             return new TimePickerDialog(
    250                     getActivity(),
    251                     this,
    252                     calendar.get(Calendar.HOUR_OF_DAY),
    253                     calendar.get(Calendar.MINUTE),
    254                     DateFormat.is24HourFormat(getActivity()));
    255         default:
    256             throw new IllegalArgumentException();
    257         }
    258     }
    259 
    260     static void configureDatePicker(DatePicker datePicker) {
    261         // The system clock can't represent dates outside this range.
    262         Calendar t = Calendar.getInstance();
    263         t.clear();
    264         t.set(1970, Calendar.JANUARY, 1);
    265         datePicker.setMinDate(t.getTimeInMillis());
    266         t.clear();
    267         t.set(2037, Calendar.DECEMBER, 31);
    268         datePicker.setMaxDate(t.getTimeInMillis());
    269     }
    270 
    271     /*
    272     @Override
    273     public void onPrepareDialog(int id, Dialog d) {
    274         switch (id) {
    275         case DIALOG_DATEPICKER: {
    276             DatePickerDialog datePicker = (DatePickerDialog)d;
    277             final Calendar calendar = Calendar.getInstance();
    278             datePicker.updateDate(
    279                     calendar.get(Calendar.YEAR),
    280                     calendar.get(Calendar.MONTH),
    281                     calendar.get(Calendar.DAY_OF_MONTH));
    282             break;
    283         }
    284         case DIALOG_TIMEPICKER: {
    285             TimePickerDialog timePicker = (TimePickerDialog)d;
    286             final Calendar calendar = Calendar.getInstance();
    287             timePicker.updateTime(
    288                     calendar.get(Calendar.HOUR_OF_DAY),
    289                     calendar.get(Calendar.MINUTE));
    290             break;
    291         }
    292         default:
    293             break;
    294         }
    295     }
    296     */
    297     @Override
    298     public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
    299         if (preference == mDatePref) {
    300             showDialog(DIALOG_DATEPICKER);
    301         } else if (preference == mTimePref) {
    302             // The 24-hour mode may have changed, so recreate the dialog
    303             removeDialog(DIALOG_TIMEPICKER);
    304             showDialog(DIALOG_TIMEPICKER);
    305         } else if (preference == mTime24Pref) {
    306             set24Hour(((CheckBoxPreference)mTime24Pref).isChecked());
    307             updateTimeAndDateDisplay(getActivity());
    308             timeUpdated();
    309         }
    310         return super.onPreferenceTreeClick(preferenceScreen, preference);
    311     }
    312 
    313     @Override
    314     public void onActivityResult(int requestCode, int resultCode,
    315             Intent data) {
    316         updateTimeAndDateDisplay(getActivity());
    317     }
    318 
    319     private void timeUpdated() {
    320         Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED);
    321         getActivity().sendBroadcast(timeChanged);
    322     }
    323 
    324     /*  Get & Set values from the system settings  */
    325 
    326     private boolean is24Hour() {
    327         return DateFormat.is24HourFormat(getActivity());
    328     }
    329 
    330     private void set24Hour(boolean is24Hour) {
    331         Settings.System.putString(getContentResolver(),
    332                 Settings.System.TIME_12_24,
    333                 is24Hour? HOURS_24 : HOURS_12);
    334     }
    335 
    336     private String getDateFormat() {
    337         return Settings.System.getString(getContentResolver(),
    338                 Settings.System.DATE_FORMAT);
    339     }
    340 
    341     private boolean getAutoState(String name) {
    342         try {
    343             return Settings.Global.getInt(getContentResolver(), name) > 0;
    344         } catch (SettingNotFoundException snfe) {
    345             return false;
    346         }
    347     }
    348 
    349     /* package */ static void setDate(Context context, int year, int month, int day) {
    350         Calendar c = Calendar.getInstance();
    351 
    352         c.set(Calendar.YEAR, year);
    353         c.set(Calendar.MONTH, month);
    354         c.set(Calendar.DAY_OF_MONTH, day);
    355         long when = c.getTimeInMillis();
    356 
    357         if (when / 1000 < Integer.MAX_VALUE) {
    358             ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when);
    359         }
    360     }
    361 
    362     /* package */ static void setTime(Context context, int hourOfDay, int minute) {
    363         Calendar c = Calendar.getInstance();
    364 
    365         c.set(Calendar.HOUR_OF_DAY, hourOfDay);
    366         c.set(Calendar.MINUTE, minute);
    367         c.set(Calendar.SECOND, 0);
    368         c.set(Calendar.MILLISECOND, 0);
    369         long when = c.getTimeInMillis();
    370 
    371         if (when / 1000 < Integer.MAX_VALUE) {
    372             ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when);
    373         }
    374     }
    375 
    376     private static String getTimeZoneText(TimeZone tz) {
    377         SimpleDateFormat sdf = new SimpleDateFormat("ZZZZ, zzzz");
    378         sdf.setTimeZone(tz);
    379         return sdf.format(new Date());
    380     }
    381 
    382     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
    383         @Override
    384         public void onReceive(Context context, Intent intent) {
    385             final Activity activity = getActivity();
    386             if (activity != null) {
    387                 updateTimeAndDateDisplay(activity);
    388             }
    389         }
    390     };
    391 }
    392