1 /* 2 * Copyright (C) 2013 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 package com.android.deskclock.alarms; 17 18 import android.app.AlarmManager; 19 import android.app.Notification; 20 import android.app.NotificationManager; 21 import android.app.PendingIntent; 22 import android.content.Context; 23 import android.content.Intent; 24 import android.content.res.Resources; 25 26 import com.android.deskclock.AlarmClockFragment; 27 import com.android.deskclock.AlarmUtils; 28 import com.android.deskclock.DeskClock; 29 import com.android.deskclock.LogUtils; 30 import com.android.deskclock.R; 31 import com.android.deskclock.provider.Alarm; 32 import com.android.deskclock.provider.AlarmInstance; 33 34 public final class AlarmNotifications { 35 registerNextAlarmWithAlarmManager(Context context, AlarmInstance instance)36 public static void registerNextAlarmWithAlarmManager(Context context, AlarmInstance instance) { 37 // Sets a surrogate alarm with alarm manager that provides the AlarmClockInfo for the 38 // alarm that is going to fire next. The operation is constructed such that it is ignored 39 // by AlarmStateManager. 40 41 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 42 43 int flags = instance == null ? PendingIntent.FLAG_NO_CREATE : 0; 44 PendingIntent operation = PendingIntent.getBroadcast(context, 0 /* requestCode */, 45 AlarmStateManager.createIndicatorIntent(context), flags); 46 47 if (instance != null) { 48 long alarmTime = instance.getAlarmTime().getTimeInMillis(); 49 50 // Create an intent that can be used to show or edit details of the next alarm. 51 PendingIntent viewIntent = PendingIntent.getActivity(context, instance.hashCode(), 52 createViewAlarmIntent(context, instance), PendingIntent.FLAG_UPDATE_CURRENT); 53 54 AlarmManager.AlarmClockInfo info = 55 new AlarmManager.AlarmClockInfo(alarmTime, viewIntent); 56 alarmManager.setAlarmClock(info, operation); 57 } else if (operation != null) { 58 alarmManager.cancel(operation); 59 } 60 } 61 showLowPriorityNotification(Context context, AlarmInstance instance)62 public static void showLowPriorityNotification(Context context, AlarmInstance instance) { 63 LogUtils.v("Displaying low priority notification for alarm instance: " + instance.mId); 64 NotificationManager nm = (NotificationManager) 65 context.getSystemService(Context.NOTIFICATION_SERVICE); 66 67 Resources resources = context.getResources(); 68 Notification.Builder notification = new Notification.Builder(context) 69 .setContentTitle(resources.getString(R.string.alarm_alert_predismiss_title)) 70 .setContentText(AlarmUtils.getAlarmText(context, instance)) 71 .setSmallIcon(R.drawable.stat_notify_alarm) 72 .setOngoing(false) 73 .setAutoCancel(false) 74 .setPriority(Notification.PRIORITY_DEFAULT) 75 .setCategory(Notification.CATEGORY_ALARM); 76 77 // Setup up hide notification 78 Intent hideIntent = AlarmStateManager.createStateChangeIntent(context, "DELETE_TAG", 79 instance, AlarmInstance.HIDE_NOTIFICATION_STATE); 80 notification.setDeleteIntent(PendingIntent.getBroadcast(context, instance.hashCode(), 81 hideIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 82 83 // Setup up dismiss action 84 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, "DISMISS_TAG", 85 instance, AlarmInstance.DISMISSED_STATE); 86 notification.addAction(R.drawable.ic_alarm_off_black, 87 resources.getString(R.string.alarm_alert_dismiss_now_text), 88 PendingIntent.getBroadcast(context, instance.hashCode(), 89 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 90 91 // Setup content action if instance is owned by alarm 92 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 93 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 94 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 95 96 nm.cancel(instance.hashCode()); 97 nm.notify(instance.hashCode(), notification.build()); 98 } 99 showHighPriorityNotification(Context context, AlarmInstance instance)100 public static void showHighPriorityNotification(Context context, AlarmInstance instance) { 101 LogUtils.v("Displaying high priority notification for alarm instance: " + instance.mId); 102 NotificationManager nm = (NotificationManager) 103 context.getSystemService(Context.NOTIFICATION_SERVICE); 104 105 Resources resources = context.getResources(); 106 Notification.Builder notification = new Notification.Builder(context) 107 .setContentTitle(resources.getString(R.string.alarm_alert_predismiss_title)) 108 .setContentText(AlarmUtils.getAlarmText(context, instance)) 109 .setSmallIcon(R.drawable.stat_notify_alarm) 110 .setOngoing(true) 111 .setAutoCancel(false) 112 .setPriority(Notification.PRIORITY_HIGH) 113 .setCategory(Notification.CATEGORY_ALARM); 114 115 // Setup up dismiss action 116 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, "DISMISS_TAG", 117 instance, AlarmInstance.DISMISSED_STATE); 118 notification.addAction(R.drawable.ic_alarm_off_black, 119 resources.getString(R.string.alarm_alert_dismiss_now_text), 120 PendingIntent.getBroadcast(context, instance.hashCode(), 121 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 122 123 // Setup content action if instance is owned by alarm 124 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 125 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 126 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 127 128 nm.cancel(instance.hashCode()); 129 nm.notify(instance.hashCode(), notification.build()); 130 } 131 showSnoozeNotification(Context context, AlarmInstance instance)132 public static void showSnoozeNotification(Context context, AlarmInstance instance) { 133 LogUtils.v("Displaying snoozed notification for alarm instance: " + instance.mId); 134 NotificationManager nm = (NotificationManager) 135 context.getSystemService(Context.NOTIFICATION_SERVICE); 136 137 Resources resources = context.getResources(); 138 Notification.Builder notification = new Notification.Builder(context) 139 .setContentTitle(instance.getLabelOrDefault(context)) 140 .setContentText(resources.getString(R.string.alarm_alert_snooze_until, 141 AlarmUtils.getFormattedTime(context, instance.getAlarmTime()))) 142 .setSmallIcon(R.drawable.stat_notify_alarm) 143 .setOngoing(true) 144 .setAutoCancel(false) 145 .setPriority(Notification.PRIORITY_MAX) 146 .setCategory(Notification.CATEGORY_ALARM); 147 148 // Setup up dismiss action 149 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, "DISMISS_TAG", 150 instance, AlarmInstance.DISMISSED_STATE); 151 notification.addAction(R.drawable.ic_alarm_off_black, 152 resources.getString(R.string.alarm_alert_dismiss_text), 153 PendingIntent.getBroadcast(context, instance.hashCode(), 154 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 155 156 // Setup content action if instance is owned by alarm 157 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 158 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 159 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 160 nm.cancel(instance.hashCode()); 161 nm.notify(instance.hashCode(), notification.build()); 162 } 163 showMissedNotification(Context context, AlarmInstance instance)164 public static void showMissedNotification(Context context, AlarmInstance instance) { 165 LogUtils.v("Displaying missed notification for alarm instance: " + instance.mId); 166 NotificationManager nm = (NotificationManager) 167 context.getSystemService(Context.NOTIFICATION_SERVICE); 168 169 String label = instance.mLabel; 170 String alarmTime = AlarmUtils.getFormattedTime(context, instance.getAlarmTime()); 171 String contextText = instance.mLabel.isEmpty() ? alarmTime : 172 context.getString(R.string.alarm_missed_text, alarmTime, label); 173 Notification.Builder notification = new Notification.Builder(context) 174 .setContentTitle(context.getString(R.string.alarm_missed_title)) 175 .setContentText(contextText) 176 .setSmallIcon(R.drawable.stat_notify_alarm) 177 .setPriority(Notification.PRIORITY_HIGH) 178 .setCategory(Notification.CATEGORY_ALARM); 179 180 // Setup dismiss intent 181 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, "DISMISS_TAG", 182 instance, AlarmInstance.DISMISSED_STATE); 183 notification.setDeleteIntent(PendingIntent.getBroadcast(context, instance.hashCode(), 184 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 185 186 // Setup content intent 187 Intent showAndDismiss = AlarmInstance.createIntent(context, AlarmStateManager.class, 188 instance.mId); 189 showAndDismiss.setAction(AlarmStateManager.SHOW_AND_DISMISS_ALARM_ACTION); 190 notification.setContentIntent(PendingIntent.getBroadcast(context, instance.hashCode(), 191 showAndDismiss, PendingIntent.FLAG_UPDATE_CURRENT)); 192 193 nm.cancel(instance.hashCode()); 194 nm.notify(instance.hashCode(), notification.build()); 195 } 196 showAlarmNotification(Context context, AlarmInstance instance)197 public static void showAlarmNotification(Context context, AlarmInstance instance) { 198 LogUtils.v("Displaying alarm notification for alarm instance: " + instance.mId); 199 NotificationManager nm = (NotificationManager) 200 context.getSystemService(Context.NOTIFICATION_SERVICE); 201 202 // Close dialogs and window shade, so this will display 203 context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); 204 205 Resources resources = context.getResources(); 206 Notification.Builder notification = new Notification.Builder(context) 207 .setContentTitle(instance.getLabelOrDefault(context)) 208 .setContentText(AlarmUtils.getFormattedTime(context, instance.getAlarmTime())) 209 .setSmallIcon(R.drawable.stat_notify_alarm) 210 .setOngoing(true) 211 .setAutoCancel(false) 212 .setDefaults(Notification.DEFAULT_LIGHTS) 213 .setWhen(0) 214 .setCategory(Notification.CATEGORY_ALARM); 215 216 // Setup Snooze Action 217 Intent snoozeIntent = AlarmStateManager.createStateChangeIntent(context, "SNOOZE_TAG", 218 instance, AlarmInstance.SNOOZE_STATE); 219 PendingIntent snoozePendingIntent = PendingIntent.getBroadcast(context, instance.hashCode(), 220 snoozeIntent, 221 PendingIntent.FLAG_UPDATE_CURRENT); 222 notification.addAction(R.drawable.ic_snooze_black, 223 resources.getString(R.string.alarm_alert_snooze_text), snoozePendingIntent); 224 225 // Setup Dismiss Action 226 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, "DISMISS_TAG", 227 instance, AlarmInstance.DISMISSED_STATE); 228 PendingIntent dismissPendingIntent = PendingIntent.getBroadcast(context, 229 instance.hashCode(), dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT); 230 notification.addAction(R.drawable.ic_alarm_off_black, 231 resources.getString(R.string.alarm_alert_dismiss_text), 232 dismissPendingIntent); 233 234 // Setup Content Action 235 Intent contentIntent = AlarmInstance.createIntent(context, AlarmActivity.class, 236 instance.mId); 237 notification.setContentIntent(PendingIntent.getActivity(context, 238 instance.hashCode(), contentIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 239 240 // Setup fullscreen intent 241 Intent fullScreenIntent = AlarmInstance.createIntent(context, AlarmActivity.class, 242 instance.mId); 243 // set action, so we can be different then content pending intent 244 fullScreenIntent.setAction("fullscreen_activity"); 245 fullScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 246 Intent.FLAG_ACTIVITY_NO_USER_ACTION); 247 notification.setFullScreenIntent(PendingIntent.getActivity(context, 248 instance.hashCode(), fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT), true); 249 notification.setPriority(Notification.PRIORITY_MAX); 250 251 nm.cancel(instance.hashCode()); 252 nm.notify(instance.hashCode(), notification.build()); 253 } 254 clearNotification(Context context, AlarmInstance instance)255 public static void clearNotification(Context context, AlarmInstance instance) { 256 LogUtils.v("Clearing notifications for alarm instance: " + instance.mId); 257 NotificationManager nm = (NotificationManager) 258 context.getSystemService(Context.NOTIFICATION_SERVICE); 259 nm.cancel(instance.hashCode()); 260 } 261 createViewAlarmIntent(Context context, AlarmInstance instance)262 private static Intent createViewAlarmIntent(Context context, AlarmInstance instance) { 263 long alarmId = instance.mAlarmId == null ? Alarm.INVALID_ID : instance.mAlarmId; 264 Intent viewAlarmIntent = Alarm.createIntent(context, DeskClock.class, alarmId); 265 viewAlarmIntent.putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.ALARM_TAB_INDEX); 266 viewAlarmIntent.putExtra(AlarmClockFragment.SCROLL_TO_ALARM_INTENT_EXTRA, alarmId); 267 viewAlarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 268 return viewAlarmIntent; 269 } 270 } 271