1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings; 18 19 import android.app.Activity; 20 import android.app.AlarmManager; 21 import android.app.Fragment; 22 import android.app.FragmentTransaction; 23 import android.content.BroadcastReceiver; 24 import android.content.Context; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.pm.ActivityInfo; 28 import android.content.res.Configuration; 29 import android.os.Bundle; 30 import android.preference.Preference; 31 import android.preference.PreferenceFragment; 32 import android.provider.Settings; 33 import android.provider.Settings.SettingNotFoundException; 34 import android.util.Log; 35 import android.view.View; 36 import android.view.View.OnClickListener; 37 import android.view.Window; 38 import android.view.inputmethod.InputMethodManager; 39 import android.widget.AdapterView; 40 import android.widget.AdapterView.OnItemClickListener; 41 import android.widget.Button; 42 import android.widget.CompoundButton; 43 import android.widget.CompoundButton.OnCheckedChangeListener; 44 import android.widget.DatePicker; 45 import android.widget.LinearLayout; 46 import android.widget.ListPopupWindow; 47 import android.widget.SimpleAdapter; 48 import android.widget.TextView; 49 import android.widget.TimePicker; 50 51 import java.util.Calendar; 52 import java.util.TimeZone; 53 54 public class DateTimeSettingsSetupWizard extends Activity 55 implements OnClickListener, OnItemClickListener, OnCheckedChangeListener, 56 PreferenceFragment.OnPreferenceStartFragmentCallback { 57 private static final String TAG = DateTimeSettingsSetupWizard.class.getSimpleName(); 58 59 // force the first status of auto datetime flag. 60 private static final String EXTRA_INITIAL_AUTO_DATETIME_VALUE = 61 "extra_initial_auto_datetime_value"; 62 63 // If we have enough screen real estate, we use a radically different layout with 64 // big date and time pickers right on the screen, which requires very different handling. 65 // Otherwise, we use the standard date time settings fragment. 66 private boolean mUsingXLargeLayout; 67 68 /* Available only in XL */ 69 private CompoundButton mAutoDateTimeButton; 70 // private CompoundButton mAutoTimeZoneButton; 71 72 private Button mTimeZoneButton; 73 private ListPopupWindow mTimeZonePopup; 74 private SimpleAdapter mTimeZoneAdapter; 75 private TimeZone mSelectedTimeZone; 76 77 private TimePicker mTimePicker; 78 private DatePicker mDatePicker; 79 private InputMethodManager mInputMethodManager; 80 81 @Override 82 protected void onCreate(Bundle savedInstanceState) { 83 requestWindowFeature(Window.FEATURE_NO_TITLE); 84 super.onCreate(savedInstanceState); 85 setContentView(R.layout.date_time_settings_setupwizard); 86 87 // we know we've loaded the special xlarge layout because it has controls 88 // not present in the standard layout 89 mUsingXLargeLayout = findViewById(R.id.time_zone_button) != null; 90 if (mUsingXLargeLayout) { 91 initUiForXl(); 92 } else { 93 findViewById(R.id.next_button).setOnClickListener(this); 94 } 95 mTimeZoneAdapter = ZonePicker.constructTimezoneAdapter(this, false, 96 R.layout.date_time_setup_custom_list_item_2); 97 98 // For the normal view, disable Back since changes stick immediately 99 // and can't be canceled, and we already have a Next button. For xLarge, 100 // though, we save up our changes and set them upon Next, so Back can 101 // cancel. And also, in xlarge, we need the keyboard dismiss button 102 // to be available. 103 if (!mUsingXLargeLayout) { 104 final View layoutRoot = findViewById(R.id.layout_root); 105 layoutRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_BACK); 106 } 107 } 108 109 public void initUiForXl() { 110 // Currently just comment out codes related to auto timezone. 111 // TODO: Remove them when we are sure they are unnecessary. 112 /* 113 final boolean autoTimeZoneEnabled = isAutoTimeZoneEnabled(); 114 mAutoTimeZoneButton = (CompoundButton)findViewById(R.id.time_zone_auto); 115 mAutoTimeZoneButton.setChecked(autoTimeZoneEnabled); 116 mAutoTimeZoneButton.setOnCheckedChangeListener(this); 117 mAutoTimeZoneButton.setText(autoTimeZoneEnabled ? R.string.zone_auto_summaryOn : 118 R.string.zone_auto_summaryOff);*/ 119 120 final TimeZone tz = TimeZone.getDefault(); 121 mSelectedTimeZone = tz; 122 mTimeZoneButton = (Button)findViewById(R.id.time_zone_button); 123 mTimeZoneButton.setText(tz.getDisplayName()); 124 mTimeZoneButton.setOnClickListener(this); 125 126 final boolean autoDateTimeEnabled; 127 final Intent intent = getIntent(); 128 if (intent.hasExtra(EXTRA_INITIAL_AUTO_DATETIME_VALUE)) { 129 autoDateTimeEnabled = intent.getBooleanExtra(EXTRA_INITIAL_AUTO_DATETIME_VALUE, false); 130 } else { 131 autoDateTimeEnabled = isAutoDateTimeEnabled(); 132 } 133 134 mAutoDateTimeButton = (CompoundButton)findViewById(R.id.date_time_auto_button); 135 mAutoDateTimeButton.setChecked(autoDateTimeEnabled); 136 mAutoDateTimeButton.setOnCheckedChangeListener(this); 137 138 mTimePicker = (TimePicker)findViewById(R.id.time_picker); 139 mTimePicker.setEnabled(!autoDateTimeEnabled); 140 mDatePicker = (DatePicker)findViewById(R.id.date_picker); 141 mDatePicker.setEnabled(!autoDateTimeEnabled); 142 mDatePicker.setCalendarViewShown(false); 143 DateTimeSettings.configureDatePicker(mDatePicker); 144 145 mInputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 146 147 ((Button)findViewById(R.id.next_button)).setOnClickListener(this); 148 final Button skipButton = (Button)findViewById(R.id.skip_button); 149 if (skipButton != null) { 150 skipButton.setOnClickListener(this); 151 } 152 } 153 154 @Override 155 public void onResume() { 156 super.onResume(); 157 IntentFilter filter = new IntentFilter(); 158 filter.addAction(Intent.ACTION_TIME_TICK); 159 filter.addAction(Intent.ACTION_TIME_CHANGED); 160 filter.addAction(Intent.ACTION_TIMEZONE_CHANGED); 161 registerReceiver(mIntentReceiver, filter, null, null); 162 } 163 164 @Override 165 public void onPause() { 166 super.onPause(); 167 unregisterReceiver(mIntentReceiver); 168 } 169 170 @Override 171 public void onClick(View view) { 172 switch (view.getId()) { 173 case R.id.time_zone_button: { 174 showTimezonePicker(R.id.time_zone_button); 175 break; 176 } 177 case R.id.next_button: { 178 if (mSelectedTimeZone != null) { 179 final TimeZone systemTimeZone = TimeZone.getDefault(); 180 if (!systemTimeZone.equals(mSelectedTimeZone)) { 181 Log.i(TAG, "Another TimeZone is selected by a user. Changing system TimeZone."); 182 final AlarmManager alarm = (AlarmManager) 183 getSystemService(Context.ALARM_SERVICE); 184 alarm.setTimeZone(mSelectedTimeZone.getID()); 185 } 186 } 187 if (mAutoDateTimeButton != null) { 188 Settings.Global.putInt(getContentResolver(), Settings.Global.AUTO_TIME, 189 mAutoDateTimeButton.isChecked() ? 1 : 0); 190 if (!mAutoDateTimeButton.isChecked()) { 191 DateTimeSettings.setDate(this, mDatePicker.getYear(), mDatePicker.getMonth(), 192 mDatePicker.getDayOfMonth()); 193 DateTimeSettings.setTime(this, 194 mTimePicker.getCurrentHour(), mTimePicker.getCurrentMinute()); 195 } 196 } 197 } // $FALL-THROUGH$ 198 case R.id.skip_button: { 199 setResult(RESULT_OK); 200 finish(); 201 break; 202 } 203 } 204 } 205 206 @Override 207 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 208 final boolean autoEnabled = isChecked; // just for readibility. 209 /*if (buttonView == mAutoTimeZoneButton) { 210 // In XL screen, we save all the state only when the next button is pressed. 211 if (!mUsingXLargeLayout) { 212 Settings.Global.putInt(getContentResolver(), 213 Settings.Global.AUTO_TIME_ZONE, 214 isChecked ? 1 : 0); 215 } 216 mTimeZone.setEnabled(!autoEnabled); 217 if (isChecked) { 218 findViewById(R.id.current_time_zone).setVisibility(View.VISIBLE); 219 findViewById(R.id.zone_picker).setVisibility(View.GONE); 220 } 221 } else */ 222 if (buttonView == mAutoDateTimeButton) { 223 Settings.Global.putInt(getContentResolver(), 224 Settings.Global.AUTO_TIME, 225 isChecked ? 1 : 0); 226 mTimePicker.setEnabled(!autoEnabled); 227 mDatePicker.setEnabled(!autoEnabled); 228 } 229 if (autoEnabled) { 230 final View focusedView = getCurrentFocus(); 231 if (focusedView != null) { 232 mInputMethodManager.hideSoftInputFromWindow(focusedView.getWindowToken(), 0); 233 focusedView.clearFocus(); 234 } 235 } 236 } 237 238 @Override 239 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 240 final TimeZone tz = ZonePicker.obtainTimeZoneFromItem(parent.getItemAtPosition(position)); 241 if (mUsingXLargeLayout) { 242 mSelectedTimeZone = tz; 243 final Calendar now = Calendar.getInstance(tz); 244 if (mTimeZoneButton != null) { 245 mTimeZoneButton.setText(tz.getDisplayName()); 246 } 247 mDatePicker.updateDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH), 248 now.get(Calendar.DAY_OF_MONTH)); 249 mTimePicker.setCurrentHour(now.get(Calendar.HOUR_OF_DAY)); 250 mTimePicker.setCurrentMinute(now.get(Calendar.MINUTE)); 251 } else { 252 // in prefs mode, we actually change the setting right now, as opposed to waiting 253 // until Next is pressed in xLarge mode 254 final AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE); 255 alarm.setTimeZone(tz.getID()); 256 DateTimeSettings settingsFragment = (DateTimeSettings) getFragmentManager(). 257 findFragmentById(R.id.date_time_settings_fragment); 258 settingsFragment.updateTimeAndDateDisplay(this); 259 } 260 mTimeZonePopup.dismiss(); 261 } 262 263 /** 264 * If this is called, that means we're in prefs style portrait mode for a large display 265 * and the user has tapped on the time zone preference. If we were a PreferenceActivity, 266 * we'd then launch the timezone fragment in a new activity, but we aren't, and here 267 * on a tablet display, we really want more of a popup picker look' like the one we use 268 * for the xlarge version of this activity. So we just take this opportunity to launch that. 269 * 270 * TODO: For phones, we might want to change this to do the "normal" opening 271 * of the zonepicker fragment in its own activity. Or we might end up just 272 * creating a separate DateTimeSettingsSetupWizardPhone activity that subclasses 273 * PreferenceActivity in the first place to handle all that automatically. 274 */ 275 @Override 276 public boolean onPreferenceStartFragment(PreferenceFragment caller, Preference pref) { 277 showTimezonePicker(R.id.timezone_dropdown_anchor); 278 return true; 279 } 280 281 private void showTimezonePicker(int anchorViewId) { 282 View anchorView = findViewById(anchorViewId); 283 if (anchorView == null) { 284 Log.e(TAG, "Unable to find zone picker anchor view " + anchorViewId); 285 return; 286 } 287 mTimeZonePopup = new ListPopupWindow(this, null); 288 mTimeZonePopup.setWidth(anchorView.getWidth()); 289 mTimeZonePopup.setAnchorView(anchorView); 290 mTimeZonePopup.setAdapter(mTimeZoneAdapter); 291 mTimeZonePopup.setOnItemClickListener(this); 292 mTimeZonePopup.setModal(true); 293 mTimeZonePopup.show(); 294 } 295 296 private boolean isAutoDateTimeEnabled() { 297 try { 298 return Settings.Global.getInt(getContentResolver(), Settings.Global.AUTO_TIME) > 0; 299 } catch (SettingNotFoundException e) { 300 return true; 301 } 302 } 303 304 /* 305 private boolean isAutoTimeZoneEnabled() { 306 try { 307 return Settings.Global.getInt(getContentResolver(), 308 Settings.Global.AUTO_TIME_ZONE) > 0; 309 } catch (SettingNotFoundException e) { 310 return true; 311 } 312 }*/ 313 314 private void updateTimeAndDateDisplay() { 315 if (!mUsingXLargeLayout) { 316 return; 317 } 318 final Calendar now = Calendar.getInstance(); 319 mTimeZoneButton.setText(now.getTimeZone().getDisplayName()); 320 mDatePicker.updateDate(now.get(Calendar.YEAR), now.get(Calendar.MONTH), 321 now.get(Calendar.DAY_OF_MONTH)); 322 mTimePicker.setCurrentHour(now.get(Calendar.HOUR_OF_DAY)); 323 mTimePicker.setCurrentMinute(now.get(Calendar.MINUTE)); 324 } 325 326 private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { 327 @Override 328 public void onReceive(Context context, Intent intent) { 329 updateTimeAndDateDisplay(); 330 } 331 }; 332 } 333