• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.calendar;
18 
19 import android.app.Notification;
20 import android.app.NotificationManager;
21 import android.app.PendingIntent;
22 import android.app.Service;
23 import android.content.BroadcastReceiver;
24 import android.content.ContentResolver;
25 import android.content.ContentValues;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.SharedPreferences;
29 import android.content.res.Resources;
30 import android.database.Cursor;
31 import android.net.Uri;
32 import android.os.PowerManager;
33 import android.preference.PreferenceManager;
34 import android.provider.Calendar.CalendarAlerts;
35 
36 /**
37  * Receives android.intent.action.EVENT_REMINDER intents and handles
38  * event reminders.  The intent URI specifies an alert id in the
39  * CalendarAlerts database table.  This class also receives the
40  * BOOT_COMPLETED intent so that it can add a status bar notification
41  * if there are Calendar event alarms that have not been dismissed.
42  * It also receives the TIME_CHANGED action so that it can fire off
43  * snoozed alarms that have become ready.  The real work is done in
44  * the AlertService class.
45  */
46 public class AlertReceiver extends BroadcastReceiver {
47     private static final String[] ALERT_PROJECTION = new String[] {
48         CalendarAlerts.TITLE,           // 0
49         CalendarAlerts.EVENT_LOCATION,  // 1
50     };
51     private static final int ALERT_INDEX_TITLE = 0;
52     private static final int ALERT_INDEX_EVENT_LOCATION = 1;
53 
54     private static final String DELETE_ACTION = "delete";
55 
56     static final Object mStartingServiceSync = new Object();
57     static PowerManager.WakeLock mStartingService;
58 
59     @Override
onReceive(Context context, Intent intent)60     public void onReceive(Context context, Intent intent) {
61         if (DELETE_ACTION.equals(intent.getAction())) {
62 
63             /* The user has clicked the "Clear All Notifications"
64              * buttons so dismiss all Calendar alerts.
65              */
66             // TODO Grab a wake lock here?
67             Intent serviceIntent = new Intent(context, DismissAllAlarmsService.class);
68             context.startService(serviceIntent);
69         } else {
70             Intent i = new Intent();
71             i.setClass(context, AlertService.class);
72             i.putExtras(intent);
73             i.putExtra("action", intent.getAction());
74             Uri uri = intent.getData();
75 
76             // This intent might be a BOOT_COMPLETED so it might not have a Uri.
77             if (uri != null) {
78                 i.putExtra("uri", uri.toString());
79             }
80             beginStartingService(context, i);
81         }
82     }
83 
84     /**
85      * Start the service to process the current event notifications, acquiring
86      * the wake lock before returning to ensure that the service will run.
87      */
beginStartingService(Context context, Intent intent)88     public static void beginStartingService(Context context, Intent intent) {
89         synchronized (mStartingServiceSync) {
90             if (mStartingService == null) {
91                 PowerManager pm =
92                     (PowerManager)context.getSystemService(Context.POWER_SERVICE);
93                 mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
94                         "StartingAlertService");
95                 mStartingService.setReferenceCounted(false);
96             }
97             mStartingService.acquire();
98             context.startService(intent);
99         }
100     }
101 
102     /**
103      * Called back by the service when it has finished processing notifications,
104      * releasing the wake lock if the service is now stopping.
105      */
finishStartingService(Service service, int startId)106     public static void finishStartingService(Service service, int startId) {
107         synchronized (mStartingServiceSync) {
108             if (mStartingService != null) {
109                 if (service.stopSelfResult(startId)) {
110                     mStartingService.release();
111                 }
112             }
113         }
114     }
115 
updateAlertNotification(Context context)116     public static void updateAlertNotification(Context context) {
117         // This can be called regularly to synchronize the alert notification
118         // with the contents of the CalendarAlerts table.
119 
120         ContentResolver cr = context.getContentResolver();
121 
122         if (cr == null) {
123             return;
124         }
125 
126         String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.FIRED;
127         Cursor alertCursor = CalendarAlerts.query(cr, ALERT_PROJECTION, selection, null);
128 
129         NotificationManager nm =
130                 (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
131 
132         if (alertCursor == null) {
133             nm.cancel(AlertActivity.NOTIFICATION_ID);
134             return;
135         }
136 
137         if (!alertCursor.moveToFirst()) {
138             alertCursor.close();
139             nm.cancel(AlertActivity.NOTIFICATION_ID);
140             return;
141         }
142 
143         // Check the settings to see if alerts are disabled
144         SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
145         String reminderType = prefs.getString(CalendarPreferenceActivity.KEY_ALERTS_TYPE,
146                 CalendarPreferenceActivity.ALERT_TYPE_STATUS_BAR);
147         if (reminderType.equals(CalendarPreferenceActivity.ALERT_TYPE_OFF)) {
148             return;
149         }
150 
151         String title = alertCursor.getString(ALERT_INDEX_TITLE);
152         String location = alertCursor.getString(ALERT_INDEX_EVENT_LOCATION);
153 
154         Notification notification = AlertReceiver.makeNewAlertNotification(context, title,
155                 location, alertCursor.getCount());
156         alertCursor.close();
157 
158         nm.notify(0, notification);
159     }
160 
makeNewAlertNotification(Context context, String title, String location, int numReminders)161     public static Notification makeNewAlertNotification(Context context, String title,
162             String location, int numReminders) {
163         Resources res = context.getResources();
164 
165         // Create an intent triggered by clicking on the status icon.
166         Intent clickIntent = new Intent();
167         clickIntent.setClass(context, AlertActivity.class);
168         clickIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
169 
170         // Create an intent triggered by clicking on the "Clear All Notifications" button
171         Intent deleteIntent = new Intent();
172         deleteIntent.setClass(context, AlertReceiver.class);
173         deleteIntent.setAction(DELETE_ACTION);
174 
175         if (title == null || title.length() == 0) {
176             title = res.getString(R.string.no_title_label);
177         }
178 
179         String helperString;
180         if (numReminders > 1) {
181             String format;
182             if (numReminders == 2) {
183                 format = res.getString(R.string.alert_missed_events_single);
184             } else {
185                 format = res.getString(R.string.alert_missed_events_multiple);
186             }
187             helperString = String.format(format, numReminders - 1);
188         } else {
189             helperString = location;
190         }
191 
192         Notification notification = new Notification(
193                 R.drawable.stat_notify_calendar,
194                 null,
195                 System.currentTimeMillis());
196         notification.setLatestEventInfo(context,
197                 title,
198                 helperString,
199                 PendingIntent.getActivity(context, 0, clickIntent, 0));
200         notification.deleteIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
201 
202         return notification;
203     }
204 }
205 
206