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.deskclock; 18 19 import android.app.Activity; 20 import android.app.Notification; 21 import android.app.NotificationManager; 22 import android.app.PendingIntent; 23 import android.content.Context; 24 import android.content.BroadcastReceiver; 25 import android.content.Intent; 26 import android.content.IntentFilter; 27 import android.content.SharedPreferences; 28 import android.content.res.Configuration; 29 import android.os.Bundle; 30 import android.preference.PreferenceManager; 31 import android.view.KeyEvent; 32 import android.view.View; 33 import android.view.ViewGroup; 34 import android.view.LayoutInflater; 35 import android.view.Window; 36 import android.view.WindowManager; 37 import android.widget.Button; 38 import android.widget.Toast; 39 import android.widget.TextView; 40 41 import java.util.Calendar; 42 43 /** 44 * Alarm Clock alarm alert: pops visible indicator and plays alarm 45 * tone 46 */ 47 public class AlarmAlert extends Activity { 48 49 // These defaults must match the values in res/xml/settings.xml 50 private static final String DEFAULT_SNOOZE = "10"; 51 private static final String DEFAULT_VOLUME_BEHAVIOR = "2"; 52 53 private Alarm mAlarm; 54 private int mVolumeBehavior; 55 56 // Receives the ALARM_KILLED action from the AlarmKlaxon. 57 private BroadcastReceiver mReceiver = new BroadcastReceiver() { 58 @Override 59 public void onReceive(Context context, Intent intent) { 60 Alarm alarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA); 61 if (mAlarm.id == alarm.id) { 62 dismiss(true); 63 } 64 } 65 }; 66 67 @Override onCreate(Bundle icicle)68 protected void onCreate(Bundle icicle) { 69 super.onCreate(icicle); 70 71 mAlarm = getIntent().getParcelableExtra(Alarms.ALARM_INTENT_EXTRA); 72 73 // Get the volume/camera button behavior setting 74 final String vol = 75 PreferenceManager.getDefaultSharedPreferences(this) 76 .getString(SettingsActivity.KEY_VOLUME_BEHAVIOR, 77 DEFAULT_VOLUME_BEHAVIOR); 78 mVolumeBehavior = Integer.parseInt(vol); 79 80 requestWindowFeature(android.view.Window.FEATURE_NO_TITLE); 81 getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 82 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD 83 | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON 84 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON); 85 updateLayout(); 86 87 // Register to get the alarm killed intent. 88 registerReceiver(mReceiver, new IntentFilter(Alarms.ALARM_KILLED)); 89 } 90 setTitle()91 private void setTitle() { 92 String label = mAlarm.getLabelOrDefault(this); 93 TextView title = (TextView) findViewById(R.id.alertTitle); 94 title.setText(label); 95 } 96 97 // This method is overwritten in AlarmAlertFullScreen in order to show a 98 // full activity with the wallpaper as the background. inflateView(LayoutInflater inflater)99 protected View inflateView(LayoutInflater inflater) { 100 return inflater.inflate(R.layout.alarm_alert, null); 101 } 102 updateLayout()103 private void updateLayout() { 104 LayoutInflater inflater = LayoutInflater.from(this); 105 106 setContentView(inflateView(inflater)); 107 108 /* snooze behavior: pop a snooze confirmation view, kick alarm 109 manager. */ 110 Button snooze = (Button) findViewById(R.id.snooze); 111 snooze.requestFocus(); 112 snooze.setOnClickListener(new Button.OnClickListener() { 113 public void onClick(View v) { 114 snooze(); 115 } 116 }); 117 118 /* dismiss button: close notification */ 119 findViewById(R.id.dismiss).setOnClickListener( 120 new Button.OnClickListener() { 121 public void onClick(View v) { 122 dismiss(false); 123 } 124 }); 125 126 /* Set the title from the passed in alarm */ 127 setTitle(); 128 } 129 130 // Attempt to snooze this alert. snooze()131 private void snooze() { 132 final String snooze = 133 PreferenceManager.getDefaultSharedPreferences(this) 134 .getString(SettingsActivity.KEY_ALARM_SNOOZE, DEFAULT_SNOOZE); 135 int snoozeMinutes = Integer.parseInt(snooze); 136 137 final long snoozeTime = System.currentTimeMillis() 138 + (1000 * 60 * snoozeMinutes); 139 Alarms.saveSnoozeAlert(AlarmAlert.this, mAlarm.id, snoozeTime); 140 141 // Get the display time for the snooze and update the notification. 142 final Calendar c = Calendar.getInstance(); 143 c.setTimeInMillis(snoozeTime); 144 145 // Append (snoozed) to the label. 146 String label = mAlarm.getLabelOrDefault(this); 147 label = getString(R.string.alarm_notify_snooze_label, label); 148 149 // Notify the user that the alarm has been snoozed. 150 Intent cancelSnooze = new Intent(this, AlarmReceiver.class); 151 cancelSnooze.setAction(Alarms.CANCEL_SNOOZE); 152 cancelSnooze.putExtra(Alarms.ALARM_ID, mAlarm.id); 153 PendingIntent broadcast = 154 PendingIntent.getBroadcast(this, mAlarm.id, cancelSnooze, 0); 155 NotificationManager nm = getNotificationManager(); 156 Notification n = new Notification(R.drawable.stat_notify_alarm, 157 label, 0); 158 n.setLatestEventInfo(this, label, 159 getString(R.string.alarm_notify_snooze_text, 160 Alarms.formatTime(this, c)), broadcast); 161 n.flags |= Notification.FLAG_AUTO_CANCEL 162 | Notification.FLAG_ONGOING_EVENT; 163 nm.notify(mAlarm.id, n); 164 165 String displayTime = getString(R.string.alarm_alert_snooze_set, 166 snoozeMinutes); 167 // Intentionally log the snooze time for debugging. 168 Log.v(displayTime); 169 170 // Display the snooze minutes in a toast. 171 Toast.makeText(AlarmAlert.this, displayTime, Toast.LENGTH_LONG).show(); 172 stopService(new Intent(Alarms.ALARM_ALERT_ACTION)); 173 finish(); 174 } 175 getNotificationManager()176 private NotificationManager getNotificationManager() { 177 return (NotificationManager) getSystemService(NOTIFICATION_SERVICE); 178 } 179 180 // Dismiss the alarm. dismiss(boolean killed)181 private void dismiss(boolean killed) { 182 // The service told us that the alarm has been killed, do not modify 183 // the notification or stop the service. 184 if (!killed) { 185 // Cancel the notification and stop playing the alarm 186 NotificationManager nm = getNotificationManager(); 187 nm.cancel(mAlarm.id); 188 stopService(new Intent(Alarms.ALARM_ALERT_ACTION)); 189 } 190 finish(); 191 } 192 193 /** 194 * this is called when a second alarm is triggered while a 195 * previous alert window is still active. 196 */ 197 @Override onNewIntent(Intent intent)198 protected void onNewIntent(Intent intent) { 199 super.onNewIntent(intent); 200 201 if (Log.LOGV) Log.v("AlarmAlert.OnNewIntent()"); 202 203 mAlarm = intent.getParcelableExtra(Alarms.ALARM_INTENT_EXTRA); 204 205 setTitle(); 206 } 207 208 @Override onStop()209 protected void onStop() { 210 super.onStop(); 211 // Don't hang around. 212 finish(); 213 } 214 215 @Override onDestroy()216 public void onDestroy() { 217 super.onDestroy(); 218 if (Log.LOGV) Log.v("AlarmAlert.onDestroy()"); 219 // No longer care about the alarm being killed. 220 unregisterReceiver(mReceiver); 221 } 222 223 @Override dispatchKeyEvent(KeyEvent event)224 public boolean dispatchKeyEvent(KeyEvent event) { 225 // Do this on key down to handle a few of the system keys. 226 boolean up = event.getAction() == KeyEvent.ACTION_UP; 227 switch (event.getKeyCode()) { 228 // Volume keys and camera keys dismiss the alarm 229 case KeyEvent.KEYCODE_VOLUME_UP: 230 case KeyEvent.KEYCODE_VOLUME_DOWN: 231 case KeyEvent.KEYCODE_CAMERA: 232 case KeyEvent.KEYCODE_FOCUS: 233 if (up) { 234 switch (mVolumeBehavior) { 235 case 1: 236 snooze(); 237 break; 238 239 case 2: 240 dismiss(false); 241 break; 242 243 default: 244 break; 245 } 246 } 247 return true; 248 default: 249 break; 250 } 251 return super.dispatchKeyEvent(event); 252 } 253 } 254