SetAlarm.java revision c7edd6ea840e25cb04d090b6c29dc96c04d2be40
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.TimePickerDialog; 20import android.content.Context; 21import android.content.Intent; 22import android.media.RingtoneManager; 23import android.net.Uri; 24import android.os.Bundle; 25import android.preference.CheckBoxPreference; 26import android.preference.EditTextPreference; 27import android.preference.Preference; 28import android.preference.PreferenceActivity; 29import android.preference.PreferenceScreen; 30import android.text.format.DateFormat; 31import android.view.LayoutInflater; 32import android.view.Menu; 33import android.view.MenuItem; 34import android.view.View; 35import android.view.ViewGroup.LayoutParams; 36import android.widget.Button; 37import android.widget.FrameLayout; 38import android.widget.LinearLayout; 39import android.widget.ListView; 40import android.widget.TimePicker; 41import android.widget.Toast; 42 43/** 44 * Manages each alarm 45 */ 46public 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 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 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 167 public void onBackPressed() { 168 saveAlarm(); 169 finish(); 170 } 171 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 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 188 private void saveAlarm() { 189 final String alert = mAlarmPref.getAlertString(); 190 long time = Alarms.setAlarm(this, mId, mEnabled, mHour, mMinutes, 191 mRepeatPref.getDaysOfWeek(), mVibratePref.isChecked(), 192 mLabel.getText(), alert); 193 194 if (mEnabled) { 195 popAlarmSetToast(this, time); 196 } 197 } 198 199 /** 200 * Write alarm out to persistent store and pops toast if alarm 201 * enabled. 202 * Used only in test code. 203 */ 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 long time = Alarms.setAlarm(context, id, enabled, hour, minute, 213 daysOfWeek, vibrate, label, alert); 214 215 if (enabled && popToast) { 216 popAlarmSetToast(context, time); 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 */ 224 static void popAlarmSetToast(Context context, int hour, int minute, 225 Alarm.DaysOfWeek daysOfWeek) { 226 popAlarmSetToast(context, 227 Alarms.calculateAlarm(hour, minute, daysOfWeek) 228 .getTimeInMillis()); 229 } 230 231 private static void popAlarmSetToast(Context context, long timeInMillis) { 232 String toastText = formatToast(context, timeInMillis); 233 Toast toast = Toast.makeText(context, toastText, Toast.LENGTH_LONG); 234 ToastMaster.setToast(toast); 235 toast.show(); 236 } 237 238 /** 239 * format "Alarm set for 2 days 7 hours and 53 minutes from 240 * now" 241 */ 242 static String formatToast(Context context, long timeInMillis) { 243 long delta = timeInMillis - System.currentTimeMillis(); 244 long hours = delta / (1000 * 60 * 60); 245 long minutes = delta / (1000 * 60) % 60; 246 long days = hours / 24; 247 hours = hours % 24; 248 249 String daySeq = (days == 0) ? "" : 250 (days == 1) ? context.getString(R.string.day) : 251 context.getString(R.string.days, Long.toString(days)); 252 253 String minSeq = (minutes == 0) ? "" : 254 (minutes == 1) ? context.getString(R.string.minute) : 255 context.getString(R.string.minutes, Long.toString(minutes)); 256 257 String hourSeq = (hours == 0) ? "" : 258 (hours == 1) ? context.getString(R.string.hour) : 259 context.getString(R.string.hours, Long.toString(hours)); 260 261 boolean dispDays = days > 0; 262 boolean dispHour = hours > 0; 263 boolean dispMinute = minutes > 0; 264 265 int index = (dispDays ? 1 : 0) | 266 (dispHour ? 2 : 0) | 267 (dispMinute ? 4 : 0); 268 269 String[] formats = context.getResources().getStringArray(R.array.alarm_set); 270 return String.format(formats[index], daySeq, hourSeq, minSeq); 271 } 272 273 public boolean onCreateOptionsMenu(Menu menu) { 274 super.onCreateOptionsMenu(menu); 275 276 mDeleteAlarmItem = menu.add(0, 0, 0, R.string.delete_alarm); 277 mDeleteAlarmItem.setIcon(android.R.drawable.ic_menu_delete); 278 279 if (AlarmClock.DEBUG) { 280 mTestAlarmItem = menu.add(0, 0, 0, "test alarm"); 281 } 282 283 return true; 284 } 285 286 public boolean onOptionsItemSelected(MenuItem item) { 287 if (item == mDeleteAlarmItem) { 288 Alarms.deleteAlarm(this, mId); 289 finish(); 290 return true; 291 } 292 if (AlarmClock.DEBUG) { 293 if (item == mTestAlarmItem) { 294 setTestAlarm(); 295 return true; 296 } 297 } 298 299 return false; 300 } 301 302 303 /** 304 * Test code: this is disabled for production build. Sets 305 * this alarm to go off on the next minute 306 */ 307 void setTestAlarm() { 308 309 // start with now 310 java.util.Calendar c = java.util.Calendar.getInstance(); 311 c.setTimeInMillis(System.currentTimeMillis()); 312 313 int nowHour = c.get(java.util.Calendar.HOUR_OF_DAY); 314 int nowMinute = c.get(java.util.Calendar.MINUTE); 315 316 int minutes = (nowMinute + 1) % 60; 317 int hour = nowHour + (nowMinute == 0 ? 1 : 0); 318 319 saveAlarm(this, mId, true, hour, minutes, mRepeatPref.getDaysOfWeek(), 320 true, mLabel.getText(), mAlarmPref.getAlertString(), true); 321 } 322 323} 324