SettingsActivity.java revision 1b8d83a86a13a144cb50be7c0663d9a828b99f94
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
17package com.android.deskclock.settings;
18
19import android.app.Activity;
20import android.content.Context;
21import android.content.Intent;
22import android.content.res.Resources;
23import android.media.AudioManager;
24import android.os.Bundle;
25import android.preference.ListPreference;
26import android.preference.Preference;
27import android.preference.PreferenceFragment;
28import android.preference.RingtonePreference;
29import android.preference.SwitchPreference;
30import android.provider.Settings;
31import android.text.format.DateUtils;
32import android.view.Menu;
33import android.view.MenuItem;
34
35import com.android.deskclock.BaseActivity;
36import com.android.deskclock.LogUtils;
37import com.android.deskclock.R;
38import com.android.deskclock.Utils;
39import com.android.deskclock.actionbarmenu.ActionBarMenuManager;
40import com.android.deskclock.actionbarmenu.MenuItemControllerFactory;
41import com.android.deskclock.actionbarmenu.NavUpMenuItemController;
42import com.android.deskclock.data.DataModel;
43
44import java.util.ArrayList;
45import java.util.Collections;
46import java.util.List;
47import java.util.Locale;
48import java.util.TimeZone;
49
50/**
51 * Settings for the Alarm Clock.
52 */
53public final class SettingsActivity extends BaseActivity {
54
55    public static final String KEY_ALARM_SNOOZE = "snooze_duration";
56    public static final String KEY_ALARM_VOLUME = "volume_setting";
57    public static final String KEY_ALARM_CRESCENDO = "alarm_crescendo_duration";
58    public static final String KEY_TIMER_CRESCENDO = "timer_crescendo_duration";
59    public static final String KEY_TIMER_RINGTONE = "timer_ringtone";
60    public static final String KEY_AUTO_SILENCE = "auto_silence";
61    public static final String KEY_CLOCK_STYLE = "clock_style";
62    public static final String KEY_HOME_TZ = "home_time_zone";
63    public static final String KEY_AUTO_HOME_CLOCK = "automatic_home_clock";
64    public static final String KEY_DATE_TIME = "date_time";
65    public static final String KEY_VOLUME_BUTTONS = "volume_button_setting";
66    public static final String KEY_WEEK_START = "week_start";
67
68    public static final String TIMEZONE_LOCALE = "tz_locale";
69
70    public static final String DEFAULT_VOLUME_BEHAVIOR = "0";
71    public static final String VOLUME_BEHAVIOR_SNOOZE = "1";
72    public static final String VOLUME_BEHAVIOR_DISMISS = "2";
73
74    private final ActionBarMenuManager mActionBarMenuManager = new ActionBarMenuManager(this);
75
76    @Override
77    protected void onCreate(Bundle savedInstanceState) {
78        super.onCreate(savedInstanceState);
79        setVolumeControlStream(AudioManager.STREAM_ALARM);
80        setContentView(R.layout.settings);
81        mActionBarMenuManager.addMenuItemController(new NavUpMenuItemController(this))
82            .addMenuItemController(MenuItemControllerFactory.getInstance()
83                    .buildMenuItemControllers(this));
84    }
85
86    @Override
87    public boolean onCreateOptionsMenu(Menu menu) {
88        mActionBarMenuManager.createOptionsMenu(menu, getMenuInflater());
89        return true;
90    }
91
92    @Override
93    public boolean onPrepareOptionsMenu(Menu menu) {
94        mActionBarMenuManager.prepareShowMenu(menu);
95        return true;
96    }
97
98    @Override
99    public boolean onOptionsItemSelected(MenuItem item) {
100        if (mActionBarMenuManager.handleMenuItemClick(item)) {
101            return true;
102        }
103        return super.onOptionsItemSelected(item);
104    }
105
106    public static class PrefsFragment extends PreferenceFragment
107            implements Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener {
108
109        private static CharSequence[][] mTimezones;
110        private long mTime;
111
112        @Override
113        public void onCreate(Bundle savedInstanceState) {
114            super.onCreate(savedInstanceState);
115            addPreferencesFromResource(R.xml.settings);
116        }
117
118        @Override
119        public void onResume() {
120            super.onResume();
121            loadTimeZoneList();
122            // By default, do not recreate the DeskClock activity
123            getActivity().setResult(RESULT_CANCELED);
124            refresh();
125        }
126
127        @Override
128        public boolean onPreferenceChange(Preference pref, Object newValue) {
129            final int idx;
130            switch (pref.getKey()) {
131                case KEY_AUTO_SILENCE:
132                    final ListPreference autoSilencePref = (ListPreference) pref;
133                    String delay = (String) newValue;
134                    updateAutoSnoozeSummary(autoSilencePref, delay);
135                    break;
136                case KEY_CLOCK_STYLE:
137                    final ListPreference clockStylePref = (ListPreference) pref;
138                    idx = clockStylePref.findIndexOfValue((String) newValue);
139                    clockStylePref.setSummary(clockStylePref.getEntries()[idx]);
140                    break;
141                case KEY_HOME_TZ:
142                    final ListPreference homeTimezonePref = (ListPreference) pref;
143                    idx = homeTimezonePref.findIndexOfValue((String) newValue);
144                    homeTimezonePref.setSummary(homeTimezonePref.getEntries()[idx]);
145                    break;
146                case KEY_AUTO_HOME_CLOCK:
147                    final boolean autoHomeClockEnabled = ((SwitchPreference) pref).isChecked();
148                    final Preference homeTimeZonePref = findPreference(KEY_HOME_TZ);
149                    homeTimeZonePref.setEnabled(!autoHomeClockEnabled);
150                    break;
151                case KEY_VOLUME_BUTTONS:
152                    final ListPreference volumeButtonsPref = (ListPreference) pref;
153                    final int index = volumeButtonsPref.findIndexOfValue((String) newValue);
154                    volumeButtonsPref.setSummary(volumeButtonsPref.getEntries()[index]);
155                    break;
156                case KEY_WEEK_START:
157                    final ListPreference weekStartPref = (ListPreference)
158                            findPreference(KEY_WEEK_START);
159                    idx = weekStartPref.findIndexOfValue((String) newValue);
160                    weekStartPref.setSummary(weekStartPref.getEntries()[idx]);
161                    break;
162                case KEY_TIMER_RINGTONE:
163                    final RingtonePreference timerRingtonePref = (RingtonePreference)
164                            findPreference(KEY_TIMER_RINGTONE);
165                    timerRingtonePref.setSummary(DataModel.getDataModel().getTimerRingtoneTitle());
166                    break;
167            }
168            // Set result so DeskClock knows to refresh itself
169            getActivity().setResult(RESULT_OK);
170            return true;
171        }
172
173        @Override
174        public boolean onPreferenceClick(Preference pref) {
175            final Activity activity = getActivity();
176            if (activity == null) {
177                return false;
178            }
179
180            switch (pref.getKey()) {
181                case KEY_DATE_TIME:
182                    Intent dialogIntent = new Intent(Settings.ACTION_DATE_SETTINGS);
183                    dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
184                    startActivity(dialogIntent);
185                    return true;
186                case KEY_ALARM_VOLUME:
187                    final AudioManager audioManager =
188                            (AudioManager) activity.getSystemService(Context.AUDIO_SERVICE);
189                    audioManager.adjustStreamVolume(AudioManager.STREAM_ALARM,
190                            AudioManager.ADJUST_SAME, AudioManager.FLAG_SHOW_UI);
191                    return true;
192                default:
193                    return false;
194            }
195        }
196
197        /**
198         * Reconstruct the timezone list. We don't want to do this unnecessary, so proceed only if
199         * this is the initial load or the locale has changed since the last load.
200         */
201        private void loadTimeZoneList() {
202            final Locale currentLocale = getResources().getConfiguration().locale;
203            final Context context = getActivity();
204            if (mTimezones == null || Utils.getTimezoneLocale(context) != currentLocale) {
205                mTime = System.currentTimeMillis();
206                mTimezones = getAllTimezones();
207                Utils.setTimezoneLocale(context, currentLocale);
208            }
209            final ListPreference homeTimezonePref = (ListPreference) findPreference(KEY_HOME_TZ);
210            homeTimezonePref.setEntryValues(mTimezones[0]);
211            homeTimezonePref.setEntries(mTimezones[1]);
212            homeTimezonePref.setSummary(homeTimezonePref.getEntry());
213            homeTimezonePref.setOnPreferenceChangeListener(this);
214        }
215
216        /**
217         * Returns an array of ids/time zones. This returns a double indexed array
218         * of ids and time zones for Calendar. It is an inefficient method and
219         * shouldn't be called often, but can be used for one time generation of
220         * this list.
221         *
222         * @return double array of tz ids and tz names
223         */
224        public CharSequence[][] getAllTimezones() {
225            Resources resources = this.getResources();
226            String[] ids = resources.getStringArray(R.array.timezone_values);
227            String[] labels = resources.getStringArray(R.array.timezone_labels);
228            int minLength = ids.length;
229            if (ids.length != labels.length) {
230                minLength = Math.min(minLength, labels.length);
231                LogUtils.e("Timezone ids and labels have different length!");
232            }
233            List<TimeZoneRow> timezones = new ArrayList<>();
234            for (int i = 0; i < minLength; i++) {
235                timezones.add(new TimeZoneRow(ids[i], labels[i]));
236            }
237            Collections.sort(timezones);
238
239            CharSequence[][] timeZones = new CharSequence[2][timezones.size()];
240            int i = 0;
241            for (TimeZoneRow row : timezones) {
242                timeZones[0][i] = row.mId;
243                timeZones[1][i++] = row.mDisplayName;
244            }
245            return timeZones;
246        }
247
248        private void refresh() {
249            final ListPreference autoSilencePref =
250                    (ListPreference) findPreference(KEY_AUTO_SILENCE);
251            String delay = autoSilencePref.getValue();
252            updateAutoSnoozeSummary(autoSilencePref, delay);
253            autoSilencePref.setOnPreferenceChangeListener(this);
254
255            final ListPreference clockStylePref = (ListPreference) findPreference(KEY_CLOCK_STYLE);
256            clockStylePref.setSummary(clockStylePref.getEntry());
257            clockStylePref.setOnPreferenceChangeListener(this);
258
259            final Preference autoHomeClockPref = findPreference(KEY_AUTO_HOME_CLOCK);
260            final boolean autoHomeClockEnabled = ((SwitchPreference) autoHomeClockPref).isChecked();
261            autoHomeClockPref.setOnPreferenceChangeListener(this);
262
263            final ListPreference homeTimezonePref = (ListPreference) findPreference(KEY_HOME_TZ);
264            homeTimezonePref.setEnabled(autoHomeClockEnabled);
265            homeTimezonePref.setSummary(homeTimezonePref.getEntry());
266            homeTimezonePref.setOnPreferenceChangeListener(this);
267
268            final ListPreference volumeButtonsPref =
269                    (ListPreference) findPreference(KEY_VOLUME_BUTTONS);
270            volumeButtonsPref.setSummary(volumeButtonsPref.getEntry());
271            volumeButtonsPref.setOnPreferenceChangeListener(this);
272
273            final Preference volumePref = findPreference(KEY_ALARM_VOLUME);
274            volumePref.setOnPreferenceClickListener(this);
275
276            final SnoozeLengthDialog snoozePref =
277                    (SnoozeLengthDialog) findPreference(KEY_ALARM_SNOOZE);
278            snoozePref.setSummary();
279
280            final CrescendoLengthDialog alarmCrescendoPref =
281                    (CrescendoLengthDialog) findPreference(KEY_ALARM_CRESCENDO);
282            alarmCrescendoPref.setSummary();
283
284            final CrescendoLengthDialog timerCrescendoPref =
285                    (CrescendoLengthDialog) findPreference(KEY_TIMER_CRESCENDO);
286            timerCrescendoPref.setSummary();
287
288            final Preference dateAndTimeSetting = findPreference(KEY_DATE_TIME);
289            dateAndTimeSetting.setOnPreferenceClickListener(this);
290
291            final ListPreference weekStartPref = (ListPreference) findPreference(KEY_WEEK_START);
292            // Set the default value programmatically
293            final String value = weekStartPref.getValue();
294            final int idx = weekStartPref.findIndexOfValue(
295                    value == null ? String.valueOf(Utils.DEFAULT_WEEK_START) : value);
296            weekStartPref.setValueIndex(idx);
297            weekStartPref.setSummary(weekStartPref.getEntries()[idx]);
298            weekStartPref.setOnPreferenceChangeListener(this);
299
300            final RingtonePreference timerRingtonePref =
301                    (RingtonePreference) findPreference(KEY_TIMER_RINGTONE);
302            timerRingtonePref.setSummary(DataModel.getDataModel().getTimerRingtoneTitle());
303            timerRingtonePref.setOnPreferenceChangeListener(this);
304        }
305
306        private void updateAutoSnoozeSummary(ListPreference listPref, String delay) {
307            int i = Integer.parseInt(delay);
308            if (i == -1) {
309                listPref.setSummary(R.string.auto_silence_never);
310            } else {
311                listPref.setSummary(Utils.getNumberFormattedQuantityString(getActivity(),
312                        R.plurals.auto_silence_summary, i));
313            }
314        }
315
316        private class TimeZoneRow implements Comparable<TimeZoneRow> {
317            private static final boolean SHOW_DAYLIGHT_SAVINGS_INDICATOR = false;
318
319            public final String mId;
320            public final String mDisplayName;
321            public final int mOffset;
322
323            public TimeZoneRow(String id, String name) {
324                mId = id;
325                TimeZone tz = TimeZone.getTimeZone(id);
326                boolean useDaylightTime = tz.useDaylightTime();
327                mOffset = tz.getOffset(mTime);
328                mDisplayName = buildGmtDisplayName(name, useDaylightTime);
329            }
330
331            @Override
332            public int compareTo(TimeZoneRow another) {
333                return mOffset - another.mOffset;
334            }
335
336            public String buildGmtDisplayName(String displayName, boolean useDaylightTime) {
337                int p = Math.abs(mOffset);
338                StringBuilder name = new StringBuilder("(GMT");
339                name.append(mOffset < 0 ? '-' : '+');
340
341                name.append(p / DateUtils.HOUR_IN_MILLIS);
342                name.append(':');
343
344                int min = p / 60000;
345                min %= 60;
346
347                if (min < 10) {
348                    name.append('0');
349                }
350                name.append(min);
351                name.append(") ");
352                name.append(displayName);
353                if (useDaylightTime && SHOW_DAYLIGHT_SAVINGS_INDICATOR) {
354                    name.append(" \u2600"); // Sun symbol
355                }
356                return name.toString();
357            }
358        }
359    }
360}
361