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 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 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 .setVisibility(Notification.VISIBILITY_PUBLIC) 77 .setLocalOnly(true); 78 79 // Setup up hide notification 80 Intent hideIntent = AlarmStateManager.createStateChangeIntent(context, 81 AlarmStateManager.ALARM_DELETE_TAG, instance, 82 AlarmInstance.HIDE_NOTIFICATION_STATE); 83 notification.setDeleteIntent(PendingIntent.getBroadcast(context, instance.hashCode(), 84 hideIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 85 86 // Setup up dismiss action 87 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 88 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.DISMISSED_STATE); 89 notification.addAction(R.drawable.ic_alarm_off_black, 90 resources.getString(R.string.alarm_alert_dismiss_now_text), 91 PendingIntent.getBroadcast(context, instance.hashCode(), 92 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 93 94 // Setup content action if instance is owned by alarm 95 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 96 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 97 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 98 99 nm.cancel(instance.hashCode()); 100 nm.notify(instance.hashCode(), notification.build()); 101 } 102 103 public static void showHighPriorityNotification(Context context, AlarmInstance instance) { 104 LogUtils.v("Displaying high priority notification for alarm instance: " + instance.mId); 105 NotificationManager nm = (NotificationManager) 106 context.getSystemService(Context.NOTIFICATION_SERVICE); 107 108 Resources resources = context.getResources(); 109 Notification.Builder notification = new Notification.Builder(context) 110 .setContentTitle(resources.getString(R.string.alarm_alert_predismiss_title)) 111 .setContentText(AlarmUtils.getAlarmText(context, instance)) 112 .setSmallIcon(R.drawable.stat_notify_alarm) 113 .setOngoing(true) 114 .setAutoCancel(false) 115 .setPriority(Notification.PRIORITY_HIGH) 116 .setCategory(Notification.CATEGORY_ALARM) 117 .setVisibility(Notification.VISIBILITY_PUBLIC) 118 .setLocalOnly(true); 119 120 // Setup up dismiss action 121 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 122 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.DISMISSED_STATE); 123 notification.addAction(R.drawable.ic_alarm_off_black, 124 resources.getString(R.string.alarm_alert_dismiss_now_text), 125 PendingIntent.getBroadcast(context, instance.hashCode(), 126 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 127 128 // Setup content action if instance is owned by alarm 129 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 130 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 131 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 132 133 nm.cancel(instance.hashCode()); 134 nm.notify(instance.hashCode(), notification.build()); 135 } 136 137 public static void showSnoozeNotification(Context context, AlarmInstance instance) { 138 LogUtils.v("Displaying snoozed notification for alarm instance: " + instance.mId); 139 NotificationManager nm = (NotificationManager) 140 context.getSystemService(Context.NOTIFICATION_SERVICE); 141 142 Resources resources = context.getResources(); 143 Notification.Builder notification = new Notification.Builder(context) 144 .setContentTitle(instance.getLabelOrDefault(context)) 145 .setContentText(resources.getString(R.string.alarm_alert_snooze_until, 146 AlarmUtils.getFormattedTime(context, instance.getAlarmTime()))) 147 .setSmallIcon(R.drawable.stat_notify_alarm) 148 .setOngoing(true) 149 .setAutoCancel(false) 150 .setPriority(Notification.PRIORITY_MAX) 151 .setCategory(Notification.CATEGORY_ALARM) 152 .setVisibility(Notification.VISIBILITY_PUBLIC) 153 .setLocalOnly(true); 154 155 // Setup up dismiss action 156 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 157 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.DISMISSED_STATE); 158 notification.addAction(R.drawable.ic_alarm_off_black, 159 resources.getString(R.string.alarm_alert_dismiss_text), 160 PendingIntent.getBroadcast(context, instance.hashCode(), 161 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 162 163 // Setup content action if instance is owned by alarm 164 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 165 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 166 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 167 nm.cancel(instance.hashCode()); 168 nm.notify(instance.hashCode(), notification.build()); 169 } 170 171 public static void showMissedNotification(Context context, AlarmInstance instance) { 172 LogUtils.v("Displaying missed notification for alarm instance: " + instance.mId); 173 NotificationManager nm = (NotificationManager) 174 context.getSystemService(Context.NOTIFICATION_SERVICE); 175 176 String label = instance.mLabel; 177 String alarmTime = AlarmUtils.getFormattedTime(context, instance.getAlarmTime()); 178 String contextText = instance.mLabel.isEmpty() ? alarmTime : 179 context.getString(R.string.alarm_missed_text, alarmTime, label); 180 Notification.Builder notification = new Notification.Builder(context) 181 .setContentTitle(context.getString(R.string.alarm_missed_title)) 182 .setContentText(contextText) 183 .setSmallIcon(R.drawable.stat_notify_alarm) 184 .setPriority(Notification.PRIORITY_HIGH) 185 .setCategory(Notification.CATEGORY_ALARM) 186 .setVisibility(Notification.VISIBILITY_PUBLIC) 187 .setLocalOnly(true); 188 189 // Setup dismiss intent 190 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 191 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.DISMISSED_STATE); 192 notification.setDeleteIntent(PendingIntent.getBroadcast(context, instance.hashCode(), 193 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 194 195 // Setup content intent 196 Intent showAndDismiss = AlarmInstance.createIntent(context, AlarmStateManager.class, 197 instance.mId); 198 showAndDismiss.setAction(AlarmStateManager.SHOW_AND_DISMISS_ALARM_ACTION); 199 notification.setContentIntent(PendingIntent.getBroadcast(context, instance.hashCode(), 200 showAndDismiss, PendingIntent.FLAG_UPDATE_CURRENT)); 201 202 nm.cancel(instance.hashCode()); 203 nm.notify(instance.hashCode(), notification.build()); 204 } 205 206 public static void showAlarmNotification(Context context, AlarmInstance instance) { 207 LogUtils.v("Displaying alarm notification for alarm instance: " + instance.mId); 208 NotificationManager nm = (NotificationManager) 209 context.getSystemService(Context.NOTIFICATION_SERVICE); 210 211 // Close dialogs and window shade, so this will display 212 context.sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)); 213 214 Resources resources = context.getResources(); 215 Notification.Builder notification = new Notification.Builder(context) 216 .setContentTitle(instance.getLabelOrDefault(context)) 217 .setContentText(AlarmUtils.getFormattedTime(context, instance.getAlarmTime())) 218 .setSmallIcon(R.drawable.stat_notify_alarm) 219 .setOngoing(true) 220 .setAutoCancel(false) 221 .setDefaults(Notification.DEFAULT_LIGHTS) 222 .setWhen(0) 223 .setCategory(Notification.CATEGORY_ALARM) 224 .setVisibility(Notification.VISIBILITY_PUBLIC) 225 .setLocalOnly(true); 226 227 // Setup Snooze Action 228 Intent snoozeIntent = AlarmStateManager.createStateChangeIntent(context, 229 AlarmStateManager.ALARM_SNOOZE_TAG, instance, AlarmInstance.SNOOZE_STATE); 230 PendingIntent snoozePendingIntent = PendingIntent.getBroadcast(context, instance.hashCode(), 231 snoozeIntent, 232 PendingIntent.FLAG_UPDATE_CURRENT); 233 notification.addAction(R.drawable.ic_snooze_black, 234 resources.getString(R.string.alarm_alert_snooze_text), snoozePendingIntent); 235 236 // Setup Dismiss Action 237 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 238 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.DISMISSED_STATE); 239 PendingIntent dismissPendingIntent = PendingIntent.getBroadcast(context, 240 instance.hashCode(), dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT); 241 notification.addAction(R.drawable.ic_alarm_off_black, 242 resources.getString(R.string.alarm_alert_dismiss_text), 243 dismissPendingIntent); 244 245 // Setup Content Action 246 Intent contentIntent = AlarmInstance.createIntent(context, AlarmActivity.class, 247 instance.mId); 248 notification.setContentIntent(PendingIntent.getActivity(context, 249 instance.hashCode(), contentIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 250 251 // Setup fullscreen intent 252 Intent fullScreenIntent = AlarmInstance.createIntent(context, AlarmActivity.class, 253 instance.mId); 254 // set action, so we can be different then content pending intent 255 fullScreenIntent.setAction("fullscreen_activity"); 256 fullScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 257 Intent.FLAG_ACTIVITY_NO_USER_ACTION); 258 notification.setFullScreenIntent(PendingIntent.getActivity(context, 259 instance.hashCode(), fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT), true); 260 notification.setPriority(Notification.PRIORITY_MAX); 261 262 nm.cancel(instance.hashCode()); 263 nm.notify(instance.hashCode(), notification.build()); 264 } 265 266 public static void clearNotification(Context context, AlarmInstance instance) { 267 LogUtils.v("Clearing notifications for alarm instance: " + instance.mId); 268 NotificationManager nm = (NotificationManager) 269 context.getSystemService(Context.NOTIFICATION_SERVICE); 270 nm.cancel(instance.hashCode()); 271 } 272 273 private static Intent createViewAlarmIntent(Context context, AlarmInstance instance) { 274 long alarmId = instance.mAlarmId == null ? Alarm.INVALID_ID : instance.mAlarmId; 275 Intent viewAlarmIntent = Alarm.createIntent(context, DeskClock.class, alarmId); 276 viewAlarmIntent.putExtra(DeskClock.SELECT_TAB_INTENT_EXTRA, DeskClock.ALARM_TAB_INDEX); 277 viewAlarmIntent.putExtra(AlarmClockFragment.SCROLL_TO_ALARM_INTENT_EXTRA, alarmId); 278 viewAlarmIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 279 return viewAlarmIntent; 280 } 281 } 282