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.PendingIntent; 21 import android.app.Service; 22 import android.content.BroadcastReceiver; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.content.res.Resources; 26 import android.net.Uri; 27 import android.os.PowerManager; 28 import android.util.Log; 29 30 /** 31 * Receives android.intent.action.EVENT_REMINDER intents and handles 32 * event reminders. The intent URI specifies an alert id in the 33 * CalendarAlerts database table. This class also receives the 34 * BOOT_COMPLETED intent so that it can add a status bar notification 35 * if there are Calendar event alarms that have not been dismissed. 36 * It also receives the TIME_CHANGED action so that it can fire off 37 * snoozed alarms that have become ready. The real work is done in 38 * the AlertService class. 39 */ 40 public class AlertReceiver extends BroadcastReceiver { 41 private static final String TAG = "AlertReceiver"; 42 43 private static final String DELETE_ACTION = "delete"; 44 45 static final Object mStartingServiceSync = new Object(); 46 static PowerManager.WakeLock mStartingService; 47 48 @Override 49 public void onReceive(Context context, Intent intent) { 50 if (AlertService.DEBUG) { 51 Log.d(TAG, "onReceive: a=" + intent.getAction() + " " + intent.toString()); 52 } 53 54 if (DELETE_ACTION.equals(intent.getAction())) { 55 56 /* The user has clicked the "Clear All Notifications" 57 * buttons so dismiss all Calendar alerts. 58 */ 59 // TODO Grab a wake lock here? 60 Intent serviceIntent = new Intent(context, DismissAllAlarmsService.class); 61 context.startService(serviceIntent); 62 } else { 63 Intent i = new Intent(); 64 i.setClass(context, AlertService.class); 65 i.putExtras(intent); 66 i.putExtra("action", intent.getAction()); 67 Uri uri = intent.getData(); 68 69 // This intent might be a BOOT_COMPLETED so it might not have a Uri. 70 if (uri != null) { 71 i.putExtra("uri", uri.toString()); 72 } 73 beginStartingService(context, i); 74 } 75 } 76 77 /** 78 * Start the service to process the current event notifications, acquiring 79 * the wake lock before returning to ensure that the service will run. 80 */ 81 public static void beginStartingService(Context context, Intent intent) { 82 synchronized (mStartingServiceSync) { 83 if (mStartingService == null) { 84 PowerManager pm = 85 (PowerManager)context.getSystemService(Context.POWER_SERVICE); 86 mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, 87 "StartingAlertService"); 88 mStartingService.setReferenceCounted(false); 89 } 90 mStartingService.acquire(); 91 context.startService(intent); 92 } 93 } 94 95 /** 96 * Called back by the service when it has finished processing notifications, 97 * releasing the wake lock if the service is now stopping. 98 */ 99 public static void finishStartingService(Service service, int startId) { 100 synchronized (mStartingServiceSync) { 101 if (mStartingService != null) { 102 if (service.stopSelfResult(startId)) { 103 mStartingService.release(); 104 } 105 } 106 } 107 } 108 109 public static Notification makeNewAlertNotification(Context context, String title, 110 String location, int numReminders) { 111 return makeNewAlertNotification(context, title, location, 112 numReminders, false); 113 } 114 115 /** 116 * Creates an alert notification. If high priority, this will attach a pending intent. 117 * Otherwise, it creates a standard notification. 118 */ 119 public static Notification makeNewAlertNotification(Context context, 120 String title, String location, int numReminders, 121 boolean highPriority) { 122 Resources res = context.getResources(); 123 124 // Create an intent triggered by clicking on the status icon. 125 Intent clickIntent = new Intent(); 126 clickIntent.setClass(context, AlertActivity.class); 127 clickIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 128 129 // Create an intent triggered by clicking on the "Clear All Notifications" button 130 Intent deleteIntent = new Intent(); 131 deleteIntent.setClass(context, AlertReceiver.class); 132 deleteIntent.setAction(DELETE_ACTION); 133 134 if (title == null || title.length() == 0) { 135 title = res.getString(R.string.no_title_label); 136 } 137 138 String helperString; 139 if (numReminders > 1) { 140 String format; 141 if (numReminders == 2) { 142 format = res.getString(R.string.alert_missed_events_single); 143 } else { 144 format = res.getString(R.string.alert_missed_events_multiple); 145 } 146 helperString = String.format(format, numReminders - 1); 147 } else { 148 helperString = location; 149 } 150 151 PendingIntent pendingClickIntent = PendingIntent.getActivity( 152 context, 0, clickIntent, 0); 153 Notification notification = new Notification( 154 R.drawable.stat_notify_calendar, 155 null, 156 System.currentTimeMillis()); 157 notification.setLatestEventInfo(context, 158 title, 159 helperString, 160 pendingClickIntent 161 ); 162 notification.deleteIntent = PendingIntent.getBroadcast(context, 0, 163 deleteIntent, 0); 164 if (highPriority) { 165 notification.fullScreenIntent = pendingClickIntent; 166 } 167 168 return notification; 169 } 170 } 171 172