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