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