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 static final String KEY_ALARM_IN_SILENT_MODE = 51 "alarm_in_silent_mode"; 52 static final String KEY_ALARM_SNOOZE = 53 "snooze_duration"; 54 static final String KEY_VOLUME_BEHAVIOR = 55 "volume_button_setting"; 56 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 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 private void updateAutoSnoozeSummary(ListPreference listPref, 181 String delay) { 182 int i = Integer.parseInt(delay); 183 if (i == -1) { 184 listPref.setSummary(R.string.auto_silence_never); 185 } else { 186 listPref.setSummary(getString(R.string.auto_silence_summary, i)); 187 } 188 } 189 190 private void notifyHomeTimeZoneChanged() { 191 Intent i = new Intent(Cities.WORLDCLOCK_UPDATE_INTENT); 192 sendBroadcast(i); 193 } 194 195 196 private void refresh() { 197 ListPreference listPref = (ListPreference) findPreference(KEY_AUTO_SILENCE); 198 String delay = listPref.getValue(); 199 updateAutoSnoozeSummary(listPref, delay); 200 listPref.setOnPreferenceChangeListener(this); 201 202 listPref = (ListPreference) findPreference(KEY_CLOCK_STYLE); 203 listPref.setSummary(listPref.getEntry()); 204 listPref.setOnPreferenceChangeListener(this); 205 206 Preference pref = findPreference(KEY_AUTO_HOME_CLOCK); 207 boolean state =((CheckBoxPreference) pref).isChecked(); 208 pref.setOnPreferenceChangeListener(this); 209 210 listPref = (ListPreference)findPreference(KEY_HOME_TZ); 211 listPref.setEnabled(state); 212 listPref.setSummary(listPref.getEntry()); 213 214 listPref = (ListPreference) findPreference(KEY_VOLUME_BUTTONS); 215 listPref.setSummary(listPref.getEntry()); 216 listPref.setOnPreferenceChangeListener(this); 217 218 SnoozeLengthDialog snoozePref = (SnoozeLengthDialog) findPreference(KEY_ALARM_SNOOZE); 219 snoozePref.setSummary(); 220 } 221 222 private class TimeZoneRow implements Comparable<TimeZoneRow> { 223 private static final boolean SHOW_DAYLIGHT_SAVINGS_INDICATOR = false; 224 225 public final String mId; 226 public final String mDisplayName; 227 public final int mOffset; 228 229 public TimeZoneRow(String id, String name) { 230 mId = id; 231 TimeZone tz = TimeZone.getTimeZone(id); 232 boolean useDaylightTime = tz.useDaylightTime(); 233 mOffset = tz.getOffset(mTime); 234 mDisplayName = buildGmtDisplayName(id, name, useDaylightTime); 235 } 236 237 @Override 238 public int compareTo(TimeZoneRow another) { 239 return mOffset - another.mOffset; 240 } 241 242 public String buildGmtDisplayName(String id, String displayName, boolean useDaylightTime) { 243 int p = Math.abs(mOffset); 244 StringBuilder name = new StringBuilder("(GMT"); 245 name.append(mOffset < 0 ? '-' : '+'); 246 247 name.append(p / DateUtils.HOUR_IN_MILLIS); 248 name.append(':'); 249 250 int min = p / 60000; 251 min %= 60; 252 253 if (min < 10) { 254 name.append('0'); 255 } 256 name.append(min); 257 name.append(") "); 258 name.append(displayName); 259 if (useDaylightTime && SHOW_DAYLIGHT_SAVINGS_INDICATOR) { 260 name.append(" \u2600"); // Sun symbol 261 } 262 return name.toString(); 263 } 264 } 265 266 267 /** 268 * Returns an array of ids/time zones. This returns a double indexed array 269 * of ids and time zones for Calendar. It is an inefficient method and 270 * shouldn't be called often, but can be used for one time generation of 271 * this list. 272 * 273 * @return double array of tz ids and tz names 274 */ 275 public CharSequence[][] getAllTimezones() { 276 Resources resources = this.getResources(); 277 String[] ids = resources.getStringArray(R.array.timezone_values); 278 String[] labels = resources.getStringArray(R.array.timezone_labels); 279 if (ids.length != labels.length) { 280 Log.wtf("Timezone ids and labels have different length!"); 281 } 282 List<TimeZoneRow> timezones = new ArrayList<TimeZoneRow>(); 283 for (int i = 0; i < ids.length; i++) { 284 timezones.add(new TimeZoneRow(ids[i], labels[i])); 285 } 286 Collections.sort(timezones); 287 288 CharSequence[][] timeZones = new CharSequence[2][timezones.size()]; 289 int i = 0; 290 for (TimeZoneRow row : timezones) { 291 timeZones[0][i] = row.mId; 292 timeZones[1][i++] = row.mDisplayName; 293 } 294 return timeZones; 295 } 296 297 } 298