1 /* 2 * Copyright (C) 2015 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.settings; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.os.Bundle; 22 import android.os.Vibrator; 23 import android.provider.Settings; 24 import androidx.preference.ListPreference; 25 import androidx.preference.ListPreferenceDialogFragmentCompat; 26 import androidx.preference.Preference; 27 import androidx.preference.PreferenceDialogFragmentCompat; 28 import androidx.preference.PreferenceFragmentCompat; 29 import androidx.preference.TwoStatePreference; 30 import android.view.Menu; 31 import android.view.MenuItem; 32 import android.view.View; 33 34 import com.android.deskclock.BaseActivity; 35 import com.android.deskclock.DropShadowController; 36 import com.android.deskclock.R; 37 import com.android.deskclock.Utils; 38 import com.android.deskclock.actionbarmenu.MenuItemControllerFactory; 39 import com.android.deskclock.actionbarmenu.NavUpMenuItemController; 40 import com.android.deskclock.actionbarmenu.OptionsMenuManager; 41 import com.android.deskclock.data.DataModel; 42 import com.android.deskclock.data.TimeZones; 43 import com.android.deskclock.data.Weekdays; 44 import com.android.deskclock.ringtone.RingtonePickerActivity; 45 46 /** 47 * Settings for the Alarm Clock. 48 */ 49 public final class SettingsActivity extends BaseActivity { 50 51 public static final String KEY_ALARM_SNOOZE = "snooze_duration"; 52 public static final String KEY_ALARM_CRESCENDO = "alarm_crescendo_duration"; 53 public static final String KEY_TIMER_CRESCENDO = "timer_crescendo_duration"; 54 public static final String KEY_TIMER_RINGTONE = "timer_ringtone"; 55 public static final String KEY_TIMER_VIBRATE = "timer_vibrate"; 56 public static final String KEY_AUTO_SILENCE = "auto_silence"; 57 public static final String KEY_CLOCK_STYLE = "clock_style"; 58 public static final String KEY_CLOCK_DISPLAY_SECONDS = "display_clock_seconds"; 59 public static final String KEY_HOME_TZ = "home_time_zone"; 60 public static final String KEY_AUTO_HOME_CLOCK = "automatic_home_clock"; 61 public static final String KEY_DATE_TIME = "date_time"; 62 public static final String KEY_VOLUME_BUTTONS = "volume_button_setting"; 63 public static final String KEY_WEEK_START = "week_start"; 64 65 public static final String DEFAULT_VOLUME_BEHAVIOR = "0"; 66 public static final String VOLUME_BEHAVIOR_SNOOZE = "1"; 67 public static final String VOLUME_BEHAVIOR_DISMISS = "2"; 68 69 public static final String PREFS_FRAGMENT_TAG = "prefs_fragment"; 70 public static final String PREFERENCE_DIALOG_FRAGMENT_TAG = "preference_dialog"; 71 72 private final OptionsMenuManager mOptionsMenuManager = new OptionsMenuManager(); 73 74 /** 75 * The controller that shows the drop shadow when content is not scrolled to the top. 76 */ 77 private DropShadowController mDropShadowController; 78 79 @Override onCreate(Bundle savedInstanceState)80 protected void onCreate(Bundle savedInstanceState) { 81 super.onCreate(savedInstanceState); 82 setContentView(R.layout.settings); 83 84 mOptionsMenuManager.addMenuItemController(new NavUpMenuItemController(this)) 85 .addMenuItemController(MenuItemControllerFactory.getInstance() 86 .buildMenuItemControllers(this)); 87 88 // Create the prefs fragment in code to ensure it's created before PreferenceDialogFragment 89 if (savedInstanceState == null) { 90 getSupportFragmentManager().beginTransaction() 91 .replace(R.id.main, new PrefsFragment(), PREFS_FRAGMENT_TAG) 92 .disallowAddToBackStack() 93 .commit(); 94 } 95 } 96 97 @Override onResume()98 protected void onResume() { 99 super.onResume(); 100 101 final View dropShadow = findViewById(R.id.drop_shadow); 102 final PrefsFragment fragment = 103 (PrefsFragment) getSupportFragmentManager().findFragmentById(R.id.main); 104 mDropShadowController = new DropShadowController(dropShadow, fragment.getListView()); 105 } 106 107 @Override onPause()108 protected void onPause() { 109 mDropShadowController.stop(); 110 super.onPause(); 111 } 112 113 @Override onCreateOptionsMenu(Menu menu)114 public boolean onCreateOptionsMenu(Menu menu) { 115 mOptionsMenuManager.onCreateOptionsMenu(menu); 116 return true; 117 } 118 119 @Override onPrepareOptionsMenu(Menu menu)120 public boolean onPrepareOptionsMenu(Menu menu) { 121 mOptionsMenuManager.onPrepareOptionsMenu(menu); 122 return true; 123 } 124 125 @Override onOptionsItemSelected(MenuItem item)126 public boolean onOptionsItemSelected(MenuItem item) { 127 return mOptionsMenuManager.onOptionsItemSelected(item) 128 || super.onOptionsItemSelected(item); 129 } 130 131 public static class PrefsFragment extends PreferenceFragmentCompat implements 132 Preference.OnPreferenceChangeListener, 133 Preference.OnPreferenceClickListener { 134 135 @Override onCreatePreferences(Bundle bundle, String rootKey)136 public void onCreatePreferences(Bundle bundle, String rootKey) { 137 getPreferenceManager().setStorageDeviceProtected(); 138 addPreferencesFromResource(R.xml.settings); 139 final Preference timerVibrate = findPreference(KEY_TIMER_VIBRATE); 140 final boolean hasVibrator = ((Vibrator) timerVibrate.getContext() 141 .getSystemService(VIBRATOR_SERVICE)).hasVibrator(); 142 timerVibrate.setVisible(hasVibrator); 143 loadTimeZoneList(); 144 } 145 146 @Override onActivityCreated(Bundle savedInstanceState)147 public void onActivityCreated(Bundle savedInstanceState) { 148 super.onActivityCreated(savedInstanceState); 149 150 // By default, do not recreate the DeskClock activity 151 getActivity().setResult(RESULT_CANCELED); 152 } 153 154 @Override onResume()155 public void onResume() { 156 super.onResume(); 157 refresh(); 158 } 159 160 @Override onPreferenceChange(Preference pref, Object newValue)161 public boolean onPreferenceChange(Preference pref, Object newValue) { 162 switch (pref.getKey()) { 163 case KEY_ALARM_CRESCENDO: 164 case KEY_HOME_TZ: 165 case KEY_ALARM_SNOOZE: 166 case KEY_TIMER_CRESCENDO: 167 final ListPreference preference = (ListPreference) pref; 168 final int index = preference.findIndexOfValue((String) newValue); 169 preference.setSummary(preference.getEntries()[index]); 170 break; 171 case KEY_CLOCK_STYLE: 172 case KEY_WEEK_START: 173 case KEY_VOLUME_BUTTONS: 174 final SimpleMenuPreference simpleMenuPreference = (SimpleMenuPreference) pref; 175 final int i = simpleMenuPreference.findIndexOfValue((String) newValue); 176 pref.setSummary(simpleMenuPreference.getEntries()[i]); 177 break; 178 case KEY_CLOCK_DISPLAY_SECONDS: 179 DataModel.getDataModel().setDisplayClockSeconds((boolean) newValue); 180 break; 181 case KEY_AUTO_SILENCE: 182 final String delay = (String) newValue; 183 updateAutoSnoozeSummary((ListPreference) pref, delay); 184 break; 185 case KEY_AUTO_HOME_CLOCK: 186 final boolean autoHomeClockEnabled = ((TwoStatePreference) pref).isChecked(); 187 final Preference homeTimeZonePref = findPreference(KEY_HOME_TZ); 188 homeTimeZonePref.setEnabled(!autoHomeClockEnabled); 189 break; 190 case KEY_TIMER_VIBRATE: 191 final TwoStatePreference timerVibratePref = (TwoStatePreference) pref; 192 DataModel.getDataModel().setTimerVibrate(timerVibratePref.isChecked()); 193 break; 194 case KEY_TIMER_RINGTONE: 195 pref.setSummary(DataModel.getDataModel().getTimerRingtoneTitle()); 196 break; 197 } 198 // Set result so DeskClock knows to refresh itself 199 getActivity().setResult(RESULT_OK); 200 return true; 201 } 202 203 @Override onPreferenceClick(Preference pref)204 public boolean onPreferenceClick(Preference pref) { 205 final Context context = getActivity(); 206 if (context == null) { 207 return false; 208 } 209 210 switch (pref.getKey()) { 211 case KEY_DATE_TIME: 212 final Intent dialogIntent = new Intent(Settings.ACTION_DATE_SETTINGS); 213 dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 214 startActivity(dialogIntent); 215 return true; 216 case KEY_TIMER_RINGTONE: 217 startActivity(RingtonePickerActivity.createTimerRingtonePickerIntent(context)); 218 return true; 219 } 220 221 return false; 222 } 223 224 @Override onDisplayPreferenceDialog(Preference preference)225 public void onDisplayPreferenceDialog(Preference preference) { 226 // Only single-selection lists are currently supported. 227 final PreferenceDialogFragmentCompat f; 228 if (preference instanceof ListPreference) { 229 f = ListPreferenceDialogFragmentCompat.newInstance(preference.getKey()); 230 } else { 231 throw new IllegalArgumentException("Unsupported DialogPreference type"); 232 } 233 showDialog(f); 234 } 235 showDialog(PreferenceDialogFragmentCompat fragment)236 private void showDialog(PreferenceDialogFragmentCompat fragment) { 237 // Don't show dialog if one is already shown. 238 if (getFragmentManager().findFragmentByTag(PREFERENCE_DIALOG_FRAGMENT_TAG) != null) { 239 return; 240 } 241 // Always set the target fragment, this is required by PreferenceDialogFragment 242 // internally. 243 fragment.setTargetFragment(this, 0); 244 // Don't use getChildFragmentManager(), it causes issues on older platforms when the 245 // target fragment is being restored after an orientation change. 246 fragment.show(getFragmentManager(), PREFERENCE_DIALOG_FRAGMENT_TAG); 247 } 248 249 /** 250 * Reconstruct the timezone list. 251 */ loadTimeZoneList()252 private void loadTimeZoneList() { 253 final TimeZones timezones = DataModel.getDataModel().getTimeZones(); 254 final ListPreference homeTimezonePref = (ListPreference) findPreference(KEY_HOME_TZ); 255 homeTimezonePref.setEntryValues(timezones.getTimeZoneIds()); 256 homeTimezonePref.setEntries(timezones.getTimeZoneNames()); 257 homeTimezonePref.setSummary(homeTimezonePref.getEntry()); 258 homeTimezonePref.setOnPreferenceChangeListener(this); 259 } 260 refresh()261 private void refresh() { 262 final ListPreference autoSilencePref = 263 (ListPreference) findPreference(KEY_AUTO_SILENCE); 264 String delay = autoSilencePref.getValue(); 265 updateAutoSnoozeSummary(autoSilencePref, delay); 266 autoSilencePref.setOnPreferenceChangeListener(this); 267 268 final SimpleMenuPreference clockStylePref = (SimpleMenuPreference) 269 findPreference(KEY_CLOCK_STYLE); 270 clockStylePref.setSummary(clockStylePref.getEntry()); 271 clockStylePref.setOnPreferenceChangeListener(this); 272 273 final SimpleMenuPreference volumeButtonsPref = (SimpleMenuPreference) 274 findPreference(KEY_VOLUME_BUTTONS); 275 volumeButtonsPref.setSummary(volumeButtonsPref.getEntry()); 276 volumeButtonsPref.setOnPreferenceChangeListener(this); 277 278 final Preference clockSecondsPref = findPreference(KEY_CLOCK_DISPLAY_SECONDS); 279 clockSecondsPref.setOnPreferenceChangeListener(this); 280 281 final Preference autoHomeClockPref = findPreference(KEY_AUTO_HOME_CLOCK); 282 final boolean autoHomeClockEnabled = 283 ((TwoStatePreference) autoHomeClockPref).isChecked(); 284 autoHomeClockPref.setOnPreferenceChangeListener(this); 285 286 final ListPreference homeTimezonePref = (ListPreference) findPreference(KEY_HOME_TZ); 287 homeTimezonePref.setEnabled(autoHomeClockEnabled); 288 refreshListPreference(homeTimezonePref); 289 290 refreshListPreference((ListPreference) findPreference(KEY_ALARM_CRESCENDO)); 291 refreshListPreference((ListPreference) findPreference(KEY_TIMER_CRESCENDO)); 292 refreshListPreference((ListPreference) findPreference(KEY_ALARM_SNOOZE)); 293 294 final Preference dateAndTimeSetting = findPreference(KEY_DATE_TIME); 295 dateAndTimeSetting.setOnPreferenceClickListener(this); 296 297 final SimpleMenuPreference weekStartPref = (SimpleMenuPreference) 298 findPreference(KEY_WEEK_START); 299 // Set the default value programmatically 300 final Weekdays.Order weekdayOrder = DataModel.getDataModel().getWeekdayOrder(); 301 final Integer firstDay = weekdayOrder.getCalendarDays().get(0); 302 final String value = String.valueOf(firstDay); 303 final int idx = weekStartPref.findIndexOfValue(value); 304 weekStartPref.setValueIndex(idx); 305 weekStartPref.setSummary(weekStartPref.getEntries()[idx]); 306 weekStartPref.setOnPreferenceChangeListener(this); 307 308 final Preference timerRingtonePref = findPreference(KEY_TIMER_RINGTONE); 309 timerRingtonePref.setOnPreferenceClickListener(this); 310 timerRingtonePref.setSummary(DataModel.getDataModel().getTimerRingtoneTitle()); 311 } 312 refreshListPreference(ListPreference preference)313 private void refreshListPreference(ListPreference preference) { 314 preference.setSummary(preference.getEntry()); 315 preference.setOnPreferenceChangeListener(this); 316 } 317 updateAutoSnoozeSummary(ListPreference listPref, String delay)318 private void updateAutoSnoozeSummary(ListPreference listPref, String delay) { 319 int i = Integer.parseInt(delay); 320 if (i == -1) { 321 listPref.setSummary(R.string.auto_silence_never); 322 } else { 323 listPref.setSummary(Utils.getNumberFormattedQuantityString(getActivity(), 324 R.plurals.auto_silence_summary, i)); 325 } 326 } 327 } 328 }