1 /* 2 * Copyright (C) 2007 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.alarmclock; 18 19 import android.app.TimePickerDialog; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.media.RingtoneManager; 23 import android.net.Uri; 24 import android.os.Bundle; 25 import android.preference.CheckBoxPreference; 26 import android.preference.EditTextPreference; 27 import android.preference.Preference; 28 import android.preference.PreferenceActivity; 29 import android.preference.PreferenceScreen; 30 import android.text.format.DateFormat; 31 import android.view.LayoutInflater; 32 import android.view.Menu; 33 import android.view.MenuItem; 34 import android.view.View; 35 import android.view.ViewGroup.LayoutParams; 36 import android.widget.Button; 37 import android.widget.FrameLayout; 38 import android.widget.LinearLayout; 39 import android.widget.ListView; 40 import android.widget.TimePicker; 41 import android.widget.Toast; 42 43 /** 44 * Manages each alarm 45 */ 46 public class SetAlarm extends PreferenceActivity 47 implements TimePickerDialog.OnTimeSetListener { 48 49 private EditTextPreference mLabel; 50 private Preference mTimePref; 51 private AlarmPreference mAlarmPref; 52 private CheckBoxPreference mVibratePref; 53 private RepeatPreference mRepeatPref; 54 private MenuItem mDeleteAlarmItem; 55 private MenuItem mTestAlarmItem; 56 57 private int mId; 58 private boolean mEnabled; 59 private int mHour; 60 private int mMinutes; 61 62 /** 63 * Set an alarm. Requires an Alarms.ALARM_ID to be passed in as an 64 * extra. FIXME: Pass an Alarm object like every other Activity. 65 */ 66 @Override onCreate(Bundle icicle)67 protected void onCreate(Bundle icicle) { 68 super.onCreate(icicle); 69 70 addPreferencesFromResource(R.xml.alarm_prefs); 71 72 // Get each preference so we can retrieve the value later. 73 mLabel = (EditTextPreference) findPreference("label"); 74 mLabel.setOnPreferenceChangeListener( 75 new Preference.OnPreferenceChangeListener() { 76 public boolean onPreferenceChange(Preference p, 77 Object newValue) { 78 // Set the summary based on the new label. 79 p.setSummary((String) newValue); 80 return true; 81 } 82 }); 83 mTimePref = findPreference("time"); 84 mAlarmPref = (AlarmPreference) findPreference("alarm"); 85 mVibratePref = (CheckBoxPreference) findPreference("vibrate"); 86 mRepeatPref = (RepeatPreference) findPreference("setRepeat"); 87 88 Intent i = getIntent(); 89 mId = i.getIntExtra(Alarms.ALARM_ID, -1); 90 if (Log.LOGV) { 91 Log.v("In SetAlarm, alarm id = " + mId); 92 } 93 94 /* load alarm details from database */ 95 Alarm alarm = Alarms.getAlarm(getContentResolver(), mId); 96 mEnabled = alarm.enabled; 97 mLabel.setText(alarm.label); 98 mLabel.setSummary(alarm.label); 99 mHour = alarm.hour; 100 mMinutes = alarm.minutes; 101 mRepeatPref.setDaysOfWeek(alarm.daysOfWeek); 102 mVibratePref.setChecked(alarm.vibrate); 103 // Give the alert uri to the preference. 104 mAlarmPref.setAlert(alarm.alert); 105 updateTime(); 106 107 // We have to do this to get the save/cancel buttons to highlight on 108 // their own. 109 getListView().setItemsCanFocus(true); 110 111 // Grab the content view so we can modify it. 112 FrameLayout content = (FrameLayout) getWindow().getDecorView() 113 .findViewById(com.android.internal.R.id.content); 114 115 // Get the main ListView and remove it from the content view. 116 ListView lv = getListView(); 117 content.removeView(lv); 118 119 // Create the new LinearLayout that will become the content view and 120 // make it vertical. 121 LinearLayout ll = new LinearLayout(this); 122 ll.setOrientation(LinearLayout.VERTICAL); 123 124 // Have the ListView expand to fill the screen minus the save/cancel 125 // buttons. 126 LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams( 127 LayoutParams.FILL_PARENT, 128 LayoutParams.WRAP_CONTENT); 129 lp.weight = 1; 130 ll.addView(lv, lp); 131 132 // Inflate the buttons onto the LinearLayout. 133 View v = LayoutInflater.from(this).inflate( 134 R.layout.save_cancel_alarm, ll); 135 136 // Attach actions to each button. 137 Button b = (Button) v.findViewById(R.id.alarm_save); 138 b.setOnClickListener(new View.OnClickListener() { 139 public void onClick(View v) { 140 saveAlarm(); 141 finish(); 142 } 143 }); 144 b = (Button) v.findViewById(R.id.alarm_cancel); 145 b.setOnClickListener(new View.OnClickListener() { 146 public void onClick(View v) { 147 finish(); 148 } 149 }); 150 151 // Replace the old content view with our new one. 152 setContentView(ll); 153 } 154 155 @Override onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference)156 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, 157 Preference preference) { 158 if (preference == mTimePref) { 159 new TimePickerDialog(this, this, mHour, mMinutes, 160 DateFormat.is24HourFormat(this)).show(); 161 } 162 163 return super.onPreferenceTreeClick(preferenceScreen, preference); 164 } 165 166 @Override onBackPressed()167 public void onBackPressed() { 168 saveAlarm(); 169 finish(); 170 } 171 onTimeSet(TimePicker view, int hourOfDay, int minute)172 public void onTimeSet(TimePicker view, int hourOfDay, int minute) { 173 mHour = hourOfDay; 174 mMinutes = minute; 175 updateTime(); 176 // If the time has been changed, enable the alarm. 177 mEnabled = true; 178 } 179 updateTime()180 private void updateTime() { 181 if (Log.LOGV) { 182 Log.v("updateTime " + mId); 183 } 184 mTimePref.setSummary(Alarms.formatTime(this, mHour, mMinutes, 185 mRepeatPref.getDaysOfWeek())); 186 } 187 saveAlarm()188 private void saveAlarm() { 189 final String alert = mAlarmPref.getAlertString(); 190 Alarms.setAlarm(this, mId, mEnabled, mHour, mMinutes, 191 mRepeatPref.getDaysOfWeek(), mVibratePref.isChecked(), 192 mLabel.getText(), alert); 193 194 if (mEnabled) { 195 popAlarmSetToast(this, mHour, mMinutes, 196 mRepeatPref.getDaysOfWeek()); 197 } 198 } 199 200 /** 201 * Write alarm out to persistent store and pops toast if alarm 202 * enabled 203 */ saveAlarm( Context context, int id, boolean enabled, int hour, int minute, Alarm.DaysOfWeek daysOfWeek, boolean vibrate, String label, String alert, boolean popToast)204 private static void saveAlarm( 205 Context context, int id, boolean enabled, int hour, int minute, 206 Alarm.DaysOfWeek daysOfWeek, boolean vibrate, String label, 207 String alert, boolean popToast) { 208 if (Log.LOGV) Log.v("** saveAlarm " + id + " " + label + " " + enabled 209 + " " + hour + " " + minute + " vibe " + vibrate); 210 211 // Fix alert string first 212 Alarms.setAlarm(context, id, enabled, hour, minute, daysOfWeek, vibrate, 213 label, alert); 214 215 if (enabled && popToast) { 216 popAlarmSetToast(context, hour, minute, daysOfWeek); 217 } 218 } 219 220 /** 221 * Display a toast that tells the user how long until the alarm 222 * goes off. This helps prevent "am/pm" mistakes. 223 */ popAlarmSetToast(Context context, int hour, int minute, Alarm.DaysOfWeek daysOfWeek)224 static void popAlarmSetToast(Context context, int hour, int minute, 225 Alarm.DaysOfWeek daysOfWeek) { 226 227 String toastText = formatToast(context, hour, minute, daysOfWeek); 228 Toast toast = Toast.makeText(context, toastText, Toast.LENGTH_LONG); 229 ToastMaster.setToast(toast); 230 toast.show(); 231 } 232 233 /** 234 * format "Alarm set for 2 days 7 hours and 53 minutes from 235 * now" 236 */ formatToast(Context context, int hour, int minute, Alarm.DaysOfWeek daysOfWeek)237 static String formatToast(Context context, int hour, int minute, 238 Alarm.DaysOfWeek daysOfWeek) { 239 long alarm = Alarms.calculateAlarm(hour, minute, 240 daysOfWeek).getTimeInMillis(); 241 long delta = alarm - System.currentTimeMillis();; 242 long hours = delta / (1000 * 60 * 60); 243 long minutes = delta / (1000 * 60) % 60; 244 long days = hours / 24; 245 hours = hours % 24; 246 247 String daySeq = (days == 0) ? "" : 248 (days == 1) ? context.getString(R.string.day) : 249 context.getString(R.string.days, Long.toString(days)); 250 251 String minSeq = (minutes == 0) ? "" : 252 (minutes == 1) ? context.getString(R.string.minute) : 253 context.getString(R.string.minutes, Long.toString(minutes)); 254 255 String hourSeq = (hours == 0) ? "" : 256 (hours == 1) ? context.getString(R.string.hour) : 257 context.getString(R.string.hours, Long.toString(hours)); 258 259 boolean dispDays = days > 0; 260 boolean dispHour = hours > 0; 261 boolean dispMinute = minutes > 0; 262 263 int index = (dispDays ? 1 : 0) | 264 (dispHour ? 2 : 0) | 265 (dispMinute ? 4 : 0); 266 267 String[] formats = context.getResources().getStringArray(R.array.alarm_set); 268 return String.format(formats[index], daySeq, hourSeq, minSeq); 269 } 270 onCreateOptionsMenu(Menu menu)271 public boolean onCreateOptionsMenu(Menu menu) { 272 super.onCreateOptionsMenu(menu); 273 274 mDeleteAlarmItem = menu.add(0, 0, 0, R.string.delete_alarm); 275 mDeleteAlarmItem.setIcon(android.R.drawable.ic_menu_delete); 276 277 if (AlarmClock.DEBUG) { 278 mTestAlarmItem = menu.add(0, 0, 0, "test alarm"); 279 } 280 281 return true; 282 } 283 onOptionsItemSelected(MenuItem item)284 public boolean onOptionsItemSelected(MenuItem item) { 285 if (item == mDeleteAlarmItem) { 286 Alarms.deleteAlarm(this, mId); 287 finish(); 288 return true; 289 } 290 if (AlarmClock.DEBUG) { 291 if (item == mTestAlarmItem) { 292 setTestAlarm(); 293 return true; 294 } 295 } 296 297 return false; 298 } 299 300 301 /** 302 * Test code: this is disabled for production build. Sets 303 * this alarm to go off on the next minute 304 */ setTestAlarm()305 void setTestAlarm() { 306 307 // start with now 308 java.util.Calendar c = java.util.Calendar.getInstance(); 309 c.setTimeInMillis(System.currentTimeMillis()); 310 311 int nowHour = c.get(java.util.Calendar.HOUR_OF_DAY); 312 int nowMinute = c.get(java.util.Calendar.MINUTE); 313 314 int minutes = (nowMinute + 1) % 60; 315 int hour = nowHour + (nowMinute == 0 ? 1 : 0); 316 317 saveAlarm(this, mId, true, hour, minutes, mRepeatPref.getDaysOfWeek(), 318 true, mLabel.getText(), mAlarmPref.getAlertString(), true); 319 } 320 321 } 322