Home | History | Annotate | Download | only in alarms
      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 
     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 
     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 
    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 
    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 
    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 
    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      */
    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 
    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