1 /* 2 * Copyright (C) 2010 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; 18 19 import android.app.Activity; 20 import android.content.ContentResolver; 21 import android.content.Intent; 22 import android.content.SharedPreferences; 23 import android.media.RingtoneManager; 24 import android.net.Uri; 25 import android.os.Bundle; 26 import android.preference.PreferenceManager; 27 import android.text.TextUtils; 28 29 import com.android.deskclock.alarms.AlarmStateManager; 30 import com.android.deskclock.provider.Alarm; 31 import com.android.deskclock.provider.AlarmInstance; 32 import com.android.deskclock.provider.DaysOfWeek; 33 import com.android.deskclock.timer.TimerFragment; 34 import com.android.deskclock.timer.TimerObj; 35 import com.android.deskclock.timer.Timers; 36 37 import java.util.ArrayList; 38 import java.util.Calendar; 39 import java.util.List; 40 41 import static android.provider.AlarmClock.ACTION_SET_ALARM; 42 import static android.provider.AlarmClock.ACTION_SET_TIMER; 43 import static android.provider.AlarmClock.ACTION_SHOW_ALARMS; 44 import static android.provider.AlarmClock.EXTRA_DAYS; 45 import static android.provider.AlarmClock.EXTRA_HOUR; 46 import static android.provider.AlarmClock.EXTRA_LENGTH; 47 import static android.provider.AlarmClock.EXTRA_MESSAGE; 48 import static android.provider.AlarmClock.EXTRA_MINUTES; 49 import static android.provider.AlarmClock.EXTRA_RINGTONE; 50 import static android.provider.AlarmClock.EXTRA_SKIP_UI; 51 import static android.provider.AlarmClock.EXTRA_VIBRATE; 52 import static android.provider.AlarmClock.VALUE_RINGTONE_SILENT; 53 54 public class HandleApiCalls extends Activity { 55 56 public static final long TIMER_MIN_LENGTH = 1000; 57 public static final long TIMER_MAX_LENGTH = 24 * 60 * 60 * 1000; 58 59 @Override onCreate(Bundle icicle)60 protected void onCreate(Bundle icicle) { 61 try { 62 super.onCreate(icicle); 63 Intent intent = getIntent(); 64 if (intent != null) { 65 if (ACTION_SET_ALARM.equals(intent.getAction())) { 66 handleSetAlarm(intent); 67 } else if (ACTION_SHOW_ALARMS.equals(intent.getAction())) { 68 handleShowAlarms(); 69 } else if (ACTION_SET_TIMER.equals(intent.getAction())) { 70 handleSetTimer(intent); 71 } 72 } 73 } finally { 74 finish(); 75 } 76 } 77 78 /*** 79 * Processes the SET_ALARM intent 80 * @param intent 81 */ handleSetAlarm(Intent intent)82 private void handleSetAlarm(Intent intent) { 83 // If not provided or invalid, show UI 84 final int hour = intent.getIntExtra(EXTRA_HOUR, -1); 85 86 // If not provided, use zero. If it is provided, make sure it's valid, otherwise, show UI 87 final int minutes; 88 if (intent.hasExtra(EXTRA_MINUTES)) { 89 minutes = intent.getIntExtra(EXTRA_MINUTES, -1); 90 } else { 91 minutes = 0; 92 } 93 if (hour < 0 || hour > 23 || minutes < 0 || minutes > 59) { 94 // Intent has no time or an invalid time, open the alarm creation UI 95 Intent createAlarm = Alarm.createIntent(this, DeskClock.class, Alarm.INVALID_ID); 96 createAlarm.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 97 createAlarm.putExtra(AlarmClockFragment.ALARM_CREATE_NEW_INTENT_EXTRA, true); 98 createAlarm.putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.ALARM_TAB_INDEX); 99 startActivity(createAlarm); 100 finish(); 101 return; 102 } 103 104 final boolean skipUi = intent.getBooleanExtra(EXTRA_SKIP_UI, false); 105 106 final StringBuilder selection = new StringBuilder(); 107 final List<String> args = new ArrayList<String>(); 108 setSelectionFromIntent(intent, hour, minutes, selection, args); 109 110 // Check if the alarm already exists and handle it 111 final ContentResolver cr = getContentResolver(); 112 final List<Alarm> alarms = Alarm.getAlarms(cr, 113 selection.toString(), 114 args.toArray(new String[args.size()])); 115 if (!alarms.isEmpty()) { 116 Alarm alarm = alarms.get(0); 117 alarm.enabled = true; 118 Alarm.updateAlarm(cr, alarm); 119 120 // Delete all old instances and create a new one with updated values 121 AlarmStateManager.deleteAllInstances(this, alarm.id); 122 setupInstance(alarm.createInstanceAfter(Calendar.getInstance()), skipUi); 123 finish(); 124 return; 125 } 126 127 // Otherwise insert it and handle it 128 final String message = getMessageFromIntent(intent); 129 final DaysOfWeek daysOfWeek = getDaysFromIntent(intent); 130 final boolean vibrate = intent.getBooleanExtra(EXTRA_VIBRATE, false); 131 final String alert = intent.getStringExtra(EXTRA_RINGTONE); 132 133 Alarm alarm = new Alarm(hour, minutes); 134 alarm.enabled = true; 135 alarm.label = message; 136 alarm.daysOfWeek = daysOfWeek; 137 alarm.vibrate = vibrate; 138 139 if (alert == null) { 140 alarm.alert = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM); 141 } else if (VALUE_RINGTONE_SILENT.equals(alert) || alert.isEmpty()) { 142 alarm.alert = Alarm.NO_RINGTONE_URI; 143 } else { 144 alarm.alert = Uri.parse(alert); 145 } 146 alarm.deleteAfterUse = !daysOfWeek.isRepeating() && skipUi; 147 148 alarm = Alarm.addAlarm(cr, alarm); 149 setupInstance(alarm.createInstanceAfter(Calendar.getInstance()), skipUi); 150 finish(); 151 } 152 handleShowAlarms()153 private void handleShowAlarms() { 154 startActivity(new Intent(this, DeskClock.class) 155 .putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.ALARM_TAB_INDEX)); 156 } 157 handleSetTimer(Intent intent)158 private void handleSetTimer(Intent intent) { 159 final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); 160 // If no length is supplied , show the timer setup view 161 if (!intent.hasExtra(EXTRA_LENGTH)) { 162 startActivity(new Intent(this, DeskClock.class) 163 .putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.TIMER_TAB_INDEX) 164 .putExtra(TimerFragment.GOTO_SETUP_VIEW, true)); 165 return; 166 } 167 168 final long length = 1000l * intent.getIntExtra(EXTRA_LENGTH, 0); 169 if (length < TIMER_MIN_LENGTH || length > TIMER_MAX_LENGTH) { 170 Log.i("Invalid timer length requested: " + length); 171 return; 172 } 173 String label = getMessageFromIntent(intent); 174 175 TimerObj timer = null; 176 // Find an existing matching time 177 final ArrayList<TimerObj> timers = new ArrayList<TimerObj>(); 178 TimerObj.getTimersFromSharedPrefs(prefs, timers); 179 for (TimerObj t : timers) { 180 if (t.mSetupLength == length && (TextUtils.equals(label, t.mLabel)) 181 && t.mState == TimerObj.STATE_RESTART) { 182 timer = t; 183 break; 184 } 185 } 186 187 boolean skipUi = intent.getBooleanExtra(EXTRA_SKIP_UI, false); 188 if (timer == null) { 189 // Use a new timer 190 timer = new TimerObj(length, label); 191 // Timers set without presenting UI to the user will be deleted after use 192 timer.mDeleteAfterUse = skipUi; 193 } 194 195 timer.mState = TimerObj.STATE_RUNNING; 196 timer.mStartTime = Utils.getTimeNow(); 197 timer.writeToSharedPref(prefs); 198 199 // Tell TimerReceiver that the timer was started 200 sendBroadcast(new Intent().setAction(Timers.START_TIMER) 201 .putExtra(Timers.TIMER_INTENT_EXTRA, timer.mTimerId)); 202 203 if (skipUi) { 204 Utils.showInUseNotifications(this); 205 } else { 206 startActivity(new Intent(this, DeskClock.class) 207 .putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.TIMER_TAB_INDEX)); 208 } 209 } 210 setupInstance(AlarmInstance instance, boolean skipUi)211 private void setupInstance(AlarmInstance instance, boolean skipUi) { 212 instance = AlarmInstance.addInstance(this.getContentResolver(), instance); 213 AlarmStateManager.registerInstance(this, instance, true); 214 AlarmUtils.popAlarmSetToast(this, instance.getAlarmTime().getTimeInMillis()); 215 if (!skipUi) { 216 Intent showAlarm = Alarm.createIntent(this, DeskClock.class, instance.mAlarmId); 217 showAlarm.putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.ALARM_TAB_INDEX); 218 showAlarm.putExtra(AlarmClockFragment.SCROLL_TO_ALARM_INTENT_EXTRA, instance.mAlarmId); 219 showAlarm.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 220 startActivity(showAlarm); 221 } 222 } 223 getMessageFromIntent(Intent intent)224 private String getMessageFromIntent(Intent intent) { 225 final String message = intent.getStringExtra(EXTRA_MESSAGE); 226 return message == null ? "" : message; 227 } 228 getDaysFromIntent(Intent intent)229 private DaysOfWeek getDaysFromIntent(Intent intent) { 230 final DaysOfWeek daysOfWeek = new DaysOfWeek(0); 231 final ArrayList<Integer> days = intent.getIntegerArrayListExtra(EXTRA_DAYS); 232 if (days != null) { 233 final int[] daysArray = new int[days.size()]; 234 for (int i = 0; i < days.size(); i++) { 235 daysArray[i] = days.get(i); 236 } 237 daysOfWeek.setDaysOfWeek(true, daysArray); 238 } else { 239 // API says to use an ArrayList<Integer> but we allow the user to use a int[] too. 240 final int[] daysArray = intent.getIntArrayExtra(EXTRA_DAYS); 241 if (daysArray != null) { 242 daysOfWeek.setDaysOfWeek(true, daysArray); 243 } 244 } 245 return daysOfWeek; 246 } 247 setSelectionFromIntent( Intent intent, int hour, int minutes, StringBuilder selection, List<String> args)248 private void setSelectionFromIntent( 249 Intent intent, 250 int hour, 251 int minutes, 252 StringBuilder selection, 253 List<String> args) { 254 selection.append(Alarm.HOUR).append("=?"); 255 args.add(String.valueOf(hour)); 256 selection.append(" AND ").append(Alarm.MINUTES).append("=?"); 257 args.add(String.valueOf(minutes)); 258 259 if (intent.hasExtra(EXTRA_MESSAGE)) { 260 selection.append(" AND ").append(Alarm.LABEL).append("=?"); 261 args.add(getMessageFromIntent(intent)); 262 } 263 264 // Days is treated differently that other fields because if days is not specified, it 265 // explicitly means "not recurring". 266 selection.append(" AND ").append(Alarm.DAYS_OF_WEEK).append("=?"); 267 args.add(String.valueOf(intent.hasExtra(EXTRA_DAYS) 268 ? getDaysFromIntent(intent).getBitSet() : DaysOfWeek.NO_DAYS_SET)); 269 270 if (intent.hasExtra(EXTRA_VIBRATE)) { 271 selection.append(" AND ").append(Alarm.VIBRATE).append("=?"); 272 args.add(intent.getBooleanExtra(EXTRA_VIBRATE, false) ? "1" : "0"); 273 } 274 275 if (intent.hasExtra(EXTRA_RINGTONE)) { 276 selection.append(" AND ").append(Alarm.RINGTONE).append("=?"); 277 278 String ringTone = intent.getStringExtra(EXTRA_RINGTONE); 279 if (ringTone == null) { 280 // If the intent explicitly specified a NULL ringtone, treat it as the default 281 // ringtone. 282 ringTone = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM).toString(); 283 } else if (VALUE_RINGTONE_SILENT.equals(ringTone) || ringTone.isEmpty()) { 284 ringTone = Alarm.NO_RINGTONE; 285 } 286 args.add(ringTone); 287 } 288 } 289 } 290