1 /* 2 * Copyright (C) 2009 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.deskclock; 18 19 import android.app.ActionBar; 20 import android.content.Intent; 21 import android.content.res.Resources; 22 import android.media.AudioManager; 23 import android.os.Bundle; 24 import android.preference.CheckBoxPreference; 25 import android.preference.ListPreference; 26 import android.preference.Preference; 27 import android.preference.PreferenceActivity; 28 import android.preference.PreferenceScreen; 29 import android.provider.Settings; 30 import android.text.format.DateUtils; 31 import android.view.Menu; 32 import android.view.MenuItem; 33 34 import com.android.deskclock.worldclock.Cities; 35 36 import java.util.ArrayList; 37 import java.util.Collections; 38 import java.util.List; 39 import java.util.TimeZone; 40 41 /** 42 * Settings for the Alarm Clock. 43 */ 44 public class SettingsActivity extends PreferenceActivity 45 implements Preference.OnPreferenceChangeListener { 46 47 private static final int ALARM_STREAM_TYPE_BIT = 48 1 << AudioManager.STREAM_ALARM; 49 50 public static final String KEY_ALARM_IN_SILENT_MODE = 51 "alarm_in_silent_mode"; 52 public static final String KEY_ALARM_SNOOZE = 53 "snooze_duration"; 54 public static final String KEY_VOLUME_BEHAVIOR = 55 "volume_button_setting"; 56 public static final String KEY_AUTO_SILENCE = 57 "auto_silence"; 58 public static final String KEY_CLOCK_STYLE = 59 "clock_style"; 60 public static final String KEY_HOME_TZ = 61 "home_time_zone"; 62 public static final String KEY_AUTO_HOME_CLOCK = 63 "automatic_home_clock"; 64 public static final String KEY_VOLUME_BUTTONS = 65 "volume_button_setting"; 66 67 public static final String DEFAULT_VOLUME_BEHAVIOR = "0"; 68 69 private static CharSequence[][] mTimezones; 70 private long mTime; 71 72 73 @Override 74 protected void onCreate(Bundle savedInstanceState) { 75 super.onCreate(savedInstanceState); 76 addPreferencesFromResource(R.xml.settings); 77 78 ActionBar actionBar = getActionBar(); 79 if (actionBar != null) { 80 actionBar.setDisplayOptions(ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP); 81 } 82 83 // We don't want to reconstruct the timezone list every single time 84 // onResume() is called so we do it once in onCreate 85 ListPreference listPref; 86 listPref = (ListPreference) findPreference(KEY_HOME_TZ); 87 if (mTimezones == null) { 88 mTime = System.currentTimeMillis(); 89 mTimezones = getAllTimezones(); 90 } 91 92 listPref.setEntryValues(mTimezones[0]); 93 listPref.setEntries(mTimezones[1]); 94 listPref.setSummary(listPref.getEntry()); 95 listPref.setOnPreferenceChangeListener(this); 96 } 97 98 @Override 99 protected void onResume() { 100 super.onResume(); 101 refresh(); 102 } 103 104 @Override 105 public boolean onOptionsItemSelected (MenuItem item) { 106 switch (item.getItemId()) { 107 case android.R.id.home: 108 finish(); 109 return true; 110 default: 111 break; 112 } 113 return super.onOptionsItemSelected(item); 114 } 115 116 117 @Override 118 public boolean onCreateOptionsMenu (Menu menu) { 119 getMenuInflater().inflate(R.menu.settings_menu, menu); 120 MenuItem help = menu.findItem(R.id.menu_item_help); 121 if (help != null) { 122 Utils.prepareHelpMenuItem(this, help); 123 } 124 return super.onCreateOptionsMenu(menu); 125 } 126 127 @Override 128 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, 129 Preference preference) { 130 if (KEY_ALARM_IN_SILENT_MODE.equals(preference.getKey())) { 131 CheckBoxPreference pref = (CheckBoxPreference) preference; 132 int ringerModeStreamTypes = Settings.System.getInt( 133 getContentResolver(), 134 Settings.System.MODE_RINGER_STREAMS_AFFECTED, 0); 135 136 if (pref.isChecked()) { 137 ringerModeStreamTypes &= ~ALARM_STREAM_TYPE_BIT; 138 } else { 139 ringerModeStreamTypes |= ALARM_STREAM_TYPE_BIT; 140 } 141 142 Settings.System.putInt(getContentResolver(), 143 Settings.System.MODE_RINGER_STREAMS_AFFECTED, 144 ringerModeStreamTypes); 145 146 return true; 147 } 148 149 return super.onPreferenceTreeClick(preferenceScreen, preference); 150 } 151 152 @Override 153 public boolean onPreferenceChange(Preference pref, Object newValue) { 154 if (KEY_AUTO_SILENCE.equals(pref.getKey())) { 155 final ListPreference listPref = (ListPreference) pref; 156 String delay = (String) newValue; 157 updateAutoSnoozeSummary(listPref, delay); 158 } else if (KEY_CLOCK_STYLE.equals(pref.getKey())) { 159 final ListPreference listPref = (ListPreference) pref; 160 final int idx = listPref.findIndexOfValue((String) newValue); 161 listPref.setSummary(listPref.getEntries()[idx]); 162 } else if (KEY_HOME_TZ.equals(pref.getKey())) { 163 final ListPreference listPref = (ListPreference) pref; 164 final int idx = listPref.findIndexOfValue((String) newValue); 165 listPref.setSummary(listPref.getEntries()[idx]); 166 notifyHomeTimeZoneChanged(); 167 } else if (KEY_AUTO_HOME_CLOCK.equals(pref.getKey())) { 168 boolean state =((CheckBoxPreference) pref).isChecked(); 169 Preference homeTimeZone = findPreference(KEY_HOME_TZ); 170 homeTimeZone.setEnabled(!state); 171 notifyHomeTimeZoneChanged(); 172 } else if (KEY_VOLUME_BUTTONS.equals(pref.getKey())) { 173 final ListPreference listPref = (ListPreference) pref; 174 final int idx = listPref.findIndexOfValue((String) newValue); 175 listPref.setSummary(listPref.getEntries()[idx]); 176 } 177 return true; 178 } 179 180 @Override 181 protected boolean isValidFragment(String fragmentName) { 182 // Exported activity but no headers we support. 183 return false; 184 } 185 186 private void updateAutoSnoozeSummary(ListPreference listPref, 187 String delay) { 188 int i = Integer.parseInt(delay); 189 if (i == -1) { 190 listPref.setSummary(R.string.auto_silence_never); 191 } else { 192 listPref.setSummary(getString(R.string.auto_silence_summary, i)); 193 } 194 } 195 196 private void notifyHomeTimeZoneChanged() { 197 Intent i = new Intent(Cities.WORLDCLOCK_UPDATE_INTENT); 198 sendBroadcast(i); 199 } 200 201 202 private void refresh() { 203 ListPreference listPref = (ListPreference) findPreference(KEY_AUTO_SILENCE); 204 String delay = listPref.getValue(); 205 updateAutoSnoozeSummary(listPref, delay); 206 listPref.setOnPreferenceChangeListener(this); 207 208 listPref = (ListPreference) findPreference(KEY_CLOCK_STYLE); 209 listPref.setSummary(listPref.getEntry()); 210 listPref.setOnPreferenceChangeListener(this); 211 212 Preference pref = findPreference(KEY_AUTO_HOME_CLOCK); 213 boolean state =((CheckBoxPreference) pref).isChecked(); 214 pref.setOnPreferenceChangeListener(this); 215 216 listPref = (ListPreference)findPreference(KEY_HOME_TZ); 217 listPref.setEnabled(state); 218 listPref.setSummary(listPref.getEntry()); 219 220 listPref = (ListPreference) findPreference(KEY_VOLUME_BUTTONS); 221 listPref.setSummary(listPref.getEntry()); 222 listPref.setOnPreferenceChangeListener(this); 223 224 SnoozeLengthDialog snoozePref = (SnoozeLengthDialog) findPreference(KEY_ALARM_SNOOZE); 225 snoozePref.setSummary(); 226 } 227 228 private class TimeZoneRow implements Comparable<TimeZoneRow> { 229 private static final boolean SHOW_DAYLIGHT_SAVINGS_INDICATOR = false; 230 231 public final String mId; 232 public final String mDisplayName; 233 public final int mOffset; 234 235 public TimeZoneRow(String id, String name) { 236 mId = id; 237 TimeZone tz = TimeZone.getTimeZone(id); 238 boolean useDaylightTime = tz.useDaylightTime(); 239 mOffset = tz.getOffset(mTime); 240 mDisplayName = buildGmtDisplayName(id, name, useDaylightTime); 241 } 242 243 @Override 244 public int compareTo(TimeZoneRow another) { 245 return mOffset - another.mOffset; 246 } 247 248 public String buildGmtDisplayName(String id, String displayName, boolean useDaylightTime) { 249 int p = Math.abs(mOffset); 250 StringBuilder name = new StringBuilder("(GMT"); 251 name.append(mOffset < 0 ? '-' : '+'); 252 253 name.append(p / DateUtils.HOUR_IN_MILLIS); 254 name.append(':'); 255 256 int min = p / 60000; 257 min %= 60; 258 259 if (min < 10) { 260 name.append('0'); 261 } 262 name.append(min); 263 name.append(") "); 264 name.append(displayName); 265 if (useDaylightTime && SHOW_DAYLIGHT_SAVINGS_INDICATOR) { 266 name.append(" \u2600"); // Sun symbol 267 } 268 return name.toString(); 269 } 270 } 271 272 273 /** 274 * Returns an array of ids/time zones. This returns a double indexed array 275 * of ids and time zones for Calendar. It is an inefficient method and 276 * shouldn't be called often, but can be used for one time generation of 277 * this list. 278 * 279 * @return double array of tz ids and tz names 280 */ 281 public CharSequence[][] getAllTimezones() { 282 Resources resources = this.getResources(); 283 String[] ids = resources.getStringArray(R.array.timezone_values); 284 String[] labels = resources.getStringArray(R.array.timezone_labels); 285 int minLength = ids.length; 286 if (ids.length != labels.length) { 287 minLength = Math.min(minLength, labels.length); 288 Log.e("Timezone ids and labels have different length!"); 289 } 290 List<TimeZoneRow> timezones = new ArrayList<TimeZoneRow>(); 291 for (int i = 0; i < minLength; i++) { 292 timezones.add(new TimeZoneRow(ids[i], labels[i])); 293 } 294 Collections.sort(timezones); 295 296 CharSequence[][] timeZones = new CharSequence[2][timezones.size()]; 297 int i = 0; 298 for (TimeZoneRow row : timezones) { 299 timeZones[0][i] = row.mId; 300 timeZones[1][i++] = row.mDisplayName; 301 } 302 return timeZones; 303 } 304 305 } 306