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