165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane/* 265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Copyright (C) 2014 The Android Open Source Project 365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Licensed under the Apache License, Version 2.0 (the "License"); 565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * you may not use this file except in compliance with the License. 665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * You may obtain a copy of the License at 765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * http://www.apache.org/licenses/LICENSE-2.0 965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * 1065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Unless required by applicable law or agreed to in writing, software 1165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * distributed under the License is distributed on an "AS IS" BASIS, 1265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * See the License for the specific language governing permissions and 1465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * limitations under the License. 1565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 1665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepackage com.android.tv.settings.system; 1865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 1965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.ActionBehavior; 2065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.ActionKey; 2165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.BaseSettingsActivity; 2265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.R; 2365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.util.SettingsHelper; 2465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.old.Action; 2565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.old.ActionAdapter; 2665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.old.ActionFragment; 2765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.dialog.old.ContentFragment; 2865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.widget.picker.DatePicker; 2965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.widget.picker.TimePicker; 3065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.widget.picker.Picker; 3165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport com.android.tv.settings.widget.picker.PickerConstant; 3265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 3365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport org.xmlpull.v1.XmlPullParserException; 3465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 3565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.app.AlarmManager; 3665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.BroadcastReceiver; 3765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Context; 3865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.Intent; 3965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.IntentFilter; 4065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.content.res.XmlResourceParser; 4165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.os.Bundle; 4265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.provider.Settings; 4365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.provider.Settings.SettingNotFoundException; 4465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.text.format.DateFormat; 4565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport android.util.Log; 4665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 4765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.ArrayList; 4865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Calendar; 4965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Collections; 5065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.Date; 5165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.List; 5265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Laneimport java.util.TimeZone; 5365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lanepublic class DateTimeActivity extends BaseSettingsActivity implements ActionAdapter.Listener { 5565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String TAG = "DateTimeActivity"; 5765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final boolean DEBUG = false; 5865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 5965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String HOURS_12 = "12"; 6065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String HOURS_24 = "24"; 6165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final int HOURS_IN_HALF_DAY = 12; 6365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static final String XMLTAG_TIMEZONE = "timezone"; 6565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private Calendar mDummyDate; 6765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mIsResumed; 6865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 6965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private IntentFilter mIntentFilter; 7065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private String mNowDate; 7265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private String mNowTime; 7365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ArrayList<Action> mTimeZoneActions; 7565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private SettingsHelper mHelper; 7765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 7865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 7965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Flag indicating whether this UpdateView call is from onCreate. 8065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 8165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mOnCreateUpdateView = false; 8265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 8365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 8465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Flag indicating whether this UpdateView call is from onResume. 8565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 8665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean mOnResumeUpdateView = false; 8765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 8865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 8965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 9065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onReceive(Context context, Intent intent) { 9165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mIsResumed) { 9265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch ((ActionType) mState) { 9365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE_TIME_OVERVIEW: 9465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE: 9565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME: 9665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane updateTimeAndDateDisplay(); 9765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 9965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 10065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }; 10165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 10265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 10365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onCreate(Bundle savedInstanceState) { 10465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDummyDate = Calendar.getInstance(); 10565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIntentFilter = new IntentFilter(); 10665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIntentFilter.addAction(Intent.ACTION_TIME_TICK); 10765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIntentFilter.addAction(Intent.ACTION_TIME_CHANGED); 10865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIntentFilter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 10965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIntentFilter.addAction(Intent.ACTION_DATE_CHANGED); 11065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane registerReceiver(mIntentReceiver, mIntentFilter); 11165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mHelper = new SettingsHelper(getApplicationContext()); 11365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setSampleDate(); 11565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane updateTimeAndDateStrings(); 11765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnCreateUpdateView = true; 11865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 11965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super.onCreate(savedInstanceState); 12065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 12165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 12265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void setSampleDate() { 12365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Calendar now = Calendar.getInstance(); 12465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDummyDate.setTimeZone(now.getTimeZone()); 12565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // We use December 31st because it's unambiguous when demonstrating the date format. 12665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // We use 15:14 so we can demonstrate the 12/24 hour options. 12765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mDummyDate.set(now.get(Calendar.YEAR), 11, 31, 15, 14, 0); 12865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 12965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 13065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean getAutoState(String name) { 13165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane try { 13265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return Settings.Global.getInt(getContentResolver(), name) > 0; 13365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } catch (SettingNotFoundException snfe) { 13465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return false; 13565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 13765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 13865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane static void setDate(Context context, int year, int month, int day) { 13965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Calendar c = Calendar.getInstance(); 14065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 14165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane c.set(Calendar.YEAR, year); 14265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane c.set(Calendar.MONTH, month); 14365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane c.set(Calendar.DAY_OF_MONTH, day); 14465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane long when = c.getTimeInMillis(); 14565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 14665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (when / 1000 < Integer.MAX_VALUE) { 14765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when); 14865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 14965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 15065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 15165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane static void setTime(Context context, int hourOfDay, int minute) { 15265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Calendar c = Calendar.getInstance(); 15365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 15465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane c.set(Calendar.HOUR_OF_DAY, hourOfDay); 15565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane c.set(Calendar.MINUTE, minute); 15665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane c.set(Calendar.SECOND, 0); 15765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane c.set(Calendar.MILLISECOND, 0); 15865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane long when = c.getTimeInMillis(); 15965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (when / 1000 < Integer.MAX_VALUE) { 16165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when); 16265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private boolean isTimeFormat24h() { 1662100f1f07a85cf21a0497517cb136869ea831bf2William Bourke return DateFormat.is24HourFormat(this); 16765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 16865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 16965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void setTime24Hour(boolean is24Hour) { 17065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Settings.System.putString(getContentResolver(), 17165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Settings.System.TIME_12_24, 17265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane is24Hour ? HOURS_24 : HOURS_12); 17365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void setAutoDateTime(boolean on) { 17665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Settings.Global.putInt(getContentResolver(), Settings.Global.AUTO_TIME, on ? 1 : 0); 17765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 17865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 17965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 18065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void onResume() { 18165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super.onResume(); 18265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIsResumed = true; 18365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane registerReceiver(mIntentReceiver, mIntentFilter); 18465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 18565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnResumeUpdateView = true; 18665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 18765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane updateTimeAndDateDisplay(); 18865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 18965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 19065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 19165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void onPause() { 19265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane super.onPause(); 19365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIsResumed = false; 19465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane unregisterReceiver(mIntentReceiver); 19565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 19665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 19765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Updates the member strings to reflect the current date and time. 19865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void updateTimeAndDateStrings() { 19965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Calendar now = Calendar.getInstance(); 20065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane java.text.DateFormat dateFormat = DateFormat.getDateFormat(this); 20165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mNowDate = dateFormat.format(now.getTime()); 20265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane java.text.DateFormat timeFormat = DateFormat.getTimeFormat(this); 20365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mNowTime = timeFormat.format(now.getTime()); 20465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 20565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 20665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 20765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onActionClicked(Action action) { 20865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /* 20965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * For list preferences 21065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 21165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final String key = action.getKey(); 21265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch ((ActionType) mState) { 21365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME_SET_TIME_ZONE: 21465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setTimeZone(key); 21565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane updateTimeAndDateStrings(); 21665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane goBack(); 21765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 21865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 21965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /* 22065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * For other preferences 22165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 22265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionKey<ActionType, ActionBehavior> actionKey = new ActionKey<ActionType, ActionBehavior>( 22365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionType.class, ActionBehavior.class, key); 22465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final ActionType type = actionKey.getType(); 22565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final ActionBehavior behavior = actionKey.getBehavior(); 22665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (type == null || behavior == null) { 22765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Possible race condition manifested by monkey test. 22865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.e(TAG, "type or behavior is null - exiting b/17404946"); 22965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 23065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 23165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (type) { 23265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE: 23365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME: 23465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME_CHOOSE_FORMAT: 23565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE_SET_DATE: 23665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME_SET_TIME: 23765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME_SET_TIME_ZONE: 23865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case AUTO_DATE_TIME: 23965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (behavior == ActionBehavior.INIT) { 24065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setState(type, true); 24165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 24365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 24465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch (behavior) { 24565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case ON: 24665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mState == ActionType.TIME_CHOOSE_FORMAT) { 24765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setTime24Hour(true); 24865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane updateTimeAndDateStrings(); 24965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else if (mState == ActionType.AUTO_DATE_TIME) { 25065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAutoDateTime(true); 25165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 25265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane goBack(); 25365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 25465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case OFF: 25565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mState == ActionType.TIME_CHOOSE_FORMAT) { 25665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setTime24Hour(false); 25765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane updateTimeAndDateStrings(); 25865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else if (mState == ActionType.AUTO_DATE_TIME) { 25965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAutoDateTime(false); 26065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane goBack(); 26265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 26365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 26565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 26665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 26765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected Object getInitialState() { 26865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return ActionType.DATE_TIME_OVERVIEW; 26965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 27065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 27165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Updates the Date and Time entries in the current view, without resetting the 27265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Action fragment, so we don't trigger an animation. 27365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void updateTimeAndDateDisplay() { 27465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane updateTimeAndDateStrings(); 27565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 27665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mActionFragment instanceof ActionFragment) { 27765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionAdapter adapter = (ActionAdapter) ((ActionFragment)mActionFragment).getAdapter(); 27865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 27965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (adapter != null) { 28065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.clear(); 28165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 28265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch ((ActionType) mState) { 28365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE_TIME_OVERVIEW: 28465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.AUTO_DATE_TIME.toAction(mResources, 28565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mHelper.getStatusStringFromBoolean(getAutoState( 28665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Settings.Global.AUTO_TIME)))); 28765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.DATE.toAction(mResources, mNowDate)); 28865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.TIME.toAction(mResources, mNowTime)); 28965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 29065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE: 29165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.DATE_SET_DATE.toAction(mResources, mNowDate)); 29265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 29365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME: 29465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.TIME_SET_TIME.toAction(mResources, mNowTime)); 29565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.TIME_SET_TIME_ZONE.toAction(mResources, 29665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getCurrentTimeZoneName())); 29765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.TIME_CHOOSE_FORMAT.toAction( 29865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mResources, getTimeFormatDescription())); 29965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 30065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 30165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane adapter.setActions(mActions); 30265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 30365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 30465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 30565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 30665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // If we don't have an ActionFragment or adapter, fall back to the regular updateView 30765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane updateView(); 30865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 30965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 31065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 31165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void refreshActionList() { 31265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.clear(); 31365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane boolean autoTime = getAutoState(Settings.Global.AUTO_TIME); 31465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch ((ActionType)mState) { 31565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE_TIME_OVERVIEW: 31665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.AUTO_DATE_TIME.toAction(mResources, 31765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mHelper.getStatusStringFromBoolean(autoTime))); 31865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.DATE.toAction(mResources, mNowDate)); 31965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.TIME.toAction(mResources, mNowTime)); 32065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 32165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE: 32265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.DATE_SET_DATE.toAction(mResources, mNowDate, !autoTime)); 32365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 32465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME: 32565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.TIME_SET_TIME.toAction(mResources, mNowTime, !autoTime)); 32665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.TIME_SET_TIME_ZONE.toAction( 32765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mResources, getCurrentTimeZoneName())); 32865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionType.TIME_CHOOSE_FORMAT.toAction( 32965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mResources, getTimeFormatDescription())); 33065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 33165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME_CHOOSE_FORMAT: 33265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionBehavior.ON.toAction(ActionBehavior.getOnKey( 33365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionType.TIME_CHOOSE_FORMAT.name()), mResources, isTimeFormat24h())); 33465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionBehavior.OFF.toAction(ActionBehavior.getOffKey( 33565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionType.TIME_CHOOSE_FORMAT.name()), mResources, !isTimeFormat24h())); 33665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 33765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME_SET_TIME_ZONE: 33865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions = getZoneActions(this); 33965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 34065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case AUTO_DATE_TIME: 34165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionBehavior.ON.toAction(ActionBehavior.getOnKey( 34265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionType.AUTO_DATE_TIME.name()), mResources, autoTime)); 34365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActions.add(ActionBehavior.OFF.toAction(ActionBehavior.getOffKey( 34465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ActionType.AUTO_DATE_TIME.name()), mResources, !autoTime)); 34565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 34665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane default: 34765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 34865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 34965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 35065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 35165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private String getTimeFormatDescription() { 35265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String status = mHelper.getStatusStringFromBoolean(isTimeFormat24h()); 35365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String desc = String.format("%s (%s)", status, 35465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane DateFormat.getTimeFormat(this).format(mDummyDate.getTime())); 35565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return desc; 35665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 35765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 35865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 35965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void updateView() { 36065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane refreshActionList(); 36165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 36265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane switch ((ActionType) mState) { 36365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE_TIME_OVERVIEW: 36465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mOnCreateUpdateView && mOnResumeUpdateView) { 36565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // If current updateView call is due to onResume following onCreate, 36665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // avoid duplicate setView, which will lead to broken animation. 36765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnCreateUpdateView = false; 36865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnResumeUpdateView = false; 36965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 37065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return; 37165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 37265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mOnResumeUpdateView = false; 37365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 37465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionFragment = ActionFragment.newInstance(mActions); 37565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 37665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case DATE_SET_DATE: 37765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane DatePicker datePicker = 37865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane DatePicker.newInstance(new String(DateFormat.getDateFormatOrder(this))); 37965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane datePicker.setResultListener(new Picker.ResultListener() { 38065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 38165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 38265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onCommitResult(List<String> result) { 38365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String formatOrder = new String( 38465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane DateFormat.getDateFormatOrder(DateTimeActivity.this)).toUpperCase(); 38565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int yIndex = formatOrder.indexOf('Y'); 38665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int mIndex = formatOrder.indexOf('M'); 38765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int dIndex = formatOrder.indexOf('D'); 38865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (yIndex < 0 || mIndex < 0 || dIndex < 0 || 38965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane yIndex > 2 || mIndex > 2 || dIndex > 2) { 39065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Badly formatted input. Use default order. 39165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mIndex = 0; 39265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane dIndex = 1; 39365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane yIndex = 2; 39465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 39565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String month = result.get(mIndex); 39665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int day = Integer.parseInt(result.get(dIndex)); 39765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int year = Integer.parseInt(result.get(yIndex)); 39865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int monthInt = 0; 39965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String[] months = PickerConstant.getInstance(mResources).months; 40065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int totalMonths = months.length; 40165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane for (int i = 0; i < totalMonths; i++) { 40265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (months[i].equals(month)) { 40365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane monthInt = i; 40465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 40565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 40665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 40765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // turn off Auto date/time 40865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAutoDateTime(false); 40965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 41065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setDate(DateTimeActivity.this, year, monthInt, day); 41165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane goBack(); 41265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 41365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }); 41465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionFragment = datePicker; 41565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 41665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane case TIME_SET_TIME: 41765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Picker timePicker = TimePicker.newInstance(isTimeFormat24h(), true); 41865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane timePicker.setResultListener(new Picker.ResultListener() { 41965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 42065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 42165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public void onCommitResult(List<String> result) { 42265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane boolean is24hFormat = isTimeFormat24h(); 42365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int hour = Integer.parseInt(result.get(0)); 42465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int minute = Integer.parseInt(result.get(1)); 42565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (!is24hFormat) { 42665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String ampm = result.get(2); 42765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (ampm.equals(getResources().getStringArray(R.array.ampm)[1])) { 42865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // PM case, valid hours: 12-23 42965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane hour = (hour % HOURS_IN_HALF_DAY) + HOURS_IN_HALF_DAY; 43065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 43165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // AM case, valid hours: 0-11 43265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane hour = hour % HOURS_IN_HALF_DAY; 43365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 43465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 43565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 43665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // turn off Auto date/time 43765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setAutoDateTime(false); 43865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 43965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setTime(DateTimeActivity.this, hour, minute); 44065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane goBack(); 44165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 44265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane }); 44365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionFragment = timePicker; 44465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 44565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane default: 44665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mActionFragment = ActionFragment.newInstance(mActions); 44765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 44865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 44965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 45065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setViewWithActionFragment( 45165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((ActionType) mState).getTitle(mResources), getPrevState() != null ? 45265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((ActionType) getPrevState()).getTitle(mResources) 45365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane : getString(R.string.settings_app_name), 45465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ((ActionType) mState).getDescription(mResources), R.drawable.ic_settings_datetime); 45565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 45665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 45765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void setViewWithActionFragment(String title, String breadcrumb, String description, 45865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int iconResId) { 45965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mContentFragment = ContentFragment.newInstance(title, breadcrumb, description, iconResId, 46065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane getResources().getColor(R.color.icon_background)); 46165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setContentAndActionFragments(mContentFragment, mActionFragment); 46265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 46365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 46465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 46565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane protected void setProperty(boolean enable) { 46665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 46765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 46865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 46965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Returns a string representing the current time zone set in the system. 47065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 47165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private String getCurrentTimeZoneName() { 47265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final Calendar now = Calendar.getInstance(); 47365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TimeZone tz = now.getTimeZone(); 47465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 47565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Date date = new Date(); 47665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return formatOffset(new StringBuilder(), tz.getOffset(date.getTime())). 47765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane append(", "). 47865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane append(tz.getDisplayName(tz.inDaylightTime(date), TimeZone.LONG)).toString(); 47965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 48065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 48165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 48265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Formats the provided timezone offset into a string of the form GMT+XX:XX 48365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 48465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static StringBuilder formatOffset(StringBuilder sb, long offset) { 48565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane long off = offset / 1000 / 60; 48665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 48765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane sb.append("GMT"); 48865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (off < 0) { 48965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane sb.append('-'); 49065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane off = -off; 49165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 49265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane sb.append('+'); 49365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 49465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 49565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int hours = (int) (off / 60); 49665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane int minutes = (int) (off % 60); 49765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 49865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane sb.append((char) ('0' + hours / 10)); 49965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane sb.append((char) ('0' + hours % 10)); 50065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 50165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane sb.append(':'); 50265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 50365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane sb.append((char) ('0' + minutes / 10)); 50465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane sb.append((char) ('0' + minutes % 10)); 50565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 50665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return sb; 50765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 50865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 50965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 51065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Helper class to hold the time zone data parsed from the Time Zones XML 51165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * file. 51265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 51365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private class TimeZoneInfo implements Comparable<TimeZoneInfo> { 51465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public String tzId; 51565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public String tzName; 51665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public long tzOffset; 51765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 51865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public TimeZoneInfo(String id, String name, long offset) { 51965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane tzId = id; 52065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane tzName = name; 52165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane tzOffset = offset; 52265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 52365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 52465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane @Override 52565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane public int compareTo(TimeZoneInfo another) { 52665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return (int) (tzOffset - another.tzOffset); 52765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 52865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 52965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 53065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 53165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Parse the Time Zones information from the XML file and creates Action 53265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * objects for each time zone. 53365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 53465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ArrayList<Action> getZoneActions(Context context) { 53565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (mTimeZoneActions != null && mTimeZoneActions.size() != 0) { 53665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mTimeZoneActions; 53765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 53865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 53965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ArrayList<TimeZoneInfo> timeZones = getTimeZones(context); 54065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 54165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mTimeZoneActions = new ArrayList<Action>(); 54265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 54365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Sort the Time Zones list in ascending offset order 54465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Collections.sort(timeZones); 54565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 54665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TimeZone currentTz = TimeZone.getDefault(); 54765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 54865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane for (TimeZoneInfo tz : timeZones) { 54965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane StringBuilder name = new StringBuilder(); 55065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane boolean checked = currentTz.getID().equals(tz.tzId); 55165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane mTimeZoneActions.add(getTimeZoneAction(tz.tzId, tz.tzName, 55265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane formatOffset(name, tz.tzOffset).toString(), checked)); 55365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 55465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 55565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return mTimeZoneActions; 55665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 55765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 55865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane /** 55965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * Parses the XML time zone information into an array of TimeZoneInfo 56065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane * objects. 56165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane */ 56265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private ArrayList<TimeZoneInfo> getTimeZones(Context context) { 56365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane ArrayList<TimeZoneInfo> timeZones = new ArrayList<TimeZoneInfo>(); 56465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final long date = Calendar.getInstance().getTimeInMillis(); 56565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane try { 56665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane XmlResourceParser xrp = context.getResources().getXml(R.xml.timezones); 56765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane while (xrp.next() != XmlResourceParser.START_TAG) 56865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane continue; 56965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane xrp.next(); 57065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane while (xrp.getEventType() != XmlResourceParser.END_TAG) { 57165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane while (xrp.getEventType() != XmlResourceParser.START_TAG && 57265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane xrp.getEventType() != XmlResourceParser.END_DOCUMENT) { 57365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane xrp.next(); 57465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 57565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 57665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (xrp.getEventType() == XmlResourceParser.END_DOCUMENT) { 57765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane break; 57865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 57965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 58065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (xrp.getName().equals(XMLTAG_TIMEZONE)) { 58165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String id = xrp.getAttributeValue(0); 58265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane String displayName = xrp.nextText(); 58365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane TimeZone tz = TimeZone.getTimeZone(id); 58465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane long offset; 58565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane if (tz != null) { 58665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane offset = tz.getOffset(date); 58765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane timeZones.add(new TimeZoneInfo(id, displayName, offset)); 58865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } else { 58965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane continue; 59065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 59165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 59265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane while (xrp.getEventType() != XmlResourceParser.END_TAG) { 59365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane xrp.next(); 59465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 59565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane xrp.next(); 59665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 59765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane xrp.close(); 59865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } catch (XmlPullParserException xppe) { 59965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.e(TAG, "Ill-formatted timezones.xml file"); 60065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } catch (java.io.IOException ioe) { 60165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane Log.e(TAG, "Unable to read timezones.xml file"); 60265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return timeZones; 60465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 60565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 60665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private static Action getTimeZoneAction(String tzId, String displayName, String gmt, 60765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane boolean setChecked) { 60865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane return new Action.Builder().key(tzId).title(displayName).description(gmt). 60965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane checked(setChecked).build(); 61065a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 61165a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 61265a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane private void setTimeZone(String tzId) { 61365a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane // Update the system timezone value 61465a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane final AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 61565a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane alarm.setTimeZone(tzId); 61665a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane 61765a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane setSampleDate(); 61865a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane } 61965a5a7d84ad9b5324ae53eda526e39e513473af7Christopher Lane} 620