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.PendingIntent; 19 import android.app.Service; 20 import android.content.Context; 21 import android.content.Intent; 22 import android.content.res.Resources; 23 import android.support.v4.app.NotificationCompat; 24 import android.support.v4.app.NotificationManagerCompat; 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 public static final String EXTRA_NOTIFICATION_ID = "extra_notification_id"; 36 showLowPriorityNotification(Context context, AlarmInstance instance)37 public static void showLowPriorityNotification(Context context, AlarmInstance instance) { 38 LogUtils.v("Displaying low priority notification for alarm instance: " + instance.mId); 39 40 NotificationCompat.Builder notification = new NotificationCompat.Builder(context) 41 .setContentTitle(context.getString( 42 R.string.alarm_alert_predismiss_title)) 43 .setContentText(AlarmUtils.getAlarmText(context, instance, 44 true /* includeLabel */)) 45 .setSmallIcon(R.drawable.stat_notify_alarm) 46 .setAutoCancel(false) 47 .setPriority(NotificationCompat.PRIORITY_DEFAULT) 48 .setCategory(NotificationCompat.CATEGORY_ALARM) 49 .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) 50 .setLocalOnly(true); 51 52 // Setup up hide notification 53 Intent hideIntent = AlarmStateManager.createStateChangeIntent(context, 54 AlarmStateManager.ALARM_DELETE_TAG, instance, 55 AlarmInstance.HIDE_NOTIFICATION_STATE); 56 notification.setDeleteIntent(PendingIntent.getService(context, instance.hashCode(), 57 hideIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 58 59 // Setup up dismiss action 60 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 61 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.PREDISMISSED_STATE); 62 notification.addAction(R.drawable.ic_alarm_off_24dp, 63 context.getString(R.string.alarm_alert_dismiss_now_text), 64 PendingIntent.getService(context, instance.hashCode(), 65 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 66 67 // Setup content action if instance is owned by alarm 68 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 69 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 70 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 71 72 NotificationManagerCompat nm = NotificationManagerCompat.from(context); 73 nm.notify(instance.hashCode(), notification.build()); 74 } 75 showHighPriorityNotification(Context context, AlarmInstance instance)76 public static void showHighPriorityNotification(Context context, AlarmInstance instance) { 77 LogUtils.v("Displaying high priority notification for alarm instance: " + instance.mId); 78 79 NotificationCompat.Builder notification = new NotificationCompat.Builder(context) 80 .setContentTitle(context.getString(R.string.alarm_alert_predismiss_title)) 81 .setContentText(AlarmUtils.getAlarmText(context, instance, 82 true /* includeLabel */)) 83 .setSmallIcon(R.drawable.stat_notify_alarm) 84 .setAutoCancel(false) 85 .setOngoing(true) 86 .setGroup(Integer.toString(instance.hashCode())) 87 .setGroupSummary(true) 88 .setPriority(NotificationCompat.PRIORITY_HIGH) 89 .setCategory(NotificationCompat.CATEGORY_ALARM) 90 .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) 91 .setLocalOnly(true); 92 93 // Setup up dismiss action 94 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 95 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.PREDISMISSED_STATE); 96 notification.addAction(R.drawable.ic_alarm_off_24dp, 97 context.getString(R.string.alarm_alert_dismiss_now_text), 98 PendingIntent.getService(context, instance.hashCode(), 99 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 100 101 // Setup content action if instance is owned by alarm 102 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 103 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 104 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 105 106 NotificationManagerCompat nm = NotificationManagerCompat.from(context); 107 nm.notify(instance.hashCode(), notification.build()); 108 } 109 showSnoozeNotification(Context context, AlarmInstance instance)110 public static void showSnoozeNotification(Context context, AlarmInstance instance) { 111 LogUtils.v("Displaying snoozed notification for alarm instance: " + instance.mId); 112 113 NotificationCompat.Builder notification = new NotificationCompat.Builder(context) 114 .setContentTitle(instance.getLabelOrDefault(context)) 115 .setContentText(context.getString(R.string.alarm_alert_snooze_until, 116 AlarmUtils.getFormattedTime(context, instance.getAlarmTime()))) 117 .setSmallIcon(R.drawable.stat_notify_alarm) 118 .setAutoCancel(false) 119 .setOngoing(true) 120 .setPriority(NotificationCompat.PRIORITY_MAX) 121 .setCategory(NotificationCompat.CATEGORY_ALARM) 122 .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) 123 .setLocalOnly(true); 124 125 // Setup up dismiss action 126 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 127 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.DISMISSED_STATE); 128 notification.addAction(R.drawable.ic_alarm_off_24dp, 129 context.getString(R.string.alarm_alert_dismiss_text), 130 PendingIntent.getService(context, instance.hashCode(), 131 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 132 133 // Setup content action if instance is owned by alarm 134 Intent viewAlarmIntent = createViewAlarmIntent(context, instance); 135 notification.setContentIntent(PendingIntent.getActivity(context, instance.hashCode(), 136 viewAlarmIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 137 138 NotificationManagerCompat nm = NotificationManagerCompat.from(context); 139 nm.notify(instance.hashCode(), notification.build()); 140 } 141 showMissedNotification(Context context, AlarmInstance instance)142 public static void showMissedNotification(Context context, AlarmInstance instance) { 143 LogUtils.v("Displaying missed notification for alarm instance: " + instance.mId); 144 145 String label = instance.mLabel; 146 String alarmTime = AlarmUtils.getFormattedTime(context, instance.getAlarmTime()); 147 NotificationCompat.Builder notification = new NotificationCompat.Builder(context) 148 .setContentTitle(context.getString(R.string.alarm_missed_title)) 149 .setContentText(instance.mLabel.isEmpty() ? alarmTime : 150 context.getString(R.string.alarm_missed_text, alarmTime, label)) 151 .setSmallIcon(R.drawable.stat_notify_alarm) 152 .setPriority(NotificationCompat.PRIORITY_HIGH) 153 .setCategory(NotificationCompat.CATEGORY_ALARM) 154 .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) 155 .setLocalOnly(true); 156 157 final int hashCode = instance.hashCode(); 158 159 // Setup dismiss intent 160 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(context, 161 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.DISMISSED_STATE); 162 notification.setDeleteIntent(PendingIntent.getService(context, hashCode, 163 dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 164 165 // Setup content intent 166 Intent showAndDismiss = AlarmInstance.createIntent(context, AlarmStateManager.class, 167 instance.mId); 168 showAndDismiss.putExtra(EXTRA_NOTIFICATION_ID, hashCode); 169 showAndDismiss.setAction(AlarmStateManager.SHOW_AND_DISMISS_ALARM_ACTION); 170 notification.setContentIntent(PendingIntent.getBroadcast(context, hashCode, 171 showAndDismiss, PendingIntent.FLAG_UPDATE_CURRENT)); 172 173 NotificationManagerCompat nm = NotificationManagerCompat.from(context); 174 nm.notify(hashCode, notification.build()); 175 } 176 showAlarmNotification(Service service, AlarmInstance instance)177 public static void showAlarmNotification(Service service, AlarmInstance instance) { 178 LogUtils.v("Displaying alarm notification for alarm instance: " + instance.mId); 179 180 Resources resources = service.getResources(); 181 NotificationCompat.Builder notification = new NotificationCompat.Builder(service) 182 .setContentTitle(instance.getLabelOrDefault(service)) 183 .setContentText(AlarmUtils.getFormattedTime(service, instance.getAlarmTime())) 184 .setSmallIcon(R.drawable.stat_notify_alarm) 185 .setOngoing(true) 186 .setAutoCancel(false) 187 .setDefaults(NotificationCompat.DEFAULT_LIGHTS) 188 .setWhen(0) 189 .setCategory(NotificationCompat.CATEGORY_ALARM) 190 .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) 191 .setLocalOnly(true); 192 193 // Setup Snooze Action 194 Intent snoozeIntent = AlarmStateManager.createStateChangeIntent(service, 195 AlarmStateManager.ALARM_SNOOZE_TAG, instance, AlarmInstance.SNOOZE_STATE); 196 snoozeIntent.putExtra(AlarmStateManager.FROM_NOTIFICATION_EXTRA, true); 197 PendingIntent snoozePendingIntent = PendingIntent.getService(service, instance.hashCode(), 198 snoozeIntent, 199 PendingIntent.FLAG_UPDATE_CURRENT); 200 notification.addAction(R.drawable.ic_snooze_24dp, 201 resources.getString(R.string.alarm_alert_snooze_text), snoozePendingIntent); 202 203 // Setup Dismiss Action 204 Intent dismissIntent = AlarmStateManager.createStateChangeIntent(service, 205 AlarmStateManager.ALARM_DISMISS_TAG, instance, AlarmInstance.DISMISSED_STATE); 206 dismissIntent.putExtra(AlarmStateManager.FROM_NOTIFICATION_EXTRA, true); 207 PendingIntent dismissPendingIntent = PendingIntent.getService(service, 208 instance.hashCode(), dismissIntent, PendingIntent.FLAG_UPDATE_CURRENT); 209 notification.addAction(R.drawable.ic_alarm_off_24dp, 210 resources.getString(R.string.alarm_alert_dismiss_text), 211 dismissPendingIntent); 212 213 // Setup Content Action 214 Intent contentIntent = AlarmInstance.createIntent(service, AlarmActivity.class, 215 instance.mId); 216 notification.setContentIntent(PendingIntent.getActivity(service, 217 instance.hashCode(), contentIntent, PendingIntent.FLAG_UPDATE_CURRENT)); 218 219 // Setup fullscreen intent 220 Intent fullScreenIntent = AlarmInstance.createIntent(service, AlarmActivity.class, 221 instance.mId); 222 // set action, so we can be different then content pending intent 223 fullScreenIntent.setAction("fullscreen_activity"); 224 fullScreenIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | 225 Intent.FLAG_ACTIVITY_NO_USER_ACTION); 226 notification.setFullScreenIntent(PendingIntent.getActivity(service, 227 instance.hashCode(), fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT), true); 228 notification.setPriority(NotificationCompat.PRIORITY_MAX); 229 230 clearNotification(service, instance); 231 service.startForeground(instance.hashCode(), notification.build()); 232 } 233 clearNotification(Context context, AlarmInstance instance)234 public static void clearNotification(Context context, AlarmInstance instance) { 235 LogUtils.v("Clearing notifications for alarm instance: " + instance.mId); 236 NotificationManagerCompat nm = NotificationManagerCompat.from(context); 237 nm.cancel(instance.hashCode()); 238 } 239 240 /** 241 * Updates the notification for an existing alarm. Use if the label has changed. 242 */ updateNotification(Context context, AlarmInstance instance)243 public static void updateNotification(Context context, AlarmInstance instance) { 244 switch (instance.mAlarmState) { 245 case AlarmInstance.LOW_NOTIFICATION_STATE: 246 showLowPriorityNotification(context, instance); 247 break; 248 case AlarmInstance.HIGH_NOTIFICATION_STATE: 249 showHighPriorityNotification(context, instance); 250 break; 251 case AlarmInstance.SNOOZE_STATE: 252 showSnoozeNotification(context, instance); 253 break; 254 case AlarmInstance.MISSED_STATE: 255 showMissedNotification(context, instance); 256 break; 257 default: 258 LogUtils.d("No notification to update"); 259 } 260 } 261 createViewAlarmIntent(Context context, AlarmInstance instance)262 public 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