2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings;
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;
41 import java.util.Calendar;
42 import java.util.Date;
43 import java.util.TimeZone;
45 public class DateTimeSettings extends SettingsPreferenceFragment
46 implements OnSharedPreferenceChangeListener,
47 TimePickerDialog.OnTimeSetListener, DatePickerDialog.OnDateSetListener {
49 private static final String HOURS_12 = "12";
50 private static final String HOURS_24 = "24";
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;
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";
60 private static final int DIALOG_DATEPICKER = 0;
61 private static final int DIALOG_TIMEPICKER = 1;
63 // have we been launched from the setup wizard?
64 protected static final String EXTRA_IS_FIRST_RUN = "firstRun";
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;
75 public void onCreate(Bundle icicle) {
76 super.onCreate(icicle);
78 addPreferencesFromResource(R.xml.date_time_prefs);
83 private void initUI() {
84 boolean autoTimeEnabled = getAutoState(Settings.System.AUTO_TIME);
85 boolean autoTimeZoneEnabled = getAutoState(Settings.System.AUTO_TIME_ZONE);
87 Intent intent = getActivity().getIntent();
88 boolean isFirstRun = intent.getBooleanExtra(EXTRA_IS_FIRST_RUN, false);
90 mDummyDate = Calendar.getInstance();
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() || isFirstRun) {
98 getPreferenceScreen().removePreference(mAutoTimeZonePref);
99 autoTimeZoneEnabled = false;
101 mAutoTimeZonePref.setChecked(autoTimeZoneEnabled);
103 mTimePref = findPreference("time");
104 mTime24Pref = findPreference("24 hour");
105 mTimeZone = findPreference("timezone");
106 mDatePref = findPreference("date");
107 mDateFormat = (ListPreference) findPreference(KEY_DATE_FORMAT);
109 getPreferenceScreen().removePreference(mTime24Pref);
110 getPreferenceScreen().removePreference(mDateFormat);
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) {
121 for (int i = 0; i < formattedDates.length; i++) {
123 DateFormat.getDateFormatForSetting(getActivity(), dateFormats[i])
124 .format(mDummyDate.getTime());
126 if (dateFormats[i].length() == 0) {
127 formattedDates[i] = getResources().
128 getString(R.string.normal_date_format, formatted);
130 formattedDates[i] = formatted;
134 mDateFormat.setEntries(formattedDates);
135 mDateFormat.setEntryValues(R.array.date_format_values);
136 mDateFormat.setValue(currentFormat);
138 mTimePref.setEnabled(!autoTimeEnabled);
139 mDatePref.setEnabled(!autoTimeEnabled);
140 mTimeZone.setEnabled(!autoTimeZoneEnabled);
144 public void onResume() {
147 getPreferenceScreen().getSharedPreferences()
148 .registerOnSharedPreferenceChangeListener(this);
150 ((CheckBoxPreference)mTime24Pref).setChecked(is24Hour());
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);
159 updateTimeAndDateDisplay(getActivity());
163 public void onPause() {
165 getActivity().unregisterReceiver(mIntentReceiver);
166 getPreferenceScreen().getSharedPreferences()
167 .unregisterOnSharedPreferenceChangeListener(this);
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));
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);
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);
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
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);
227 public Dialog onCreateDialog(int id) {
231 case DIALOG_DATEPICKER: {
232 final Calendar calendar = Calendar.getInstance();
233 d = new DatePickerDialog(
236 calendar.get(Calendar.YEAR),
237 calendar.get(Calendar.MONTH),
238 calendar.get(Calendar.DAY_OF_MONTH));
241 case DIALOG_TIMEPICKER: {
242 final Calendar calendar = Calendar.getInstance();
243 d = new TimePickerDialog(
246 calendar.get(Calendar.HOUR_OF_DAY),
247 calendar.get(Calendar.MINUTE),
248 DateFormat.is24HourFormat(getActivity()));
261 public void onPrepareDialog(int id, Dialog d) {
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));
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));
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());
298 return super.onPreferenceTreeClick(preferenceScreen, preference);
302 public void onActivityResult(int requestCode, int resultCode,
304 updateTimeAndDateDisplay(getActivity());
307 private void timeUpdated() {
308 Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED);
309 getActivity().sendBroadcast(timeChanged);
312 /* Get & Set values from the system settings */
314 private boolean is24Hour() {
315 return DateFormat.is24HourFormat(getActivity());
318 private void set24Hour(boolean is24Hour) {
319 Settings.System.putString(getContentResolver(),
320 Settings.System.TIME_12_24,
321 is24Hour? HOURS_24 : HOURS_12);
324 private String getDateFormat() {
325 return Settings.System.getString(getContentResolver(),
326 Settings.System.DATE_FORMAT);
329 private boolean getAutoState(String name) {
331 return Settings.System.getInt(getContentResolver(), name) > 0;
332 } catch (SettingNotFoundException snfe) {
337 /* Helper routines to format timezone */
339 /* package */ static void setDate(int year, int month, int day) {
340 Calendar c = Calendar.getInstance();
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();
347 if (when / 1000 < Integer.MAX_VALUE) {
348 SystemClock.setCurrentTimeMillis(when);
352 /* package */ static void setTime(int hourOfDay, int minute) {
353 Calendar c = Calendar.getInstance();
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();
361 if (when / 1000 < Integer.MAX_VALUE) {
362 SystemClock.setCurrentTimeMillis(when);
366 /* package */ static String getTimeZoneText(TimeZone tz) {
367 boolean daylight = tz.inDaylightTime(new Date());
368 StringBuilder sb = new StringBuilder();
370 sb.append(formatOffset(tz.getRawOffset() +
371 (daylight ? tz.getDSTSavings() : 0))).
373 append(tz.getDisplayName(daylight, TimeZone.LONG));
375 return sb.toString();
378 private static char[] formatOffset(int off) {
379 off = off / 1000 / 60;
381 char[] buf = new char[9];
393 int hours = off / 60;
394 int minutes = off % 60;
396 buf[4] = (char) ('0' + hours / 10);
397 buf[5] = (char) ('0' + hours % 10);
401 buf[7] = (char) ('0' + minutes / 10);
402 buf[8] = (char) ('0' + minutes % 10);
407 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
409 public void onReceive(Context context, Intent intent) {
410 final Activity activity = getActivity();
411 if (activity != null) {
412 updateTimeAndDateDisplay(activity);